问题
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
Versions (1-8) are replaceable: a user-provided non-member function with the same signature defined anywhere in the program, in any source file, replaces the default version. Its declaration does not need to be visible.
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;
}
Output:
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
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. 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
回答1:
Windows is not Linux, and you need behave accordingly.
Simply put, it is generally on the safe side to ensure each EXE/DLL will manage its own memory, i.e. memory allocated by an EXE/DLL should only be deallocated by the same EXE/DLL. It means when a DLL provides createObj
function, it should also provide a destroyObj
function. Of course, you do not have to do this if you can ensure all the EXEs and DLLs use the same runtime DLL (same version, and no static runtime). Even with this, EXEs and DLLs do not share their operator new
/delete
.
When using a memory debugger, you should link its object file to each EXE and DLL. Each EXE/DLL will then have its own memory allocators and detect on its own.
回答2:
I found answer on GCC Bugzilla – Bug 77726.
Liu Hao wrote:
It isn't weired if you know how a Dynamic-Link Library (DLL) on Windows works different than a Shared Object (SO) on Linux.
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.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.
来源:https://stackoverflow.com/questions/46025819/global-overload-operator-new-delete-in-mingw