问题描述
我想在应用程序中重载new/delete运算符,以捕获所有内存泄漏.它可以在Linux上正常工作.但是我在Windows上遇到了问题.新建/删除重载仅适用于.exe,不适用于来自.dll文件的调用.此外,如果在我的代码中创建了一些对象,但是正在从.dll文件中删除该对象,则会导致应用崩溃. Cppreference 此处说
I want to overload new/delete operators in my application to catch all memory leaks. It works on Linux fine. But I got a problems on Windows. New/delete overloading works only for .exe but not for calls from .dll files. Furthemore if some object is created in my code but is deleting from .dll file it leads to app crash. Cppreference here says
我编写了最小的Qt模板应用程序对此进行了测试.这里是mainwindow.cpp:
I wrote minimal Qt template application to test this. Here mainwindow.cpp:
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <cstdio>
#include <cstdlib>
// replacement of a minimal set of functions:
void *operator new(std::size_t sz)
{
void *ptr = std::malloc(sz);
std::printf("global op new called, size = %zu, pointer = 0x%p\n", sz, ptr);
return ptr;
}
void operator delete(void* ptr) noexcept
{
std::printf("global op delete called, pointer = 0x%p\n", ptr);
std::free(ptr);
}
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
}
MainWindow::~MainWindow()
{
delete ui;
}
输出:
global op new called, size = 20, pointer = 0x00c4f608
global op new called, size = 24, pointer = 0x00c4f648
global op new called, size = 16, pointer = 0x00b35bf8
global op new called, size = 24, pointer = 0x00c4f6a8
global op new called, size = 24, pointer = 0x00c4f868
global op new called, size = 24, pointer = 0x00c4f988
global op delete called, pointer = 0x00c4f608
已使用Qt 4.8.7/GCC 4.8.2和Qt 5.5.1/GCC 4.9.2进行了测试.那么如何在MinGW中全局超载new/delete?
It was tested with Qt 4.8.7/GCC 4.8.2 and Qt 5.5.1/GCC 4.9.2. So how to globally overload new/delete in MinGW?
P. S.我写了最少的测试用例重现了该问题.它输出了我
P. S. I wrote minimal test case to reproduce the problem. It output me
$ ./main.exe
global op new called, size = 4, pointer = 0x003e17b8
global op new called, size = 4, pointer = 0x003e3d68
library delete called, pointer = 0x003e17b8
global op delete called, pointer = 0x003e3d68
推荐答案
我在GCC Bugzilla上找到了答案– 错误77726 .
I found answer on GCC Bugzilla – Bug 77726.
刘昊写道:
Windows在Linux上没有动态链接器,例如ld.so
. 与Linux相反,DLL中的符号是在生成时解析的, SO中的符号在加载时解析. DLL加载程序可以 将符号解析为地址,但它不像链接器那么强大 毕竟.因此,可执行文件不能使用其强符号 覆盖DLL中已解决的弱漏洞.
Windows does not have a dynamic linker such as ld.so
on Linux. Symbols in a DLL are resolved at build-time, in contrary to Linux, where symbols in a SO are resolved at load-time. The DLL loader can resolve symbols to addresses, but it isn't as powerful as linkers after all. Consequently, an executable cannot use its strong symbols to override already-resolved weak ones in a DLL.
如果用户未定义大小释放函数,则默认 使用libstdc ++ *.dll中的一个,它调用弱默认值, 同一DLL中的非大小释放函数,这是唯一的 DLL生成且不能被覆盖时的候选对象.
If the user does not define a sized deallocation function, the default one in libstdc++*.dll is used, which calls the weak, default, non-sized deallocation function in the same DLL, which is the only candidate when the DLL is built and can't be overridden.
这篇关于MinGW中的全局过载运算符new/delete的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!