使用自定义 new/delete 和 C++ 中的 Qt 的段错误

Segfault with custom new/delete and Qt in C++

所以我想尝试一下自定义 new/delete 并按照 this 回答。我有一个运行良好的 MWE,但是一旦我包含 Qt header(即使不使用它),我得到的只是一个分段错误。段错误发生在输入 main() 之前,我不知道发生了什么。这是代码:

/* main.cpp */
#include <iostream>
//#include <QString> // uncommenting this line causes the segfault

int main() {
    int* ref = new int(42);
    std::cout << ref << ", " << *ref << std::endl;
    delete ref;
}
/* custom_new.cpp */
#include <iostream>

void* operator new(size_t n) {
    void* result = malloc(n);
    std::cout << "Allocating " << n << " bytes at position " << result << std::endl;
    return result;
}

void operator delete(void* p) {
    std::cout << "Deleting memory at position " << p << std::endl;
    free(p);
}
# CMakeLists.txt
find_package(Qt5Core CONFIG REQUIRED)
add_library(custom_new custom_new.cpp)
add_executable(mwe main.cpp)
target_link_libraries(mwe Qt5::Core custom_new)

从全局 operator new 内部访问 cout 是个坏主意,因为 cout 可能尚未初始化。

libQt5Coremain() 之前有许多 运行 的静态初始化器,其中一些使用 operator new 分配内存。事实上 QMutex 似乎在 cout 之前被初始化,所以它在 cout <<.

上崩溃了
$ gdb ./a.out
(gdb) r
Program received signal SIGSEGV, Segmentation fault.
0x00007fffff22d426 in std::ostream::sentry::sentry(std::ostream&) () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
(gdb) bt
#0  0x00007fffff22d426 in std::ostream::sentry::sentry(std::ostream&) () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#1  0x00007fffff22da38 in std::basic_ostream<char, std::char_traits<char> >& std::__ostream_insert<char, std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*, long) () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#2  0x00007fffff22de47 in std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*) () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#3  0x00000000080013cd in operator new (n=32) at a.cpp:17
#4  0x00007fffff3658d2 in QMutex::QMutex(QMutex::RecursionMode) () from /usr/lib/x86_64-linux-gnu/libQt5Core.so.5
#5  0x00007fffff47699f in qRegisterResourceData(int, unsigned char const*, unsigned char const*, unsigned char const*) () from /usr/lib/x86_64-linux-gnu/libQt5Core.so.5
#6  0x00007fffff34baa3 in ?? () from /usr/lib/x86_64-linux-gnu/libQt5Core.so.5
#7  0x00007fffff7cf37a in call_init (l=<optimized out>, argc=argc@entry=1, argv=argv@entry=0x7ffffffee678, env=env@entry=0x7ffffffee688) at dl-init.c:72
#8  0x00007fffff7cf476 in call_init (env=0x7ffffffee688, argv=0x7ffffffee678, argc=1, l=<optimized out>) at dl-init.c:30
#9  _dl_init (main_map=0x7fffff7e9190, argc=1, argv=0x7ffffffee678, env=0x7ffffffee688) at dl-init.c:119
#10 0x00007fffff7c10ca in _dl_start_user () from /lib64/ld-linux-x86-64.so.2

如果您真的想在 operator new 中使用 cout,请使用全局标志并将其设置为 main() 中的 true,以便跳过之前调用的输出main().