C++;不总是使用运算符删除覆盖 < >我使用谷歌测试进行了一些C++单元测试。编写了一些代码来覆盖new/delete操作符,以检查单元测试中是否存在泄漏。但是有个问题。有些google test new/deletes使用我的重写方法,但有些不使用,因此我在跟踪代码中出现错误——有时看到内存泄漏,即使它确实被删除了,有时看到malloc返回

C++;不总是使用运算符删除覆盖 < >我使用谷歌测试进行了一些C++单元测试。编写了一些代码来覆盖new/delete操作符,以检查单元测试中是否存在泄漏。但是有个问题。有些google test new/deletes使用我的重写方法,但有些不使用,因此我在跟踪代码中出现错误——有时看到内存泄漏,即使它确实被删除了,有时看到malloc返回,c++,new-operator,googletest,delete-operator,C++,New Operator,Googletest,Delete Operator,以下是我的最小新建/删除覆盖(仅打印用于手动检查的地址): 当我在gdb中中断delete ptr\uu行时,然后执行步骤,它直接进入ptr\up=p行,因此没有其他内容覆盖该删除 我正在将gtest构建为一个归档文件,并在构建单元测试时将其链接进来。以防万一:我和mingw在windows大楼使用cygwin 下面是一个简单的示例,2个文件min.cpp和minmain.cpp。下面是min.cpp: #include <iostream> #include <string&

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

当我在gdb中中断
delete ptr\uu
行时,然后执行步骤,它直接进入
ptr\up=p
行,因此没有其他内容覆盖该删除

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

下面是一个简单的示例,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);
}
要创建min.o,请编译main和link,并使用:

/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端口.h:1145处中断以进入
delete ptr\uuu
行,然后执行步骤

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

我在同一个地址上创建了跟踪,但其间没有跟踪的删除,这是一个问题,因为在这两个地址之间存在允许再次分配同一地址的删除,但这些删除没有经过我的重写的删除运算符


为什么要删除ptr行未使用我的重写删除功能?

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

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

为此,我将compile/link命令修改为:

/bin/x86\u 64-w64-mingw32-g++.exe-std=c++11-D\u使用数学定义-g-Wall-I../third\u party/googletest-1.8.0/googletest/include-o minmain.cpp min.o../third\u/googletest-1.8.0/googletest/make/gtest\u main.a/cygdrive/c/cygwin64/lib/gcc/x86\u 64-w32/6.4.0/liba++>


非常感谢Peter帮我找到了正确的方法。

因为
ptr\uucode>是
nullptr
?这是个好主意,但不是,否则我就不会有不匹配的问题了。我只是在gdb中再次运行了它,并打印了
ptr\uu
,以确保它不会考虑使用a,而不是让我们猜测您在其他地方调用了什么类型的UB。当然,发布a。如果链接到外部库时出现问题,解释可能是该库已编译/链接并使用了自己的UB(例如,您的实现的默认值)运算符
new
delete
。而标准要求程序中的所有编译单元使用这些函数的相同版本(即,您所做的理论上不是问题)当使用链接库时,有些实现在这方面就不那么聪明了。您可能想检查是否已知mingw存在此类问题(我现在不知道)。
#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);
}
#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
/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
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