Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Initialize const char * with out any memory leaks

Below is my sample code. Its just a sample which is similar to the code which i'm using in my applicaiton.

#define STR_SIZE 32

void someThirdPartyFunc(const char* someStr);

void getString(int Num, const char* myStr)
{
  char tempStr[] = "MyTempString=";
  int size = strlen(tempStr) + 2;
  snprintf((char*)myStr, size, "%s%d", tempStr, Num);
}

int main()
{
  const char * myStr = new char(STR_SIZE);
  getString(1, myStr); // get the formated string by sending the number
  someThirdPartyFunc(myStr); // send the string to the thirdpartyFunction
  delete myStr;

  return 0;
}

I am getting an exception if i use this code. I think the problem is with deleting the "myStr". But delete is really necessary.

Is there any other way to format the string in getString and send it to the ThirdPartyFunc??

Thanks in advance.

like image 296
Jabez Avatar asked Oct 21 '25 12:10

Jabez


2 Answers

you are allocating not an array of chars but one char with this line:

 const char * myStr = new char(STR_SIZE);

and that one allocated char is initialized with the value of STR_SIZE, causing a "char overflow" in this case.

if you want an array of size STR_SIZE:

 const char * myStr = new char[STR_SIZE];

(note the rectangular [ ]). you have to deallocate such allocated chunk of memory by using the delete[] operator.

personal note: the code you have written above (manually allocated strings etc) is good educational wise; you will do a lot of such mistakes and thus learn about the inner workings of C / C++. for production code you do not want that, for production code you want std::string or other string-containers to avoid repeating string-related mistakes. in general you are not the one who sucessfully reinvent how string-libraries will work. the same is true for other container-types like dynamically-growable-arrays (std::vector) or dictionary-types or whatever. but for educational fiddling around your code above serves a good purpose.

there are other problems in your code snippet (handing over const char* to a function and then modifying the ram, not calculating correctly the size parameter when calling snprintf etc), but these are not related to your segfault-problem.

like image 53
akira Avatar answered Oct 24 '25 02:10

akira


Re the technical, instead of

const char * myStr = new char(STR_SIZE);

do

char const myStr[STR_SIZE] = "";

Note that both have the problem that the string can’t be modified.

But you only asked about the allocation/deallocation problem.


But then, there's so much wrong at levels above the language-technical.

Here's the original code, complete:

void someThirdPartyFunc(const char* someStr);

void getString(int Num, const char* myStr)
{
  char tempStr[] = "MyTempString=";
  int size = strlen(tempStr) + 2;
  snprintf((char*)myStr, size, "%s%d", tempStr, Num);
}

int main()
{
  const char * myStr = new char(STR_SIZE);
  getString(1, myStr); // get the formated string by sending the number
  someThirdPartyFunc(myStr); // send the string to the thirdpartyFunction
  delete myStr;

  return 0;
}

Here's how to do that at the C++ level:

#include <string>           // std::string
#include <sstream>          // std::ostringstream
using namespace std;

void someThirdPartyFunc( char const* ) {}

string getString( int const num )
{
    ostringstream stream;
    stream  << "MyTempString=" << num;
    return stream.str();
}

int main()
{
  someThirdPartyFunc( getString( 1 ).c_str() );
}

The #define disappeared out of the more natural code, but note that it can very easily lead to undesired text substitutions, even with all uppercase macro names. And shouting all uppercase is an eyesore anyway (which is why it's the macro name convention, as opposed to some other convention). In C++ simply use const instead.

like image 33
Cheers and hth. - Alf Avatar answered Oct 24 '25 03:10

Cheers and hth. - Alf