MinGW中的全局重载运算符new / delete

时间:2017-09-03 16:57:04

标签: c++ qt mingw new-operator delete-operator

我想在我的应用程序中重载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()

2 个答案:

答案 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并且无法覆盖的候选者。