安全重载全局new和delete
在阅读 Bruce Eckel 时,我遇到了以下示例:
#include <cstdio>
#include <cstdlib>
using namespace std;
void* operator new(size_t sz)
{
printf("operator new: %d Bytes\n", sz);
void* m = malloc(sz);
if(!m) puts("out of memory");
return m;
}
void operator delete(void* m)
{
puts("operator delete");
free(m);
}
class S {
int i[100];
public:
S() { puts("S::S()"); }
~S() { puts("S::~S()"); }
};
int main() {
puts("creating & destroying an int");
int* p = new int(47);
delete p;
puts("creating & destroying an s");
S* s = new S;
delete s;
puts("creating & destroying S[3]");
S* sa = new S[3];
delete []sa;
}
我对以下语句有疑问:
注意使用
printf( )
和puts( )
而不是 iostreams 。这是因为当创建iostream
对象(如全局cin
、cout
和cerr
)时,它调用operator new
来分配内存。使用printf( )
,您不会陷入死锁,因为它不会调用new
来初始化自身。
但是,当我在用cout
替换 put 后运行程序时,我没有遇到这样的死锁。谁能解释一下吗?operator new
返回一个 void 指针,但最终我们得到了一个指向动态分配对象的指针。那么它是一个返回指向对象的指针的构造函数(尽管构造函数没有返回类型)还是它的编译器在内部执行此操作?
While reading Bruce Eckel i came across the following example:
#include <cstdio>
#include <cstdlib>
using namespace std;
void* operator new(size_t sz)
{
printf("operator new: %d Bytes\n", sz);
void* m = malloc(sz);
if(!m) puts("out of memory");
return m;
}
void operator delete(void* m)
{
puts("operator delete");
free(m);
}
class S {
int i[100];
public:
S() { puts("S::S()"); }
~S() { puts("S::~S()"); }
};
int main() {
puts("creating & destroying an int");
int* p = new int(47);
delete p;
puts("creating & destroying an s");
S* s = new S;
delete s;
puts("creating & destroying S[3]");
S* sa = new S[3];
delete []sa;
}
I am having doubt with following statement:
Notice that
printf( )
andputs( )
are used rather than iostreams. This is because when aniostream
object is created (like the globalcin
,cout
, andcerr
), it callsoperator new
to allocate memory. Withprintf( )
, you don't get into a deadlock because it doesn't callnew
to initialize itself.
However, when i am running the program after replacing put withcout
i am getting no such deadlock. Can anyone explain that?operator new
returns a void pointer, but finally we are getting pointer to a dynamically allocated object. So is it a constructor that returns a pointer to the object (this, though the constructor doesn't have a return type) or its the compiler that does i internally?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
1)C++标准包含很多不常用的“may”。这是其中之一。运算符<<函数可能使用动态内存,但并非必须如此。通常情况并非如此。
因此,您的示例有效并不意味着它是正确的。这只是意味着它适用于您正在使用的实现。在其他实现上它可能会崩溃。
标准定义的“可能”也可以走向另一个方向。例如,任何 STL 标头可以包括任何其他标准标头,但不要求这样做。 iostream 标头以及 istream 和 ostream 标头通常就是这种情况。当使用 iostream 时,几乎所有实现都包括 ostream 和 istream,但从技术上讲它们不是必须的。这意味着当您使用 ostream 并仅包含 iostream 时,您的程序可能会工作,但实际上就标准而言它是不正确的。
对于 c 和 c++ 来说,了解什么可能会悄无声息地破坏是相当重要的,但这通常不是很容易。
1) The C++ standard contains a lot of "mays" which are not usually used. This is one of them. The operator<< function may use dynamic memory, but it does not have to. Often this is not the case.
So that your example works does not mean it is correct. It just means it works with the implementation you are using. On other implementations it could break.
The "mays" defined by the standard can also go in another direction. For example any STL-Header may include any other standard header, but is not required to do so. This is often the case with the iostream header and the istream and ostream headers. Almost any implementation includes ostream and istream when iostream is used, but technically they don't have to. This means when you use ostream and just include iostream you program might work, but actually it is not correct as far as the standard is concerned.
For both c and c++ it is rather important to know what may silently break, but this is often not very easy.
使用
printf()
来避免递归调用operator new()
是一种安全措施——只是为了确保它有效。您如何知道使用iostream
永远不会导致调用operator new()
函数?您将new 表达式(一种语言构造)与
operator new()
函数混淆了。 new 表达式 确实返回一个类型化指针,但是对operator new()
函数的调用是在“幕后”完成的,operator new()
> 函数返回void*
。编译器会为此生成所有必要的代码。Use of
printf()
to avoid a recursive call intooperator new()
is a safety measure - just to be sure it works. How do you know use ofiostream
never ever causes a call tooperator new()
function?You're confusing new expression (a language construct) with
operator new()
function. new expression indeed returns a typed pointer, but the a call tooperator new()
function is done "under the hood" andoperator new()
function returnsvoid*
. The compiler generates all necessary code for that.