سؤال

كان منذ سنوات قليلة كتبت C/C++, و الآن أنا أواجه مشكلة أنا فقط لا يمكن أن يبدو أن حل في بلدي.

نظرا التالية البنية:

struct InputData
{
    float diameter;
    float length;
    int vertIndex;
    struct InputData *parent;
    vector<InputData*> children;
    bool deadEnd;

    InputData(float dia, float lngth)
    {
        diameter = dia;
        length = lngth;
        vertIndex = NULL;
        parent = NULL;
        deadEnd = false;
    }
};

لا تبدأ من خلال تحديد عدد من العقد ، الأم/الطفل العلاقة:

InputData i0 = InputData(3.0f, 3.0f);
InputData i1 = InputData(2.0f, 2.0f);
InputData i2 = InputData(1.0f, 1.0f);
InputData i3 = InputData(1.0f, 1.0f);
InputData i4 = InputData(1.0f, 1.0f);
InputData i5 = InputData(1.01f, 0.5f);

i0.children.push_back(&i1);
i1.children.push_back(&i2);
i2.children.push_back(&i3);
i3.children.push_back(&i4);
i4.children.push_back(&i5);

i1.parent = &i0;
i2.parent = &i1;
i3.parent = &i2;
i4.parent = &i3;
i5.parent = &i4;

علما بأن i5 فقط في العقد ليس لديها أي أطفال.

ثم ننتقل إلى القيام ببعض العمل باستخدام هذه البيانات (الدعوة BuildMeshVertices(&i0, &القمم) من main ()) ، و في نهاية المطاف مضيفا الطفل i5:

void BuildMeshVertices(InputData* current, vector<SimpleVertex> *vertices)
{
    //Do work

    if(current->children.size() == 1)
    {
        BuildMeshVertices(current->children[0], vertices);
    }
    else if(current->children.size() == 0 && current->deadEnd == false)
    {
        InputData iDeadEnd = InputData(1.01f, 0.5f);
        iDeadEnd.deadEnd = true;
        iDeadEnd.parent = current;
        current->children.push_back(&iDeadEnd);     

        BuildMeshVertices(&iDeadEnd, vertices);
    }
}

وبعد ذلك كل شيء على ما يرام.i0 لديها طفل واحد (i1), i1 لديها طفل واحد (i2), و هكذا دواليك و i5 الآن لديها طفل أيضا.

أدعو وظيفة أخرى (BuildMeshIndices ()) ، و فجأة بضعة أسطر في هذه الوظيفة (خط) 63 البيانات المضافة حديثا الطفل i5 يتم الكتابة فوقها.i5 لا يزال يشير إلى حق الطفل ، ولكن البيانات لهذا الطفل فجأة مشوه.

وهنا لقطة قبل وبعد (آسف على الرابط لكنني لم يسمح لهم استخدام العلامات IMG)

أنا لا يمكن معرفة لماذا يحدث هذا ولكن لدي شعور انها حصلت على أن تفعل شيئا مع ضعف الذاكرة الإدارة ؟

التحديث كما أنه لا يجب أن يتم بهذه الطريقة.إذا كان على سبيل المثال تغيير الأطفال ناقل إلى ناقل من القيم هو المفضل C++ الطريقة ، أنا أفضل أن.حاولت التعليق على الأجوبة, ولكن لست متأكدا من أنكم رؤية التعليقات (حسب التعليمات تحتاج 50 سمعة ترك تعليقات)?

أدناه هو رمز مصدر الكامل (مع كل شيء لا لزوم لها تجريده ، ولكن يكفي أن إعادة إنشاء الخطأ):

#include "stdafx.h"
#include <vector>

using std::vector;

struct InputData
{
    float diameter;
    float length;
    int vertIndex;
    struct InputData *parent;
    vector<InputData*> children;
    bool deadEnd;

    InputData(float dia, float lngth)
    {
        diameter = dia;
        length = lngth;
        vertIndex = NULL;
        parent = NULL;
        deadEnd = false;
    }
};

//--------------------------------------------------------------------------------------
// Vertex types
//--------------------------------------------------------------------------------------
struct SimpleVertex
{
    float Pos;

    SimpleVertex(float Position)
    {
        Pos = Position;
    }
};

void BuildMeshVertices(InputData* current, vector<SimpleVertex> *vertices)
{
    current->vertIndex = vertices->size();

    //Add vertices..

    if(current->children.size() == 1)
    {
        BuildMeshVertices(current->children[0], vertices);
    }
    else if(current->children.size() == 0 && current->deadEnd == false)
    {
        InputData iDeadEnd = InputData(1.01f, 0.5f);
        iDeadEnd.deadEnd = true;
        iDeadEnd.parent = current;
        current->children.push_back(&iDeadEnd);     

        BuildMeshVertices(&iDeadEnd, vertices);
    }
}

void BuildMeshIndices(InputData* current, vector<unsigned long> *indices)
{
    indices->push_back(current->vertIndex+2);
    indices->push_back(current->vertIndex+0);
    indices->push_back(current->vertIndex+1);
    indices->push_back(current->vertIndex+3);
    indices->push_back(current->vertIndex+0);
    indices->push_back(current->vertIndex+2);

    InputData *parent = current->parent;

    unsigned long vOffset;

    if(parent != NULL && parent->children.size() == 1)
    {   
        vOffset = (unsigned long)current->vertIndex;

        indices->push_back(vOffset+7);
        indices->push_back(vOffset+5);
        indices->push_back(vOffset+4);
        indices->push_back(vOffset+6);
        indices->push_back(vOffset+5);
        indices->push_back(vOffset+7);

        indices->push_back(vOffset+10);
        indices->push_back(vOffset+8);
        indices->push_back(vOffset+9);
        indices->push_back(vOffset+11);
        indices->push_back(vOffset+8);
        indices->push_back(vOffset+10);

        indices->push_back(vOffset+15);
        indices->push_back(vOffset+13);
        indices->push_back(vOffset+12);
        indices->push_back(vOffset+14);
        indices->push_back(vOffset+13);
        indices->push_back(vOffset+15);

        indices->push_back(vOffset+18);
        indices->push_back(vOffset+16);
        indices->push_back(vOffset+17);
        indices->push_back(vOffset+19);
        indices->push_back(vOffset+16);
        indices->push_back(vOffset+18);
    }

    if(current->children.size() == 1 && current->deadEnd == false)
    {
        BuildMeshIndices(current->children[0], indices);
    }
}

int _tmain(int argc, _TCHAR* argv[])
{
    InputData i0 = InputData(3.0f, 3.0f);
    InputData i1 = InputData(2.0f, 2.0f);
    InputData i2 = InputData(1.0f, 1.0f);
    InputData i3 = InputData(1.0f, 1.0f);
    InputData i4 = InputData(1.0f, 1.0f);
    InputData i5 = InputData(1.01f, 0.5f);

    i0.children.push_back(&i1);
    i1.children.push_back(&i2);
    i2.children.push_back(&i3);
    i3.children.push_back(&i4);
    i4.children.push_back(&i5);

    i1.parent = &i0;
    i2.parent = &i1;
    i3.parent = &i2;
    i4.parent = &i3;
    i5.parent = &i4;

    // Create vertex buffer
    vector<SimpleVertex> vertices;

    BuildMeshVertices(&i0, &vertices);

    // Create index buffer
    vector<unsigned long> indices;

    BuildMeshIndices(&i0, &indices);

    return 0;
}
هل كانت مفيدة؟

المحلول

تغيير الخام مؤشرات المؤشرات الذكية وسوف تحصل على ركوب من مشاكل إدارة الذاكرة.

أنت لا تحتاج إلى نسخ كل دفعة إلى المشروع المطلوب فقط رؤوس.

#include <vector>
#include <boost/shared_ptr.hpp>
#include <boost/weak_ptr.hpp>

struct InputData
{
    float diameter;
    float length;
    unsigned long vertIndex;
    boost::weak_ptr<InputData> parent;
    std::vector< boost::shared_ptr<InputData> > children;
    bool deadEnd;

    InputData(float dia, float lngth, boost::weak_ptr<InputData> p = boost::weak_ptr<InputData>(), bool de = false)
        : diameter(dia), length(lngth), vertIndex(0), parent(p), deadEnd(de) {}
};

struct SimpleVertex
{
    float Pos;

    SimpleVertex(float position) : Pos(position) {}
};

void BuildMeshVertices(boost::shared_ptr<InputData> current, std::vector<SimpleVertex>& vertices)
{
    current->vertIndex = vertices.size();

    //Add vertices..
    if(current->children.size() == 1)
    {
        BuildMeshVertices(current->children[0], vertices);
    }
    else if(current->children.size() == 0 && current->deadEnd == false)
    {
          // this was a stack variable, so the pointer became invalid when going out of ambit.
        boost::shared_ptr<InputData> iDeadEnd( new InputData(1.01f, 0.5f, current, true) );
        current->children.push_back(iDeadEnd);         

        BuildMeshVertices(iDeadEnd, vertices);
    }
}

void BuildMeshIndices(boost::shared_ptr<InputData> current, std::vector<unsigned long>& indices)
{
    unsigned long vi = current->vertIndex;
    unsigned long  ioffset[] = { vi+2, vi, vi+1, vi+3, vi, vi+2};
    indices.insert(indices.end(), ioffset, ioffset+6);

    boost::shared_ptr<InputData> parent = current->parent.lock();
    if (parent && parent->children.size() == 1)
    {   
        unsigned long offs = current->vertIndex;
          unsigned long voffset[] = 
          { offs+7, offs+5, offs+4, offs+6, offs+5, offs+7,
            offs+10, offs+8, offs+9, offs+11, offs+8, offs+10,
            offs+15, offs+13, offs+12, offs+14, offs+13, offs+15,
            offs+18, offs+16, offs+17, offs+19, offs+16, offs+18 };
          indices.insert(indices.end(), voffset, voffset+24);
    }

    if(current->children.size() == 1 && current->deadEnd == false)
    {
        BuildMeshIndices(current->children[0], indices);
    }
}

int main()
{
    boost::shared_ptr<InputData> i0( new InputData(3.0f, 3.0f) );
    boost::shared_ptr<InputData> i1( new InputData(2.0f, 2.0f) );
    boost::shared_ptr<InputData> i2( new InputData(1.0f, 1.0f) );
    boost::shared_ptr<InputData> i3( new InputData(1.0f, 1.0f) );
    boost::shared_ptr<InputData> i4( new InputData(1.0f, 1.0f) );
    boost::shared_ptr<InputData> i5( new InputData(1.01f, 0.5f) );

    i0->children.push_back(i1);
    i1->children.push_back(i2);
    i2->children.push_back(i3);
    i3->children.push_back(i4);
    i4->children.push_back(i5);

    i1->parent = i0;
    i2->parent = i1;
    i3->parent = i2;
    i4->parent = i3;
    i5->parent = i4;

    // Create vertex buffer
    std::vector<SimpleVertex> vertices;
    BuildMeshVertices(i0, vertices);

    // Create index buffer
    std::vector<unsigned long> indices;
    BuildMeshIndices(i0, indices);

    return 0;
}

أعتقد أنك لا تزال لديها نصف C, نصف C++ رمز القذرة...يجب عليك أن تختار اللغة.

نصائح أخرى

كنت تدفع المؤشر إلى كومة الكائن في ناقلات.بمجرد تنفيذ يترك نطاق هذا كومة الكائن سوف تحصل على تدمير الذاكرة سيتم استخدامها ، مما أدى إلى قيمة وهمية.محاولة

InputData *iDeadEnd = new InputData(1.01f, 0.5f);
iDeadEnd->deadEnd = true;
iDeadEnd->parent = current;
current->children.push_back(iDeadEnd);

ثم سيكون لديك لتحرير الذاكرة في الوقت المناسب.

يجب عليك استخدام الذاكرة الديناميكية في العمل مع المؤشرات. InputData سوف يتم تدميرها عند الخروج من الدالة BuildMeshVertices, لذا فإن البيانات ستكون garbaged أو سوف تحصل على ذاكرة استثناء.

يجب أن تفعل شيئا مثل

InputData * iDeadEnd = new InputData(1.01f, 0.5f);

بدلا من

InputData iDeadEnd = InputData(1.01f, 0.5f);

أنت المثيلات iDeadEnd على المكدس ، وأخذ مؤشر إلى عنوان كومة!عندما مهام إنهاء و كومة بالمرافعة ، بيانات iDeadEnd هو الذهاب الى تشويش.

InputData *iDeadEnd = new InputData(1.01f, 0.5f);
iDeadEnd->deadEnd = true;
iDeadEnd->parent = current;
current->children.push_back(iDeadEnd);         

BuildMeshVertices(iDeadEnd, vertices);

المشكلة لديك الآن هو أن الذاكرة iDeadEnd يحتاج إلى صراحة deallocated عندما كنت فعلت مع ذلك.

لحظة الخاص بك BuildMeshVertices وظيفة مخارج ثم iDeadEnd (i5 الطفل) هو فككت لأنك أعلنت على كومة من الخروج من وظيفة كاملة الإطار المكدس هو إبطال كل كائن تفكيكه.إما أنك ترغب في تخصيص حيوي iDeadEnd أو جذريا إعادة التفكير في كيفية تعريف شجرة.من الأفضل وجود كل البنية عقد ناقل InputData (لا InputData*) ثم وضع لهم على النحو التالي:

InputData i0 = InputData(3.0f, 3.0f);
i0.children.push_back( InputData( 2.0f, 2.0f ) );
i0.children[0].children.push_back( InputData( 1.0f, 1.0f ) );

الخ

حتى بعيد عن المثالية لأسباب واضحة.تعريف شجرة من عناصر أبدا أكثر متعة من الأشياء القيام به مع ذلك.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top