今天早些时候我问了this question .
在花了一些时间调查这个问题后,我发现了这是怎么回事。我将其作为一个新问题发布,因为我认为它很有趣,可以作为一个单独的问题进行跟踪。我将用答案更新该问题(以及指向该问题的链接)。
从调试器启动单元测试
// Construct object
Object* pObject = new Object(...);
// Pointer value of pObject == 0x05176960
// Lots of other code
// ...
// Destroy object
delete pObject;
// Construct object again
pObject = new Object(...);
// Pointer value of pObject == 0x05560194 /* Different memory location */
从命令行启动单元测试
// Construct object
Object* pObject = new Object(...);
// Pointer value of pObject == 0x05176960
// Lots of other code
// ...
// Destroy object
delete pObject;
// Construct object again
pObject = new Object(...);
// Pointer value of pObject == 0x05176960 /* Same memory location */
总结:
- 从命令行启动单元测试时,随后调用
new
分配对象
(删除
在分配一个新对象之前先调用之前的Object
)总是返回内存中的相同地址。 - 从调试器启动单元测试时,随后调用
new
分配对象
(删除
在分配新对象之前调用先前的Object
)始终返回内存中的唯一地址。
问题是因为 Object
的分配在通过命令行启动时总是在内存中获得相同的地址,我正在访问的 map 存储了旧指针仍然可以使用,测试不会崩溃。但我希望我的单元测试在缺陷修复未到位时崩溃,以确保它不会无声地失败并且缺陷不会再次出现。
我的问题分为两部分:
为什么堆管理器会在从命令行启动单元测试时重新使用相同的内存部分,而当我从调试器启动单元测试时却不会?
是否有我可以在我的测试工具上使用的编译器设置,或者我可以调用的方法来防止堆管理器重新使用我已删除的内存部分,以允许我正确地编写我的单元测试? 1
1显然,一种方法是不删除原始对象,但分配它的代码部分在我的生产代码中,我这样做会导致内存泄漏。
最佳答案
您的单元测试存在缺陷,因为它依赖于未定义的行为。您应该重写您的单元测试,使其不依赖于未定义的行为,在这种情况下,无论内存管理器如何决定分配内存,它都会始终通过。
你正在做的是这样的:
Object* pObject = new Object(...);
...
delete pObject;
pObject = new Object(...);
// Use dangling pointer to first object, and if it crashes, the unit test fails
// This is WRONG since a crash isn't guaranteed
您应该改为重构单元测试,使其像这样工作:
Object* pObject = new Object(...);
...
// Check to see if there are dangling references to pObject right before we
// delete it. If there are, assert() and fail the unit test.
assert(NoDanglingReferences(pObject));
delete pObject;
// Continue on with more tests
关于c++ - 是否可以将一段内存标记为 "out of bounds",以便堆管理器不从中分配内存?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4274058/