Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Malloc outside of main() or any other function (i.e. at global scope)

I wanted a heap allocated buffer common to a class (to use as a scratchpad during computations). At some point I may free and then reallocate the buffer if it is not large enough. I wanted the buffer to exist without having to call a "myclass::initialize();" in main(); I came up with the following code that compiles and works well for my purpose.

My questions are: Why does this code compile correctly? Why is malloc() allowed to be outside of main() or any other function? Is the compiler interpreting this somehow and removing the malloc?

Code compiled on linux 64bit using "g++ example.cpp" and checked with 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
}

Thanks for the answers. Sound like this is more common than I thought. "Functions calls are allowed in static initializers". This leads me to a slightly modified version catching a possible malloc error:

#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
}
like image 542
Dr. Wolfe Avatar asked Oct 18 '22 22:10

Dr. Wolfe


2 Answers

It's just doing static initialization (initialization before main is called). Static initializers are allowed to call functions.

like image 137
Oliver Dain Avatar answered Nov 02 '22 11:11

Oliver Dain


main() is just another function - which is why it has such specific requirements placed on it to allow it to be called properly.

Other things can and do happen before it gets called. Static initialization among them.

like image 40
Andrew Henle Avatar answered Nov 02 '22 12:11

Andrew Henle