int main(){
char *s ;
char *fun( ) ;
s = fun( ) ;
printf ( "%s", s ) ;
}
char *fun( ){
char buffer[30] ;
strcpy ( buffer, "RAM - Rarely Adequate Memory") ;
return ( buffer ) ;
}
为什么上面的代码打印出不可预测的结果?如何使char buffer [30]静态帮助?
答案 0 :(得分:5)
程序的整个运行时存在一个static
变量,与普通的“自动”变量不同,只要其父范围存在,该变量才存在。
如果确实返回了指向非static
变量的指针,则表示调用者获取对内存的引用,当被调用函数返回时,该引用不再保留它在函数内所执行的操作。调用者无法有效访问该内存,这样做会调用未定义的行为。
答案 1 :(得分:2)
自动变量驻留在(函数调用)堆栈上。因此,当调用下一个函数时,(在此示例中为printf
),堆栈内容将被覆盖。因此出现了不可预测的错误。
然而,静态变量存储在数据段中。 (与全局变量非常相似,只要考虑存储。)
因此,在下一个函数调用期间不会覆盖静态变量。因此它工作正常。
答案 2 :(得分:0)
char buffer[30];
该行为堆栈上的缓冲区分配空间。当函数退出时,存储将消失,并将被printf中声明的自动变量覆盖。
static char buffer[30];
导致缓冲区从程序的数据段分配,因此在调用printf时不会被覆盖。但是,因为它只被分配一次,所以每次调用fun
都会覆盖以前的值(对你来说不是问题,因为你正在将一个常量字符串写入其中。
答案 3 :(得分:0)
在代码中
char *fun( ){
char buffer[30] ;
strcpy ( buffer, "RAM - Rarely Adequate Memory") ;
return ( buffer ) ;
}
buffer
数组仅在函数本身的生命周期内存在;函数退出后,buffer
使用的内存可供其他线程或进程使用。这意味着在执行语句之间的时间
s = fun( ) ;
printf ( "%s", s ) ;
另一个线程或进程可能会覆盖buffer
正在使用的内存。
如果您将buffer
声明为static
,例如
char *fun( ){
static char buffer[30] ;
strcpy ( buffer, "RAM - Rarely Adequate Memory") ;
return ( buffer ) ;
}
然后buffer
使用的内存在程序启动时分配并保持到程序终止,这意味着没有其他内容可以覆盖它。然而,这需要付出代价; fun
不再是re-entrant。由于函数当前已写入,因此它不是问题,因为它为任何调用返回相同的值。但是,如果fun
意味着针对不同情况返回不同的字符串,则如果一个调用被另一个调用中断,则可能会遇到问题。
第三种选择是动态分配buffer
的内存:
char *fun( ){
char *buffer = malloc( sizeof *buffer * 30 ) ;
if ( buffer )
strcpy ( buffer, "RAM - Rarely Adequate Memory") ;
return ( buffer ) ;
}
这解决了前两个问题;函数退出后保留缓冲区的内容,并且您不限于单个静态缓冲区。但由于没有免费午餐这样的东西,现在调用函数必须确保在完成它时释放该内存:
int main(){
char *s ;
char *fun( ) ;
s = fun( ) ;
printf ( "%s", s ) ;
free( s );
}