【发布时间】:2009-12-13 16:39:18
【问题描述】:
我有一段时间没有编写 C++ 了,在玩弄重载的全局运算符 new 和 delete 时遇到了一个奇怪的行为。
问题的本质似乎是围绕默认全局 new 构建的包装器并驻留在 separate 源文件中
尽管如此,还是调用了在另一个(并单独编译的)源文件中重载的operator new。
为什么会这样,即我违反/滥用了哪些语言规则/功能?
提前致谢,详情如下。
项目结构:
.
..
main.cpp
mem_wrappers.h
mem_wrappers.cpp
项目文件内容:
main.cpp
#include "./mem_wrappers.h"
#include <iostream>
#include <cstring>
void* operator new[] (size_t sz) throw (std::bad_alloc) {
std::cout << "overloaded new()[]" << std::endl;
return default_arr_new_wrapper(sz);
}
int main() {
const unsigned num = 5;
int * i_arr = new int [num];
return 0;
}
mem_wrappers.h
#include <cstring>
void * default_arr_new_wrapper(size_t sz);
mem_wrappers.cpp
#include <new>
#include <cstring>
#include <iostream>
void * default_arr_new_wrapper(size_t sz) {
std::cout << "default_arr_new wrapper()" << std::endl;
return ::operator new[](sz);
}
符合 g++ main.cpp mem_wrappers.cpp --ansi --pedantic -Wall 运行时会产生无穷无尽的operator new[] 到default_arr_new_wrapper 调用,反之亦然,导致以下输出: p>
overloaded new()[]
default_arr_new_wrapper()
overloaded new()[]
default_arr_new_wrapper()
...
最后,在 SO 中(MS Visual Studio Express 编译器的行为相似)。
我使用的编译器:gcc 版本 3.4.2 (mingw-special) 和 MS Visual Studio 2008 版本 9.0.30729.1 SP。
编辑/更新
如果(正如第一个答案和 cmets 建议的那样)全局 operator new 仅通过在单个编译单元中重载它 [运算符] 就有效地为整个可执行文件重新定义,那么:
仅仅是链接一个源文件重载全局operator new 的目标文件是否会使任何应用程序或库更改其(好吧,让我们这么称呼它)内存分配策略?因此,这个重载运算符是否有效地为语言运行时提供了一个钩子(我的意思是那些已经编译的没有任何重载的新目标文件中的链接器符号是什么,是否只能有一个 new)?
附:我知道malloc 和free 会这样做,并且在发布到这里之前已经尝试过它们(工作正常),但是,这种行为背后的原因是什么(如果我真的要包装默认的operator new 怎么办?:) ) ?
【问题讨论】:
-
顾名思义,global operator new 就是 global。
-
@Neil 那么链接呢(对当前编译单元来说不是全局的吗)?
-
mlvljr,您可以在下划线前放置一个 \(反斜杠)以避免将以下字符呈现为斜体。但通常,当您引用变量名时,最好将其呈现为代码,例如
varname。 -
谢谢大家,我已经投票给大家了。
标签: c++ operator-overloading new-operator