在 C++ 中删除多维结构会导致访问冲突

Posted

技术标签:

【中文标题】在 C++ 中删除多维结构会导致访问冲突【英文标题】:Deleting multidimensional structs in C++ leads to access violations 【发布时间】:2015-08-03 20:17:42 【问题描述】:

我有一个指向其他结构的结构。例如,我的结构遵循与此类似的模式(尽管它们要复杂得多)。

typedef struct parent

    string name;
    int numOfKids;
    child* children;
  parent

typedef struct child

    string name;
    details* information;
  child

typedef struct details

    int age;
    string bestFriend;
  details

要创建一组父母,我执行以下操作:

Parents * parents = new parents[numParents];
for(int i = 0; i< numParents; i++)

   parents[i].children = new children[parents[i].numOfKids];
   for (int j = 0; j < parents[i].numOfKids; j++)
   
       parents[i].children[j].information = ( details* )malloc( sizeof( details ) );
       memset( parents[i].children[j].details, 0, sizeof( details ) );
   

后来我试图像这样清理内存:

void clearParents(parents** pParents, int numParents)

    for(int i = 0; i< numParents)
    
        for(int j = 0; j< pParents[i]->numOfKids; j++)
        
            free(pParents[i]->children[j].details);
        

        delete [] pParents[i]->children
        delete( pParents[i])
     

这个 clearParents 函数似乎在第一次循环时可以正常工作,但是在返回到内部循环时,它会崩溃

for (int j = 0; j < parents[i].numOfKids; j++)

出现错误:0xC0000005 访问冲突读取位置 0xCCCCCCD4

我猜这与我释放/删除父母数组中的内存有关,同时还尝试继续循环遍历它,但我不确定如何解决问题。

提前感谢您提供的任何见解

【问题讨论】:

omg 为什么所有的数组和new 和指针?是什么设计决定导致了这种情况? 调试!!启动调试器,单步调试代码的每一行,观察变量如何变化。完成此操作之前不要在这里问! 不要将new[]delete 混用 @LightnessRacesinOrbit 很遗憾,这不是我的决定。我实际上使用的是 NvAPI,结构代表了 Nvidia 构建的结构。如果您想查看我的实际分配情况,您可以在此处的答案中看到一个示例:***.com/a/12012589/2252761 遗憾的是,Nvidia 没有提供任何关于如何在完成后释放内存的文档,并且我不想把整个结构放在这里,因为如果你以前没有看过它会很吓人。 如果你使用 std::vector,你的很多问题都会消失 【参考方案1】:

您对双指针pParents 感到困惑。您的解除分配模式与分配模式不匹配。我猜你真的想要这样的东西

void clearParents(parents* pParents, int numParents)

    for(int i = 0; i< numParents; ++i)
    
        for(int j = 0; j< pParents[i].numOfKids; j++)
        
            free(pParents[i].children[j].details);
        
        delete[] pParents[i].children;
     
     delete[] pParents;

【讨论】:

遗憾的是我无法更改双指针,因为这只是我真实代码的一个示例。正如我在之前的评论中提到的,我实际上使用的是 Nvidia 的 API,这些结构是 Nvidia 调用所需结构的简化版本。双指针还在,delete[] pParents[i] 还能用吗? @LightnessRacesinOrbit 他的例子中的方法头有“parents* pParents”,在我的例子中它有“parents** pParents”。也许我很困惑,但在我看来,他正在删除双指针,而不是最后一次删除,使所有“->”变成“。”如果设计取决于我,我会做这样,但双指针不在我的手中 @TrolliOlli 是的,我现在看到了。虽然我仍然不明白为什么你认为你“需要”双指针。只需在进入函数的途中取消引用一次............ 即使使用双指针 delete[] pParents[i] 也是错误的,因为您分配了一次但删除了 numParents 次。当我说你的释放模式与分配模式不匹配时,这就是我的意思。如果你必须有一个双指针,那么也许你需要delete[] *pParents;?还有free((*pParents)[i].children[j].details);delete[] (*pParents)[i].children; 但只是猜测而已。 @john 哦,好吧,这更有意义!但是,我仍然收到错误(即使我删除了整行),所以看起来错误来自 children 或 children[j].details 的内部删除之一。【参考方案2】:

您将new[]delete 混合在一起。 pParents 是使用 new[] 声明的,因此您需要在最外面的 for 循环末尾使用 delete[] 将其删除。您不应该尝试删除外部 for 循环中的每个元素。

【讨论】:

以上是关于在 C++ 中删除多维结构会导致访问冲突的主要内容,如果未能解决你的问题,请参考以下文章

C++ - 使用 std::sort 对结构向量进行排序导致读取访问冲突

访问冲突 C++(删除向量中的项目)

新/删除导致访问冲突

编写从 C++ 应用程序链接的 Delphi DLL:访问 C++ 接口成员函数会导致访问冲突

当我尝试删除数组时,C++ 访问冲突读取位置 0xDDDDDDCD 已更新

从非托管 C++ 调用 WCF 服务会导致访问冲突