gpt4 book ai didi

C++ operator delete override 并不总是被使用

转载 作者:行者123 更新时间:2023-11-30 05:02:43 24 4
gpt4 key购买 nike

我有一些使用谷歌测试的 C++ 单元测试。将一些代码放在一起以覆盖新/删除运算符以检查单元测试中的泄漏。虽然有一个问题。一些 google test new/deletes 使用我重写的方法,但有些没有,所以我在跟踪代码中得到错误的错误——有时看到内存泄漏,即使它真的被删除了,有时看到 malloc 返回

这是我最小的新建/删除覆盖(仅打印地址以供手动检查):

void * operator new(size_t size)
{
void * addr = malloc(size);
std::cout << " tracking create: " << addr << "(size " << size << ")" << std::endl;
return addr;
}
void * operator new[](size_t size)
{
void * addr = malloc(size);
std::cout << " tracking create: " << addr << "(size " << size << ")" << std::endl;
return addr;
}

void operator delete(void * addr) noexcept
{
std::cout << " tracking delete: " << addr << std::endl;
free(addr);
}

void operator delete[](void * addr) noexcept
{
std::cout << " tracking delete: " << addr << std::endl;
free(addr);
}

这里是谷歌测试线,它没有经过我覆盖的删除 (gtest-port.h):

void reset(T* p = NULL) {
if (p != ptr_) {
if (IsTrue(sizeof(T) > 0)) { // Makes sure T is a complete type.
delete ptr_;
}
ptr_ = p;
}
}

当我在 gdb 中的 delete ptr_ 行中断时,然后 step,它直接进入 ptr_ = p 行,所以没有其他东西覆盖它删除。

我将 gtest 构建为存档文件,并在构建单元测试时将其链接进来。以防万一:我正在使用 cygwin 使用 mingw 构建 Windows。

这是一个最小的例子,2 个文件 min.cpp 和 minmain.cpp。这是 min.cpp:

#include <iostream>
#include <string>

// Overload the new/delete operators to check for memory errors
void * operator new(size_t size)
{
void * addr = malloc(size);
std::cout << " tracking create: " << addr << "(size " << size << ")" << std::endl;
return addr;
}
void * operator new[](size_t size)
{
void * addr = malloc(size);
std::cout << " tracking create: " << addr << "(size " << size << ")" << std::endl;
return addr;
}

void operator delete(void * addr) noexcept
{
std::cout << " tracking delete: " << addr << std::endl;
free(addr);
}

void operator delete[](void * addr) noexcept
{
std::cout << " tracking delete: " << addr << std::endl;
free(addr);
}

minmain.cpp:

#include "gtest/gtest.h"

TEST(MinTest, MinimalTest)
{
int test = 5;
test++;
test++;
test++;
ASSERT_EQ(test, 8);
}

int main(int argc, char *argv[])
{
char* t = new char();
t[0] = 't'; std::cout << "t is " << t[0] << std::endl;
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}

编译:

/bin/x86_64-w64-mingw32-g++.exe -std=c++11 -D_USE_MATH_DEFINES -g -Wall -I../third_party/googletest-1.8.0/googletest/include -c min.cpp -o min.o

创建 min.o,然后编译 main 并链接在一起:

/bin/x86_64-w64-mingw32-g++.exe -std=c++11 -D_USE_MATH_DEFINES -g -Wall -I../third_party/googletest-1.8.0/googletest/include -o minmain minmain.cpp min.o ../third_party/googletest-1.8.0/googletest/make/gtest_main.a

使用 gtest 1.8.0 版本,在 gtest-port.h:1145 处中断以到达 delete ptr_ 行,然后执行。

以下是运行上述示例的一些示例输出(输出的前几行):

tracking create: 0x30e4c0(size 392)
tracking create: 0xa477e0(size 392)
tracking create: 0xa477e0(size 392)
tracking create: 0xa477e0(size 392)
tracking create: 0xa477e0(size 392)
tracking create: 0xa47b80(size 28)
tracking delete: 0xa47b80

我在同一地址上跟踪创建而中间没有跟踪删除的事实是一个问题,因为中间有删除允许再次分配相同的地址,但这些删除没有通过我覆盖的删除操作符.

为什么 gtest 中的 delete ptr_; 行没有使用我重写的删除函数?

最佳答案

看起来这是 MinGW 中的一个错误: MinGW bug #634

一种解决方法是链接 libstdc++ 的静态版本,而不是让它链接动态库。这不是最理想的解决方案,但对于我的单元测试来说已经足够好了,它允许我正确覆盖。

我通过编译/链接命令修改为以下内容:

/bin/x86_64-w64-mingw32-g++.exe -std=c++11 -D_USE_MATH_DEFINES -g -Wall -I../third_party/googletest-1.8.0/googletest/include -o minmain minmain.cpp min.o ../third_party/googletest-1.8.0/googletest/make/gtest_main.a/cygdrive/c/cygwin64/lib/gcc/x86_64-w64-mingw32/6.4.0/libstdc++.a

非常感谢 Peter 让我找到了正确的道路。

关于C++ operator delete override 并不总是被使用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49713773/

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