是否有可能以纪念内存“出界”,这样的堆管理器不从它分配一个段?(Is it possible to

2019-09-26 01:08发布

今天早些时候,我问这个问题 。

花一些时间来调查这个问题之后,我发现这是怎么回事。 因为我觉得这是很有趣,足以跟踪作为一个单独的问题我张贴这是一个新问题。 我会更新的答案(和这一个链接)这个问题。

启动从调试器单元测试

// 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分配的Objectdelete荷兰国际集团先前的Object分配一个新的前)总是在内存中返回相同的地址。
  • 当从调试器启动单元测试,随后将呼叫new分配的Objectdelete荷兰国际集团先前的Object分配一个新的前)总是在内存中返回一个唯一的地址。

问题是,由于分配Object总是在内存中通过命令行启动时,会得到相同的地址仍然可以使用的地图,我访问已存储的指针和测试将不会崩溃。 但我想我的单元测试崩溃时的缺陷修复不到位,以确保它不会默默地消失,缺陷不回来。

有2个部分,我的问题:

  1. 在命令行推出的单元测试时,为什么要堆管理器重复使用相同的内存部分,但不是当我从调试器启动单元测试?

  2. 是否有一个编译器设置,我可以在我的测试工具使用,或者我可以调用,以防止堆管理器从我已删除的内存的一部分,让我正确地写我的单元测试重新使用的方法? 1


1个显然,这样做的一个方法是不删除原来的对象,而是分配该代码的部分是我的生产代码,我这样做会导致内存泄漏。

Answer 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


Answer 2:

你可以更换new ,并delete与自己的版本是有你想要的行为。



Answer 3:

首先的 - 而不是一个“正常”的内存管理器。 一旦你释放内存你通过它的所有权的内存管理器,而后者可以重复使用它。

你可以写一个自定义的经理为用户安德烈亚斯Brinck建议,但是那会是什么? 它不会从空气手艺的内存,它从什么地方像CRT堆或操作系统堆请求它。

方案A.它不会返回内存底层堆 - 你将有一个泄漏和内存块仍将被映射到地址空间,这将是访问。

当你mananger尝试分配内存再次底层堆可以再次返回该块然后 - 方案B.它会返回内存底层堆。 此外你不知道你什么时候回内存给它的底层堆做什么。 这可能使未映射与否 - 所以访问内存可能会崩溃与否。

底线是,你就完蛋了。 试图测试未定义行为不会是非常有成效的。



Answer 4:

这是不确定的行为的一个例子。 无论是C ++或堆管理器定义存储将如何分配。 你可以不依赖于任何记忆被重用或不被重用。 当你做这样的事在上面,没有办法确定或更改返回的指针是否会从第一个分配的不同。



文章来源: Is it possible to mark a segment of memory as “out of bounds” so the heap manager doesn't allocate from it?