从函数返回的结构的C ++指针导致访问冲突

时间:2015-01-15 15:53:26

标签: c++ pointers

我是C ++的新手。我使用Visual Studio。我的调试版本按预期工作,但发布版本因访问冲突而崩溃。 结构:

struct GeneticData
{
    int NumberOfIdDataPairs;
    char** IdBuffer;
    char** DataBuffer;
};

IdBuffer是一个包含20个字符的char数组数组,Databuffer是一个包含102个字符的字符数组数组。 返回指针的函数:

GeneticData* LoadData(FILE* dataFilePtr) //dataFilePtr is valid in the function
{
    char* result = NULL;
    int fileLine = 0;
    GeneticData geneticData = *new GeneticData();

    geneticData.NumberOfIdDataPairs = *new int;
    geneticData.IdBuffer = new char*[gSizeOfBuffer];
    geneticData.DataBuffer = new char*[gSizeOfBuffer];

    for (int i = 0; i < gSizeOfBuffer; i++)
    {
        geneticData.IdBuffer[i] = new char[gSizeOfId];
        geneticData.DataBuffer[i] = new char[gSizeOfData];
    }

    do
    {
        result = fgets(geneticData.IdBuffer[fileLine], gSizeOfId, dataFilePtr);
        fgets(geneticData.DataBuffer[fileLine], gSizeOfData, dataFilePtr);
        fileLine++;
    } while (result != NULL && fileLine < gSizeOfBuffer);

    if (result != NULL)
        geneticData.NumberOfIdDataPairs = fileLine;
    else
        geneticData.NumberOfIdDataPairs = fileLine - 1;

    return &geneticData;
}

gSizeofBuffer是id / data对的数量,目前它的值是1.000.000。 在函数内部一切都很好,我可以访问id / dataBuffer的值。问题出现在调用我的LoadData函数的函数中。

GeneticData geneticData;
geneticData = *LoadData(dataFilePtr);
//acces violation, geneticData contained invalid values

使用cout << geneticData.DataBuffer[1]调试器在这里停止(事后调试): enter image description here

使用cout << geneticData.DataBuffer[1][0]调试器在此行停止。在分析DataBuffer内容的实际算法中,调试器就像cout&lt;&lt; geneticData.DataBuffer[1][0]。 我将GeneticData结构的内存分配为动态内存,我不明白为什么在LoadData函数返回后指针无效。

3 个答案:

答案 0 :(得分:5)

你正在返回一个指向临时结构的指针:

GeneticData geneticData = *new GeneticData(); // memoryleak: copies from dynamic memory into local
...
return &geneticData; // returns address of local memory

如果要初始化本地结构,请写:

GeneticData geneticData; // calls the default constructor GeneticData() to initialise geneticData

请注意geneticData仅在范围结束前有效,因此是该变量的地址!

如果需要动态内存写:

GeneticData* pGeneticData = new GeneticData(); // allocates dynamic memory (new), calls the default constructor and assigns the memory address to the pointer pGeneticData

答案 1 :(得分:4)

GeneticData geneticData = *new GeneticData();

这个怪物动态地分配一个对象,使用它来复制初始化一个局部变量,然后抛弃唯一的指针,导致内存泄漏。

return &geneticData;

这将返回一个指向局部变量的指针,该局部变量在调用者可以执行任何操作之前被销毁;导致你的错误。

也许您想要返回动态对象(记得在使用完它后删除它):

GeneticData * geneticData = new GeneticData();
//...
return geneticData;

或者您希望按值返回对象:

GeneticData LoadData(FILE* dataFilePtr)
{
    GeneticData geneticData;
    //...
    return geneticData;
}

但你应该帮自己一个忙,不要乱用指针和new。使用std::vector作为缓冲区。

答案 2 :(得分:2)

你必须替换

GeneticData geneticData = *new GeneticData();

通过

GeneticData* geneticData = new GeneticData(); // we define a pointer now

return &geneticData;

通过

return geneticData; // return the pointer

但是,除非你真的知道自己在做什么,否则尽量避免使用原始指针。