我想在應用程序中重載新的/刪除操作符來捕獲所有內存泄漏。它在Linux上很好。但是我在Windows上遇到了問題。新/刪除重載僅適用於.exe,但不適用於來自.dll文件的調用。此外,如果某個對象是在我的代碼中創建的,但是從.dll文件中刪除,則會導致應用程序崩潰。 Cppreference here說MinGW中的全局超載操作符new/delete
版本(1-8)是可替換的:用戶提供的非成員函數 與節目任何地方所定義相同的簽名,在任何源 文件,替換默認版本。其聲明不需要 可見。
我寫了最小的Qt模板應用程序來測試這個。這裏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?
P. S.我寫了最小的test case來重現問題。它輸出我
$ ./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
對於EXE/DLL問題,您需要確保您使用的是共享DLL C運行時支持。如果你不是,那麼你將有2個獨立的堆(每個模塊中有一個堆),而一個malloc不能從另一箇中'免費'。 –
我建議避免在dll中釋放內存。最好將分配內存的責任分配給分配內存的組件。 – jumper0x08
jumper0x08,這是無法避免的。刪除父母時刪除所有孩子對於Qt完全正確的行爲。模板中的最小Qt應用程序(.exe)創建對象層次結構並僅刪除根對象。孩子們將被刪除在Qt庫(.dll)中。 –