Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/162.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 是否可以将内存段标记为;“禁止入内”;因此堆管理器不会';你不能从中分配吗?_C++_Unit Testing_Dynamic Memory Allocation_Heap Memory - Fatal编程技术网

C++ 是否可以将内存段标记为;“禁止入内”;因此堆管理器不会';你不能从中分配吗?

C++ 是否可以将内存段标记为;“禁止入内”;因此堆管理器不会';你不能从中分配吗?,c++,unit-testing,dynamic-memory-allocation,heap-memory,C++,Unit Testing,Dynamic Memory Allocation,Heap Memory,今天早些时候我问 在花了一些时间调查这个问题之后,我发现了正在发生的事情。我将此作为一个新问题发布,因为我认为它足够有趣,可以作为一个单独的问题进行跟踪。我将用答案更新这个问题(以及这个问题的链接) 从调试器启动单元测试 // Construct object Object* pObject = new Object(...); // Pointer value of pObject == 0x05176960 // Lots of other code // ... // Destroy

今天早些时候我问

在花了一些时间调查这个问题之后,我发现了正在发生的事情。我将此作为一个新问题发布,因为我认为它足够有趣,可以作为一个单独的问题进行跟踪。我将用答案更新这个问题(以及这个问题的链接)

从调试器启动单元测试

// 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
    以分配
    对象
    delete
    在分配新对象之前删除前一个
    对象)始终在内存中返回相同的地址
  • 调试器启动单元测试时,后续调用
    new
    以分配
    对象
    delete
    在分配新对象之前删除之前的
    对象)始终在内存中返回唯一地址
问题在于,由于通过命令行启动时,
Object
的分配总是在内存中获得相同的地址,因此我正在访问的存储了旧指针的映射仍然可以使用,并且测试不会崩溃。但是我希望我的单元测试在缺陷修复不到位时崩溃,以确保它不会悄悄地失败,并且缺陷不会再次出现

我的问题分为两部分:

  • 为什么堆管理器在从命令行启动单元测试时会重复使用相同的内存部分,而在我从调试器启动单元测试时却不会重复使用相同的内存部分

  • 我是否可以在测试工具上使用编译器设置,或者调用一种方法来防止堆管理器重新使用已删除的内存部分,以允许我正确编写单元测试?一,



  • 1执行此操作的一个明显方法是不删除原始对象,但分配此对象的代码部分在我的生产代码中,我这样做会导致内存泄漏。

    这是一个未定义行为的示例。无论是C++还是堆管理器都不知道如何分配内存。您不能依赖内存被重用或不被重用。执行上述操作时,无法确定或更改返回的指针是否与第一个分配的指针不同。

    这是未定义行为的示例。无论是C++还是堆管理器都不知道如何分配内存。您不能依赖内存被重用或不被重用。当你像上面那样做的时候,无法确定或更改返回的指针是否与第一个分配的指针不同。

    您可以使用具有所需行为的自己版本替换
    新建
    删除

    您可以使用具有所需行为的自己版本替换
    新建
    删除
    您想要的行为。

    您的单元测试是有缺陷的,因为它依赖于未定义的行为。您应该重写单元测试,使其不依赖于未定义的行为,在这种情况下,无论内存管理器决定如何分配内存,单元测试都将通过

    您正在做的是:

    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
    

    您的单元测试是有缺陷的,因为它依赖于未定义的行为。您应该重写单元测试,使其不依赖于未定义的行为,在这种情况下,无论内存管理器决定如何分配内存,单元测试都将通过

    您正在做的是:

    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
    
    首先-不在“正常”内存管理器中。释放内存后,您将其所有权传递给内存管理器,后者可以重用它

    你可以按照建议去做,但它会做什么呢?它不是从空中制造内存,而是从CRT堆或操作系统堆之类的地方请求内存

    场景A。它不会将内存返回到底层堆-您将有一个泄漏,内存块仍将映射到地址空间,并且可以访问

    场景B。它会将内存返回到底层堆-然后,当管理者尝试再次分配内存时,底层堆可以再次返回该块。而且,当您将内存返回到底层堆时,您不知道它会做什么。它可能会使其未映射或不映射-因此访问内存可能会崩溃或不崩溃

    底线是你完蛋了。尝试测试未定义的行为不会很有成效。

    首先,在“正常”内存管理器中不会。释放内存后,您将其所有权传递给内存管理器,后者可以重用它

    你可以按照建议去做,但它会做什么呢?它不是从空中制造内存,而是从CRT堆或操作系统堆之类的地方请求内存

    场景A。它不会将内存返回到底层堆-您将有一个泄漏,内存块仍将映射到地址空间,并且可以访问

    场景B。它会将内存返回到底层堆-然后,当管理者尝试再次分配内存时,底层堆可以再次返回该块。而且,当您将内存返回到底层堆时,您不知道它会做什么。它可能会使其未映射或不映射-因此访问内存可能会崩溃或不崩溃


    底线是你完蛋了。尝试测试未定义的行为不会有很大成效。

    同意,我的测试依赖于未定义的行为。实际上,它做它需要做的事情,并且(基于我100次的样本量),它总是在需要的时候中止。你可以:1/typedef指向另一个类型的指针(shared_ptr),2/重载操作符t的地址