C++ 替换libstdc++;。OSX上的dylib(4.0)全局新建和删除运算符
我正在努力用XCode 3.2、GCC 4.2、libstdc++4.0、动态版本替换全局new和delete操作符 我直接从标题“new”中获取protypes并实现它们。它们贴在下面 该项目是一个.plugin,因此是一个动态库。此插件必须将分配委托给主应用程序自己的alloc/free例程,这些例程位于旧的C SDK中 我自己对new/delete的所有调用以及std::list和std::map分配都被正确替换,但当std::vector::push_back必须增加其缓冲区时,就不会被正确替换。在这种情况下,不会调用我的运算符new,但会调用我的运算符delete。我知道这一点,因为我在新操作符分配的任何缓冲区的前四个字节中写入一个令牌,并在操作符delete中检查这个令牌。请参阅下面的违规代码C++ 替换libstdc++;。OSX上的dylib(4.0)全局新建和删除运算符,c++,xcode,gcc,stl,new-operator,C++,Xcode,Gcc,Stl,New Operator,我正在努力用XCode 3.2、GCC 4.2、libstdc++4.0、动态版本替换全局new和delete操作符 我直接从标题“new”中获取protypes并实现它们。它们贴在下面 该项目是一个.plugin,因此是一个动态库。此插件必须将分配委托给主应用程序自己的alloc/free例程,这些例程位于旧的C SDK中 我自己对new/delete的所有调用以及std::list和std::map分配都被正确替换,但当std::vector::push_back必须增加其缓冲区时,就不会被
extern "C++"
{
__attribute__((visibility("default"))) void* operator new(std::size_t) throw (std::bad_alloc);
__attribute__((visibility("default"))) void* operator new[](std::size_t) throw (std::bad_alloc);
__attribute__((visibility("default"))) void operator delete(void*) throw();
__attribute__((visibility("default"))) void operator delete[](void*) throw();
__attribute__((visibility("default"))) void* operator new(std::size_t, const std::nothrow_t&) throw();
__attribute__((visibility("default"))) void* operator new[](std::size_t, const std::nothrow_t&) throw();
__attribute__((visibility("default"))) void operator delete(void*, const std::nothrow_t&) throw();
__attribute__((visibility("default"))) void operator delete[](void*, const std::nothrow_t&) throw();
}
以下代码将在“yo”超出范围时导致断言,因为为std::vector分配的内存不是由我的new运算符分配的
{
std::vector<std::string> yo;
yo.push_back("yoyoma");
yo.push_back("yoyoma");
yo.push_back("yoyoma");
yo.push_back("yoyoma");
}
{
std::向量yo;
向后推(“yoyoma”);
向后推(“yoyoma”);
向后推(“yoyoma”);
向后推(“yoyoma”);
}
以下代码正常,因为std::vector::reserve调用my操作符new:
{
std::vector<std::string> yo;
yo.reserve(4);
yo.push_back("yoyoma");
yo.push_back("yoyoma");
yo.push_back("yoyoma");
yo.push_back("yoyoma");
}
{
std::向量yo;
yo.储备(4);
向后推(“yoyoma”);
向后推(“yoyoma”);
向后推(“yoyoma”);
向后推(“yoyoma”);
}
GBD(debugger)不会让met在需要增加缓冲区时介入std::vector::push_back实现(该方法名为_M_insert_aux)。我只知道我的操作符new从未从std::vector::push_back调用过
上述解决方法无法应用于我正在使用的所有第三方LIB。其中一个是push_back的大用户
我试图静态链接到libstdc++.a,但我遇到了同样的问题
对于不使用全局新运算符的std::vector顺便说一句,这在使用VS9的windows上非常有效 我不确定如何准确地执行您的请求,但您可以通过使用自定义分配器在STL中实现自己的分配语义 <>我想我记得我在看C++的Hans Bohen GC时,库将用GC版本替换NeX/DELT,但是你仍然必须把分配器传递给你想要使用的STL结构。
此外,您正在使用的库中可能有代码仍在使用malloc。需要考虑的一些问题。
\u M\u insert\u aux
位于vector.tcc
中,这让人恼火,因为它与GCC的关系不太好。但是,快速扫描显示它与其他方法一样正确地调用了分配器
pointer __new_start(this->_M_allocate(__len));
您可以尝试在
运算符new
中设置断点,定义一个自定义分配器(您可以从std::allocator
派生),该分配器打印调试输出,或者在new\u allocator.h:91
中设置断点,库应在此处调用您的覆盖。最可能的解释是,GCC的std::vector内部实现包括新的。MSVC有许多额外的运算符新重载。您需要拆分源代码或创建新的自定义分配器。我最终使用George Costanza的技术解决了我的问题:做相反的事情
我没有尝试使我的操作符成为新的并删除可见的内容,而是将它们完全隐藏起来
诀窍是在每个静态libs中设置它们&在bundle设置中:
- C++标准库类型:静态
- 默认情况下隐藏的符号:选中
- 修复并继续:未选中(非常重要,否则会自动禁用以前的设置)
#pragma GCC visibility push(hidden)
extern "C++"
{
void* operator new(std::size_t) throw (std::bad_alloc);
void* operator new[](std::size_t) throw (std::bad_alloc);
void operator delete(void*) throw();
void operator delete[](void*) throw();
void* operator new(std::size_t, const std::nothrow_t&) throw();
void* operator new[](std::size_t, const std::nothrow_t&) throw();
void operator delete(void*, const std::nothrow_t&) throw();
void operator delete[](void*, const std::nothrow_t&) throw();
} // extern "C++"
#pragma GCC visibility pop
不,为什么会这样?必须同时具有静态和隐藏符号才能工作。它似乎屏蔽了我的bundle插件,使其不受将其分配器内联的STL专门化实现的影响
还要注意,这只发生在从大型应用程序动态加载的捆绑插件中。在从控制台应用程序调用的普通.dylib项目中,任何设置都可以正常工作。检查是否调用的更可靠的方法是在调用应用程序API之前插入断点。vector.tcc中的实现非常漂亮。事实上,在调试一个简单的控制台应用程序时,我能够分步编写这段代码。我不知道为什么GDB在调试.dylib时找不到源代码。