我想在我的应用程序中重载new / delete操作符以捕获所有内存泄漏。它适用于Linux。但我在Windows上遇到了问题。新/删除重载仅适用于.exe但不适用于来自.dll文件的调用。此外,如果在我的代码中创建了某个对象但是从.dll文件中删除它会导致应用程序崩溃。 Cppreference here说
版本(1-8)是可替换的:用户提供的非成员函数 在任何来源中,在程序的任何位置定义相同的签名 文件,替换默认版本。它的声明不需要 可见。
我编写了最小的Qt模板应用程序来测试它。这里是mainwindow.cpp:
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
输出:
$ ./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
用Qt 4.8.7 / GCC 4.8.2和Qt 5.5.1 / GCC 4.9.2进行测试。那么如何在MinGW中全局重载new / delete?
P上。 S.我写了最小test case来重现问题。它输出我
import socket
import time
import random
server_socket = socket.socket()
server_socket.bind(('0.0.0.0', 8821))
server_socket.listen(1)
(client_socket, client_address) = server_socket.accept()
client_input = client_socket.recv(1024)
client_input = client_input.upper()
if client_input == 'TIME':
client_socket.send(time.strftime("%c"))
elif client_input == 'RAND':
client_socket.send(str(random.randrange(0, 11)))
elif client_input == 'NAME':
client_socket.send("My master called me \"Arik\". Funny, ha?")
else:
client_socket.send("Unknown command")
if len(client_input) > 4 or len(client_input) < 4:
client_socket.send("The length of your messege\nneeds to be 4 chracters.\nI know only 4 commands.\nRAND, TIME, NAME & EXIT.\nThanks.")
client_socket.close()
server_socket.close()
答案 0 :(得分:0)
Windows不是Linux,您需要相应的行为。
简单地说,通常是安全的,以确保每个EXE / DLL将管理自己的内存,即EXE / DLL分配的内存只能由相同的EXE / DLL解除分配。这意味着当DLL提供createObj
函数时,它还应该提供destroyObj
函数。当然,如果可以确保所有EXE和DLL使用相同的运行时DLL(相同版本,并且没有静态运行时),则不必执行此操作。即使这样,EXE和DLL也不会共享operator new
/ delete
。
使用内存调试程序时,应将其目标文件链接到每个EXE和DLL。然后每个EXE / DLL都有自己的内存分配器并自行检测。
答案 1 :(得分:0)
我在GCC Bugzilla上找到答案 - Bug 77726。
刘昊写道:如果你知道动态链接库(DLL)是如何打开的话,那就没有了 Windows的工作方式与Linux上的共享对象(SO)不同。
Windows在Linux上没有动态链接器,例如
ld.so
。 DLL中的符号在构建时解析,与Linux相反, 其中SO中的符号在加载时解析。 DLL加载器可以 将符号解析为地址,但它没有链接器那么强大 毕竟。因此,可执行文件不能使用其强符号 覆盖DLL中已经解析的弱点。如果用户未定义大小的释放功能,则为默认值 一个在libstdc ++ * .dll中使用,它调用弱,默认, 同一DLL中的非大小的释放函数,这是唯一的 构建DLL并且无法覆盖的候选者。