MinGW中的全局过载运算符new/delete [英] Global overload operator new/delete in MinGW

查看:136
本文介绍了MinGW中的全局过载运算符new/delete的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

版本(1-8)是可替换的:用户提供的非成员函数 在程序中的任何地方,任何源中定义的签名都相同 文件,替换默认版本.它的声明不需要 可见.

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.

我编写了最小的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.

刘昊写道:

如果您知道动态链接库(DLL)如何在 Windows的工作方式不同于Linux上的共享对象(SO).

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在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的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆