【问题标题】:Malloc outside of main() or any other function (i.e. at global scope)在 main() 或任何其他函数之外的 malloc(即在全局范围内)
【发布时间】:2015-11-17 21:46:39
【问题描述】:

我想要一个类共有的堆分配缓冲区(在计算期间用作暂存器)。在某些时候,如果缓冲区不够大,我可能会释放然后重新分配缓冲区。我希望缓冲区存在而不必调用“myclass::initialize();”在主要()中;我想出了以下代码,这些代码可以编译并很好地用于我的目的。

我的问题是:为什么这段代码编译正确?为什么 malloc() 允许在 main() 或任何其他函数之外?编译器是否以某种方式解释了这一点并删除了 malloc?

使用“g++ example.cpp”在 linux 64bit 上编译并使用 valgrind 检查的代码

// example.cpp
#include <cstdio>
#include <cstdlib>

class myclass {
public:
   static char* pbuf;                     // buffer
   static unsigned int length;            // buffer length
   const static unsigned int chunk_size;  // allocation chunck size
};

// set constants and allocate buffer
const unsigned int myclass::chunk_size = sizeof(long unsigned int) * 8; 
unsigned int myclass::length = chunk_size;  // start with smallest chunk
char* myclass::pbuf = (char*)malloc(sizeof(char)*myclass::length);

int main() {

   // write to buffer (0 to 63 on 64bit machine)
   for (int i = 0; i < myclass::length; i++) {
       *(myclass::pbuf+i) = i;
   }

   // read from buffer (print the numbers 0 to 63)
   for (int i = 0; i < myclass::length; i++) {
     printf("%d\n", *(myclass::pbuf+i));
   }

   free(myclass::pbuf); // last line of program
}

感谢您的回答。这样的声音比我想象的更常见。 “静态初始化程序中允许函数调用”。这使我得到了一个稍微修改的版本,发现了一个可能的 malloc 错误:

#include <cstdio>
#include <cstdlib>

class myclass {
public:
   static char* pbuf;                     // buffer
   static unsigned int length;            // buffer length
   const static unsigned int chunk_size;  // allocation chunck size
   static void* malloc_buf(unsigned int);
};

// set constants and allocate buffer
const unsigned int myclass::chunk_size = sizeof(long unsigned int) * 8; 
unsigned int myclass::length = chunk_size;  // start with smallest chunk
//char* myclass::pbuf = (char*)malloc(sizeof(char)*myclass::length);
char* myclass::pbuf = (char*)myclass::malloc_buf(sizeof(char)*myclass::length);

void* myclass::malloc_buf(unsigned int N) {
    void* buf = malloc(N);
    if (!buf) exit(EXIT_FAILURE);
    return buf;
} 

int main() {

   // write to buffer (0 to 63 on 64bit machine)
   for (int i = 0; i < myclass::length; i++) {
       *(myclass::pbuf+i) = i;
   }

   // read from buffer (print the numbers 0 to 63)
   for (int i = 0; i < myclass::length; i++) {
     printf("%d\n", *(myclass::pbuf+i));
   }

   free(myclass::pbuf); // last line of program
}

【问题讨论】:

  • 这是一件极其危险的事情。如果不同编译单元中的任何其他静态初始化程序访问pbuf,则结果是不可预测的,并且可能会因不同的编译器、平台甚至使用相同编译器的相同代码的编译而异。见static order fiasco
  • 恭喜您的第一个问题获得四票赞成。我们希望您在 StackOverflow 过得愉快。
  • main() 中的示例代码具有误导性(抱歉)。实际上,类成员函数是唯一访问 pbuf 数据的函数。在我自己的脑海中,我一直将缓冲区称为“便签本”。这个想法是成员函数可以使用可用的暂存器缓冲区,因为它“可用”且“足够大”。如果它太小,则可以调整它的大小,但只要需要,它就会保持“大”。我的想法是我只留下缓冲区,以便成员函数有一个临时区域可以使用......

标签: c++ class malloc variable-declaration


【解决方案1】:

它只是在做静态初始化(在调用 main 之前初始化)。静态初始化器可以调用函数。

【讨论】:

  • 不正是动态初始化吗?我的意思是 pbuf 变量初始化。编译时怎么知道malloc返回值?
  • 我承认我不清楚术语。它正在初始化一个static 变量,但我确实意识到有多种方式发生。似乎人们将所有这些都称为“静态初始化”,因为他们正在初始化静态变量,但我不能说这在技术上是否正确。
  • 是的,@JorgeGonzálezLorenzo 似乎是正确的:en.cppreference.com/w/cpp/language/initialization 我确实认为大多数人松散地将任何初始化静态变量的东西称为“静态初始化”,但我认为这在技术上并不正确。跨度>
【解决方案2】:

main() 只是另一个函数 - 这就是为什么它有如此特殊的要求才能正确调用它。

在它被调用之前,其他事情可能而且确实会发生。其中静态初始化。

【讨论】:

    猜你喜欢
    • 2017-01-20
    • 2012-09-08
    • 1970-01-01
    • 1970-01-01
    • 2012-07-05
    • 2015-10-09
    • 2012-02-18
    • 2015-03-22
    • 1970-01-01
    相关资源
    最近更新 更多