gpt4 book ai didi

C++ 新的放置运算符混淆了 Valgrind Memcheck

转载 作者:行者123 更新时间:2023-12-01 14:48:25 26 4
gpt4 key购买 nike

所以在我的程序中,我有一个连续的对象数组。我这样做是因为我想要这些对象中的每一个之间的空间局部性。它们非常小,位于一个非常大的数组中,并按顺序迭代。

因此我这样初始化它们

memoryPool = new Object[MAX_OBJECTS];

这当然会调用每个对象的默认初始化程序。我没有写默认初始化程序这完全没问题,因为它们将被覆盖。它们不能在一开始就被初始化为有效状态,因为它们需要在不同时间使用稍后生成的数据进行初始化。

因此有一个变量objectCount objectCount已使用有效的初始化程序进行初始化。何时增加 objectCount 变量

 assert(newObjectCount >= objectCount);
for (int i = objectCount; i < newObjectCount; i++) {
new(&(memoryPool[i])) Object(/*Calls the valid initializer of the class*/);
}
objectCount = newObjectCount;

这项技术使用了我发现的新布局 here .

所以你可以看到我像这样保持这些类之间的空间局部性。

可能有更好的方法来做到这一点,但我不知道有什么,我洗耳恭听。

现在进入实际问题。当使用 leak-check=full 通过 valgrind 运行时,这段代码会生成大量关于 Conditional jump or move depends on uninitialized value(s) 的输出。它总是在 Object 之一上对象。这种分配是否属于可能会导致 Memcheck 失效的“有趣的指针”?

最佳答案

第一个问题是你的情况memoryPool[i]已经包含一个有效对象,该对象被您的 placement-new 覆盖,而旧对象未被正确删除。

所以稍微好一点的方法是:

memoryPool[i].~Object();  // first destroy the obl object
new(&(memoryPool[i])) Object (...);

但是使用 placement new 应该是异常(exception)情况。如果只是替换对象,你不应该使用这种微妙的技术,而是使用简单的赋值:

memoryPool[i] = Object (...); // just replace the old object with a new one.  

当然,在这两种情况下你都应该尊重 rule of 3 .如果你不愿意,取决于 Object 的成员,你仍然可以泄漏内存。

最后,另一个问题:因为你分配了一个动态数组,你需要 delete the array以及当您不再需要它时:

delete[] memoryPool;   // note the []

一个更灵活和稳健的方法是使用 vector<Object>这将允许 memoryPool动态地增长和收缩,将您从内存管理的职责中解放出来。此外,您可以根据需要使用 emplace_back() 构造和添加元素。

关于C++ 新的放置运算符混淆了 Valgrind Memcheck,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60906453/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com