关于C语言函数调用的问题

       下面是一段来自《C专家编程》里的内容,对于大家初步理解C语言中的函数调用、函数参数以及函数中的变量有着很大帮助。接下来的这段代码片段取自按照当地日期格式打印日期的程序。这里存在一个BUG,看看你是否能够找到:  

/* 将源文件的timestamp转换为表示当地格式日期的字符串 */
char *localized_time(char *filename)
{
  struct tm *tm_ptr;
  struct stat stat_block;
  char buffer[120];
  
  /* 获得源文件的timestamp, 格式为time_t */
  stat(filename, &stat_block);
  
  /* 把UNIX的time_t转换为tm结构,里面保存当地时间 */
  tm_ptr = localtime(&stat_block.st_mtime);
  
  /* 把tm结构转换成以当地日期格式表示的字符串 */
  strftime(buffer, sizeof(buffer), "%a %b %e %T %Y", tm_ptr);
  
  return buffer;
}
             看出来了吗?问题出在函数的最后一行,buffer是一个自动分配内存的数组,为该函数的局部变量。当控制了离开声明的自动变量的范围时,自动变量便自动失效,当函数结束的时候,该变量就已经被销毁,返回一个指向局部变量的指针,却不知道这个指针所指向的地址的内容是什么。这里要记住,自动变量时在堆栈上分配内存的,当自动变量的函数或代码块退出时,它们所占的内存便被收回,因此原先自动变量地址的内容可能被立即覆盖,也可能稍后才被覆盖。


         解决这个问题有以下几种方案:

         1. 返回一个指向字符串常量的指针。

char *func() { return "Only works for simple string"; }
                /* 只适用于简单的字符串 */

       作为最简单的解决方案,它只能返回简单的字符串,字符串常量存储于只读内存区,若需要改写它将遇到困难。

         2. 使用全局声明的数组。

char *fun() 
{
     ...
  my_global_array[i] = ...
     ...
  return my_global_array;
}

       使用全局数组的缺点在于任何人都有可能在任何时候修改这个全局数组,而且该函数的下一次调用也会覆盖该数组的内容。         

        3. 使用静态数组。

char *func()
{
  static char buffer[20];
     ...
  return buffer;
}

       此函数可以防止其他人修改这个数组,但是该函数的下一次调用将覆盖这个数组的内容,所以调用者必须在此之前使用或者备份数组的内容。         

        4. 显式分配一些内存,保存返回的值。

char *func()
{
  char *s = malloc(100);
  ...
  return s;
}

       对于该函数程序员必须承担内存管理的责任,如果内存尚在使用就释放或者出现“内存泄露”(不再使用的内存未回收),就会产生令人难以置信的Bug。         

        5. 要求调用者分配内存来保存函数的返回值。

void func(char *result, int size)
{
     ...
  strncpy(result, "That'd be in the data segment, Bob", size);
}

buffer = malloc(size);
func(buffer, size);
  ...
free(buffer);

       这种方法也许是最好的解决方案,为了提高安全性,调用者应该同时指定缓冲区的大小。如果程序员可以在同一代码块中同时进行“malloc”和“free”操作,内存管理也是最为轻松的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值