Archived

This topic is now archived and is closed to further replies.

nathan123

initializing a char* with a string literal

Recommended Posts

Hi All. I have a question regarding initializing a variable of type char* with a string literal. int main() { char* pString = new char[5]; char* pStringII = "TEST"; delete []pString; delete []pStringII; return 0; } The above code creates an error at runtime because of the line delete []pStringII. Based on this error, I have the following questions I hope someone could help me with. Is initializing a variable of type char* with a string literal the same as dynamically allocating memory with the new keyword? For example: Is char* pStringII="TEST" equivalent to char* pStringII = new char[5]? If these two statements are equivalent, how does one reclaim the memory (char* pStringII="TEST"), since delete []pStringII throws an error? Thanks for your help.

Share this post


Link to post
Share on other sites
quote:
Original post by nathan123
Is initializing a variable of type char* with a string literal the same as dynamically allocating memory with the new keyword?

No. As I recall, string literals are usually located in the data segment of your executable (I''m not at all sure this is mandated by the standard, but it appears to be how it is usually done). The general rule is, use delete[] if and only if you actually allocate the memory with the keyword new.

Share this post


Link to post
Share on other sites
Thanks for your reponse.
Does this mean that the memory used by the string is not reallocated until the program completes execution? Is there a way (or is it even necessary) to reclaim this memory?

For example, if throughout the sample program below, I make many calls to testMethod, am I constantly wasting memory (each time I pass in a string literal)?


#include <iostream.h>


void testMethod( char *word)
{
cout<
}


int main()
{


testMethod("HELLO");
//...OTHER CODE which may include other calls to testMethod()
return 0;
}

Share this post


Link to post
Share on other sites
To make this VERY VERY clear ...

you MUST call operator delete IF AND ONLY IF you called operator new

you MUST call operator delete [ ] IF AND ONLY IF you called operator new [ ]

you MUST call free IF AND ONLY IF you called a C alloc function (malloc, calloc, realloc)

Share this post


Link to post
Share on other sites
In fact you don''t wast memory.
If you call 10 times the function testMethod("HELLO"), it will create the HELLO string 10 time but once at a time, during the function call. The string will be automaticly released when the function will return.

Share this post


Link to post
Share on other sites
Let me first say, thank you for all your reponses. I truly appreciate your help.
With that said, I do have one more question though.

"If you call 10 times the function testMethod("HELLO"), it will create the HELLO string 10 time but once at a time, during the function call. The string will be automaticly released when the function will return."--Viquel

If the string is automatically released when the function returns, does this mean that the data stored at *word is released?
In the program below, I copy the char pointer, *word, to a global variable char pointer, *gTest in testMethod()-- however, the information stored at gTest still exists after the function is returned. Why is this? Is my logic flawed(which it very well may be)?

I guess what I am asking is, why does the data at *word still exist after the method is returned?
Shouldn't gTest in testMethodII() point to nothing, since the data it points to was created and presumably released when testMethod() was returned?

I hope my question makes sense.

#include <iostream.h>

char *gTest;
void testMethod( char *word)
{
cout word "\n";//Q1. Do you have to delete word
gTest = word;
}

void testMethodII()
{

cout gTest "\n";
}

int main()
{


testMethod("HELLO");
testMethodII();

return 0;
}







[edited by - nathan123 on May 1, 2003 3:50:46 PM]

Share this post


Link to post
Share on other sites
"If you call 10 times the function testMethod("HELLO"), it will create the HELLO string 10 time but once at a time, during the function call. The string will be automaticly released when the function will return."--Viquel

The string HELLO will only ever be created once at compile time and stuck in the data section of your executable.

(I don''t think this is mandated by any standard, but every compiler i know of will do it this way).

Share this post


Link to post
Share on other sites
I would guess that this is because the "HELLO" string is stored in a data section that is loaded when the program starts, and is only released when the program exits. It''s not very safe to depend on this behavior, because there is not any rule that says the compiler has to do things this way. And it''s bad coding style.

Share this post


Link to post
Share on other sites
quote:
Original post by Viquel
In fact you don't wast memory.
If you call 10 times the function testMethod("HELLO"), it will create the HELLO string 10 time but once at a time, during the function call. The string will be automaticly released when the function will return.



Sorry Viquel but you're talking nonsense. Please remove your post to avoid misleading others.

Anyway, just to add some stuff that hasn't been mentioned previously:


    
#include <iostream>

void testMethod( char *word)
{
std::cout<< word << "\n";
word[1] = 'u';// modify string that has been passed

std::cout<< word << "\n";
}



  
int main()
{
char hello[] = "Hello";//creates an array of size 6 with values Hello\0

// where \0 is a single terminating character

testMethod(hello);// passes a pointer to the array, hello, which is our own copy of "Hello"


char* hell = "Hell";// creates a pointer to the constant string Hell\0

// which is stored somewhere in your executable

// It is a constant and you're not allowed to change it


// testMethod(hell);//crash! (uncomment this to see a crash)


const char* nice = "Safe!";
// testMethod(nice);// this line won't compile because testMethod takes a non-const

// pointer to a char. The compiler can't be sure it won't be modified

// so won't let you pass it.

// This is safe. If you make testMethod only take a const char* you

// can pass 'nice' but can't modify it in the function.

return 0;
}

The moral of the story is, if you're taking a pointer to a string literal then make it a const char*. Otherwise you could run into trouble somewher down the line.

Better yet, use std::string.

[edited by - petewood on May 1, 2003 6:27:15 PM]

Share this post


Link to post
Share on other sites
quote:
char hello[] = "Hello";//creates an array of size 6 with values Hello\0 // where \0 is a single terminating character testMethod(hello);// passes a pointer to the array, hello, which is our own copy of "Hello" char* hell = "Hell";// creates a pointer to the constant string Hell\0 // which is stored somewhere in your executable // It is a constant and you''re not allowed to change it// testMethod(hell);//crash! (uncomment this to see a crash)



I''ve been told that writing:>

char string[];

and

char* string;

is just the same thing. But just to clear my doubts I tried your example and my program didn''t crash it worked just fine.
But this could perhaps be a compiler thing?

In the next 80 years 6 billion people will die...

Share this post


Link to post
Share on other sites
quote:
Original post by pag
I''ve been told that writing:>

char string[];

and

char* string;

is just the same thing. But just to clear my doubts I tried your example and my program didn''t crash it worked just fine.
But this could perhaps be a compiler thing?



Ah... relying on compilers to tell you what is correct is the path to confusion. (by the way, did you uncomment the lines to make it crash?)

char letters1[] = "abcdefghijklmnopqrstuvwxyz";
will create a character array of size 27 (26 letters in the alphabet and a terminating null character). This will be created during the running of the program. The string of characters "abcdefghijklmnopqrstuvwxyz" will be copied into it. It will be its own copy which is modifiable. The string "abcdefghijklmnopqrstuvwxyz" is not modifiable.

char* letters2 = 0;
will create a pointer to a character and set it to point to nothing

letters2 = "abcdefghijklmnopqrstuvwxyz";
will set the pointer to point to the constant string literal.

you can see letters1 and letters2 are very diffferent things. letters1 points to its own memory and can do what it wants. letters2 points to someone elses memory.

Share this post


Link to post
Share on other sites
quote:
NOTE: char* is the same as char[]


The quote above was found at www.cplusplus.com, the exact URL to the page which was saying this is:> http://www.cplusplus.com/doc/tutorial/tut3-2.html . And you can find the above in the end of the page..

So what? are they wrong?

oh and this is the code I wrote:>


#include <iostream.h>

void myfunc(char* str)
{
str[0] = '0';
std::cout << str;
}

int main(int, char**)
{
char str1[] = "Hellowigjgioegoergier";
char* str2 = "Byeewfhewhfouwreewr";

myfunc(str1);
myfunc(str2);

std::cin.ignore();
return 0;
}


In the next 80 years 6 billion people will die...

[edited by - pag on May 2, 2003 7:02:02 AM]

Share this post


Link to post
Share on other sites
quote:
oh and this is the code I wrote:>


I don't believe that is the exact code as it has the old <iostream.h> header file rather than the standard <iostream>. It wouldn't compile.

And so the battle of the compilers begins.

If you change it to the correct header under MSVC 6.0 service pack 4, you get a crash in debug mode and (cough) no problems in release mode. Other versions of the compiler and other compilers may give you differing results.

The fact is, in terms of the C++ language (if that's what you want to learn), it's wrong to modify a string literal and the behaviour is undefined if you do.

BTW the quote about char* being the same as char[] is in the context of the functions they were talking about. Anywhere you can pass a char* you can pass a char[] instead. They aren't 'the same' same. They are different as I've said now a few times.

[edited by - petewood on May 2, 2003 9:42:09 AM]

Share this post


Link to post
Share on other sites
quote:
I don't believe that is the exact code as it has the old header file rather than the standard . It wouldn't compile.



eh... well it did compile and works very good. And I don't have a <iostream> file, it's named <iostream.h>. And I think it's the same for all borland c++ 5.5 command tools users out there.

and the code I posted above was taken directly from my editor...
oh and the same code worked perfectly fine with printf also...

In the next 80 years 6 billion people will die...

[edited by - pag on May 2, 2003 12:43:53 PM]

Share this post


Link to post
Share on other sites
quote:
Original post by pag
eh... well it did compile and works very good. And I don't have a <iostream> file, it's named <iostream.h>. And I think it's the same for all borland c++ 5.5 command tools users out there.


Borland does not support the old headers. iostream.h is iostream and including <iostream> will include the file iostream.h.

It is recommended that you use <iostream> not <iostream.h> as the second is technically inaccurate.

Enigma



[edited by - Enigma on May 2, 2003 5:35:07 PM]

Share this post


Link to post
Share on other sites