Search code examples
c++new-operatordynamic-memory-allocation

Dynamic memory on a function new char[size] vs char[size]


So I have this function that has a string with a pre-defined buffer (the buffer is defined when calling a function).

My question is, why doesn't the compiler throws me an error whenever I do the following (without the new operator?):

int crc32test(unsigned char *write_string, int buffer_size){
     // Append CRC32 to string
     int CRC_NBYTES = 4;
     int new_buffer_size = buffer_size + CRC_NBYTES; // Current buffer size + CRC

     // HERE (DECLARATION OF THE STRING)
     unsigned char appendedcrc_string[new_buffer_size];

     return 0;

}

isn't THIS the correct way to do it..?

int crc32test(unsigned char *write_string, int buffer_size){
      // Append CRC32 to string
     int CRC_NBYTES = 4;
     int new_buffer_size = buffer_size + CRC_NBYTES; // Current buffer size + CRC

     // HERE (DECLARATION OF THE STRING USING NEW)
     unsigned char * appendedcrc_string = new unsigned char[new_buffer_size+1];


     delete[] appendedcrc_string ;

     return 0;

}

And I actually compiled both, and both worked. Why isn't the compiler throwing me any error? And is there a reason to use the new operator if apparently the former function works too?


Solution

  • There's a few answers here already, and I'm going to repeat several things said already. The first form you use is not valid C++, but will work in certain versions of GCC and CLang... It is decidedly non-portable.

    There are a few options that you have as alternatives:

    • Use std::string<unsigned char> for your input and s.append(reinterpret_cast<unsigned char*>(crc), 4);
    • Similarly, you can use std::vector<unsigned char>
    • If your need is just for a simple resizable buffer, you can use std::unique_ptr<unsigned char[]> and use memcpy & std::swap, etc to move the data into a resized buffer and then free the old buffer.
    • As a non-portable alternative for temporary buffer creation, the alloca() function carves out a buffer by twiddling the stack pointer. It doesn't play very well with C++ features but it can be used if extremely careful about ensuring that the function will never have an exception thrown from it.
    • Store the CRC with the buffer in a structure like

      struct input {
          std::unique_ptr<unsigned char[]> buffer;
          uint32_t crc;
      }
      

      And deal with the concatenation of the CRC and buffer someplace else in your code (i.e. on output). This, I believe is the best method.