安全重载全局new和delete

发布于 2024-10-23 22:23:40 字数 1167 浏览 1 评论 0原文

在阅读 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;
} 

我对以下语句有疑问:

  1. 注意使用 printf( )puts( ) 而不是 iostreams 。这是因为当创建 iostream 对象(如全局 cincoutcerr)时,它调用operator new来分配内存。使用 printf( ),您不会陷入死锁,因为它不会调用 new 来初始化自身。
    但是,当我在用 cout 替换 put 后​​运行程序时,我没有遇到这样的死锁。谁能解释一下吗?

  2. 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:

  1. Notice that printf( ) and puts( ) are used rather than iostreams. This is because when an iostream object is created (like the global cin, cout, and cerr), it calls operator new to allocate memory. With printf( ), you don't get into a deadlock because it doesn't call new to initialize itself.
    However, when i am running the program after replacing put with cout i am getting no such deadlock. Can anyone explain that?

  2. 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

想你只要分分秒秒 2024-10-30 22:23:40

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.

冰雪之触 2024-10-30 22:23:40
  1. 使用printf()来避免递归调用operator new()是一种安全措施——只是为了确保它有效。您如何知道使用 iostream 永远不会导致调用 operator new() 函数?

  2. 您将new 表达式(一种语言构造)与operator new() 函数混淆了。 new 表达式 确实返回一个类型化指针,但是对 operator new() 函数的调用是在“幕后”完成的,operator new() > 函数返回void*。编译器会为此生成所有必要的代码。

  1. Use of printf() to avoid a recursive call into operator new() is a safety measure - just to be sure it works. How do you know use of iostream never ever causes a call to operator new() function?

  2. You're confusing new expression (a language construct) with operator new() function. new expression indeed returns a typed pointer, but the a call to operator new() function is done "under the hood" and operator new() function returns void*. The compiler generates all necessary code for that.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文