char* myArray[] and memory managment
Howdy folks,
I''m having a hard time understanding the nature of c-strings (and memory management). It seems to me that if i assign a cell of my char* array to a c string I ought to have to free the memory by
eg:
myArray[1] = "new string";
delete [] myArray[1];
clearly this isnt the case because it crashes. Isnt a c string stored on the heap? I''m totally confused.
thanks,
dave
Wow. Several things wrong here. Let''s take it a half-line at a time...
myArray[1]
First of all, of what type is myArray, and where is it declared?
For purposes of discussion, I''ll assume it''s a char pointer array (it could be a char array, but that seems less likely to me).
Now, myArray[1] is a single element in this char*array, which means that it CAN "store" a string, but first it has to have memory allocated to it. For example:
myArray[1] = new char[32]; // "makes room" for 32 chars;
The second false assumption you make is that it''s possible to assign one char pointer to another directly, and that a deep copy will occur. This is false. You must explicitly copy the data using a function like strcpy. For example:
strcpy(myArray[1], "new string");
The only way you could actually do an assignment in the way you have would be in an initializer.
Your final statement is correct. To delete the memory we allocated to (char *)myArray[1], we say
delete [] myArray[1];
Now, all this has been based on the assumption that myArray is indeed a char pointer array, and not a char array. If it is declared as a char array, just let us know so someone can explain what''s wrong there.
Peace,
ZE.
//email me.//zealouselixir software.//msdn.//n00biez.//
miscellaneous links
myArray[1]
First of all, of what type is myArray, and where is it declared?
For purposes of discussion, I''ll assume it''s a char pointer array (it could be a char array, but that seems less likely to me).
Now, myArray[1] is a single element in this char*array, which means that it CAN "store" a string, but first it has to have memory allocated to it. For example:
myArray[1] = new char[32]; // "makes room" for 32 chars;
The second false assumption you make is that it''s possible to assign one char pointer to another directly, and that a deep copy will occur. This is false. You must explicitly copy the data using a function like strcpy. For example:
strcpy(myArray[1], "new string");
The only way you could actually do an assignment in the way you have would be in an initializer.
Your final statement is correct. To delete the memory we allocated to (char *)myArray[1], we say
delete [] myArray[1];
Now, all this has been based on the assumption that myArray is indeed a char pointer array, and not a char array. If it is declared as a char array, just let us know so someone can explain what''s wrong there.
Peace,
ZE.
//email me.//zealouselixir software.//msdn.//n00biez.//
miscellaneous links
Hmm, that''s interesting. This leads me to believe that "quoted" string data is held somewhere (at the beginning?) on the stack. I''m assuming that myArray is on the heap of course. This could lead to some very nasty problems (e.g. not knowing whether you have a string created from a file or from quotes). To avoid these problems, the assignment would have to be different when used on a pointer than when used on a char array. Come on programing gurus, is that the case?
______________________________
And the Phoenix shall rise from the ashes...
--Thunder_Hawk -- ¦þ
______________________________
______________________________
And the Phoenix shall rise from the ashes...
--Thunder_Hawk -- ¦þ
______________________________
Ok, I better clarify a little. I''ll show a better abstraction of what I''m doing.
I have a class with a private member:
char* messageQueue[10];
and the method
void addMessage(char * message);
a gross simplification of this method would be:
{
messageQueue[numMessages] = message;
}
I don''t think i need to use strcpy() like zelixir said because a for my intended purpose a shallow copy is sufficient(correct me if im wrong, i will just use this function like addMessage("my message")).
but now say that i want to point that same memory cell to a new c string. if i simply say messageQueue[sameCell] = "test" will that cause a memory leak? I''ve tried to do this first, delete [] messageQueue[sameCell], and it causes the program to crash. Hopefully this further explanation will help reveal what i am not understanding.
also zelixir (thanks for the helpful reply),
I do not understand why you say i cannot simply point one of my char pointers to another string pointer. Doesn''t the pointer just represent the beginning of that strings address?
thanks all,
dave
I have a class with a private member:
char* messageQueue[10];
and the method
void addMessage(char * message);
a gross simplification of this method would be:
{
messageQueue[numMessages] = message;
}
I don''t think i need to use strcpy() like zelixir said because a for my intended purpose a shallow copy is sufficient(correct me if im wrong, i will just use this function like addMessage("my message")).
but now say that i want to point that same memory cell to a new c string. if i simply say messageQueue[sameCell] = "test" will that cause a memory leak? I''ve tried to do this first, delete [] messageQueue[sameCell], and it causes the program to crash. Hopefully this further explanation will help reveal what i am not understanding.
also zelixir (thanks for the helpful reply),
I do not understand why you say i cannot simply point one of my char pointers to another string pointer. Doesn''t the pointer just represent the beginning of that strings address?
thanks all,
dave
It all depends on how the message strings are stored in memory. This depends on how they''re declared.
Take the following example.
K. Now, whenever anyone tries to access that particular message, they get a pointer that doesn''t point anywhere meaningful. It''s just a memory address. And that is why just storing a pointer to the string is bad: you don''t have control over its creation or deletion, and you don''t know where it was allocated.
Now, consider my suggestion. When addMessage is called, something like this happens:
Now it doesn''t matter where the message came from; you can delete each element of messageQueue without concern for the string length or whether it''s on the heap or stack.
Later,
ZE.
//email me.//zealouselixir software.//msdn.//n00biez.//
miscellaneous links
Take the following example.
void GenerateMessage(){ char aMessage[] = "ATTACK GRUGNOR 15"; addMessage(aMessage);}
K. Now, whenever anyone tries to access that particular message, they get a pointer that doesn''t point anywhere meaningful. It''s just a memory address. And that is why just storing a pointer to the string is bad: you don''t have control over its creation or deletion, and you don''t know where it was allocated.
Now, consider my suggestion. When addMessage is called, something like this happens:
void addMessage(char *NewMessage){ messageQueue[currentMsgNum] = new char[strlen(NewMessage}+1]; strcpy(messageQueue[currentMsgNum]), NewMessage);}
Now it doesn''t matter where the message came from; you can delete each element of messageQueue without concern for the string length or whether it''s on the heap or stack.
Later,
ZE.
//email me.//zealouselixir software.//msdn.//n00biez.//
miscellaneous links
I think some clarification on the string problem is needed.
In the following code snippet:
char *a_string = "some text";
no dynamic memory is allocated at run time, so the string isn''t allocated on the heap. The string "some text" is stored in your executable (have a look with a hex editor) in a segment called "rdata" (I''m specifically talking about MSVC V6 here, other compilers may call it something else but the general idea will be there). Your executable has several segments: "text" contains your code, "bss" contains uninitialised global data and so on. "rdata" stands for "read only data", so the above declaration should really be:
const char *a_string = "some text";
which would stop you from deleting it as doing so will generate a compiler error. You will also need to change any functions that take a_string as a parameter to accept a const char *. You should also declare the messageQueue variable as a const char *[] as well. To ''delete'' the message just set the entry in messageQueue to NULL - it will not leak memory since, as stated above, the string is never allocated on the heap.
Remember that a pointer can point to anything, it doesn''t have to be something that was allocated with new/malloc, so it isn''t always necessary to delete what a pointer is pointing at when you''re finished with it.
Note that some compilers / linkers can merge multiple instances of the same string into a single instance, so you can repeat “some text” as many times as you want.
Of course, if you''ve got strings declared in "rdata" and strings allocated via the heap (new / malloc) then ZealousElixir''s solution is required. Or maybe overload the addMessage function to take either a char * or a const char * and have a second, boolean array that is set to true in the first instance and false in the second. When you want to delete the string, check the boolean array first to determine if the string was dynamically or statically allocated.
If you do use dynamically created strings, then you may want to consider using a reference counting system so that the string isn''t deleted until all code that uses it is finished with it.
Skizz
In the following code snippet:
char *a_string = "some text";
no dynamic memory is allocated at run time, so the string isn''t allocated on the heap. The string "some text" is stored in your executable (have a look with a hex editor) in a segment called "rdata" (I''m specifically talking about MSVC V6 here, other compilers may call it something else but the general idea will be there). Your executable has several segments: "text" contains your code, "bss" contains uninitialised global data and so on. "rdata" stands for "read only data", so the above declaration should really be:
const char *a_string = "some text";
which would stop you from deleting it as doing so will generate a compiler error. You will also need to change any functions that take a_string as a parameter to accept a const char *. You should also declare the messageQueue variable as a const char *[] as well. To ''delete'' the message just set the entry in messageQueue to NULL - it will not leak memory since, as stated above, the string is never allocated on the heap.
Remember that a pointer can point to anything, it doesn''t have to be something that was allocated with new/malloc, so it isn''t always necessary to delete what a pointer is pointing at when you''re finished with it.
Note that some compilers / linkers can merge multiple instances of the same string into a single instance, so you can repeat “some text” as many times as you want.
Of course, if you''ve got strings declared in "rdata" and strings allocated via the heap (new / malloc) then ZealousElixir''s solution is required. Or maybe overload the addMessage function to take either a char * or a const char * and have a second, boolean array that is set to true in the first instance and false in the second. When you want to delete the string, check the boolean array first to determine if the string was dynamically or statically allocated.
If you do use dynamically created strings, then you may want to consider using a reference counting system so that the string isn''t deleted until all code that uses it is finished with it.
Skizz
This topic is closed to new replies.
Advertisement
Popular Topics
Advertisement