puts() a pointer in C
I have a function:
char *make_开发者_JAVA百科text(void)
{
char txt[MAXLEN];
//make something
return txt;
}
Thats my main program:
int main(void)
{
char *s = make_text();
puts(s);
getch();
return 0;
}
puts(s)
returns 0
and its nothing printed. Whats happened?
The memory you allocated in the make_text function got freed at the end of make_text. So you shouldn't try to access it.
You could allocate the memory using malloc or calloc, so it doesn't get freed automatically.
Returning a pointer to a value on the stack is a bad idea, and probably won't work.
make_text
returns txt
, which is allocated in local storage in the make_text
function. When make_text
returns, things in local storage in that function are cleared. To do this, you need to use dynamic storage with malloc()
:
char *make_text(void)
{
char *txt = malloc(MAXLEN);
// do stuff
return txt;
}
Memory allocated with malloc()
doesn't disappear when a function returns. This means that C doesn't know when exactly it's safe to deallocate, so when you're done with it you must call free()
on txt
to manually release the memory. Otherwise, you'll have a memory leak.
when you declare char txt[MAXLEN]; inside a scope, in this case function make_text, the vector txt of char will be valid only in the make_text lifetime.
You will have to use dynamic allocation.
char *make_text(void)
{
char *txt = (char *) malloc(sizeof(char) *MAXLEN);
//make something
return txt;
}
Then you will have to deallocate the memory after the text had been used:
char *s = make_text();
free(s);
You are returning a variable, txt, from make_text that is local to the function. The results of doing this are undefined, since txt will go out of scope when the function returns.
Instead, you could pass txt as an argument:
void make_text(char * txt)
{
//make something
sprintf(txt,"%s","Something!");
}
And a main:
int main(void)
{
char s[MAXLEN];
make_text(s);
puts(s);
getch();
return 0;
}
Automatic variables (local variables and parameters to called functions) have to be stored somewhere. That somewhere is on the stack (or in registers, but that's nor important right now). Here's a little simplified stack annotation for how your program runs:
int main(void)
{
// [_start+0x040 ]
// This is just the address of some code just after the code that called main.
// You immediatly call make_text, so lets go there.
char *make_text(void)
{
// [_start+0x040, main+0x004]
// this is the address within main that make_text returns to
char txt[MAXLEN];
// [_start+0x040, main+0x004, txt[MAXLEN-1], ..., txt[0] ]
return txt;
// This empties this function's data and pops the return address into
// the instruction pointer.
}
char *s = make_text();
// [_start+0x040, &txt[0] ]
// Now, back in main we have an address to something that is not on the stack
// anymore.
// Random things happen to memory that used to be part of the stack.
puts(s);
// [_start+0x040, &txt[0], main+0x008 ]
// puts() here tries to print a string containing random data which also happens
// to be the same memory that puts is trying to use as its local variables.
getch();
// getch() is the only part that probably worked
You could return a pointer to a static variable, as in:
char *make_text(void)
{
static char txt[MAXLEN];
//make something
return txt;
}
(Of course the above code is not threadsafe).
精彩评论