C语言中函数如何返回处理后的结果?

来源:互联网 发布:手机批量修图软件 编辑:程序博客网 时间:2024/05/17 01:39

在c语言中,自动变量在堆栈中分配内存,当包含自动变量的函数或代码块退出时,它们所占用的内存便被回收。被回收的内存可能会被马上覆盖,也可能等到很久以后才会被覆盖,这取决于堆栈中先前的自动变量位于何处,下一个函数/代码块声明的变量/写入的内容等条件,所以如果有以下代码:

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

那么这个函数会导致一个难以察觉的bug。我想在调用函数中获取buffer里的内容,但有时候能够“正常”获取,有时候数据被破坏了……
解决这个问题有几种方案。

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

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

这是最简单的解决方案,但实际应用中一般有更多的需求。

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

char globalArr[512];...char * func(){    ...    globalArr[i] = ...    ...    return globalArr;}

这适用于自己创建字符串的情况,也很简单易用。它的缺点在于任何人都有可能在任何时候有修改这个全局数组,而且函数的下一次调用也会覆盖该数组的内容。

3. 使用静态数组。例如:

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

这就可以防止任何人修改这个数组。只有拥有指向该数组的指针的函数(通过参数传递给它)才能修改这个静态数组。但是,该函数的下一次调用将覆盖这个数组的内容,所以调用者必须在此之前使用或备份这个数组的内容。和全局数组一样,大型缓冲区如果闲置不用是非常浪费内存空间的。

4. 显示分配一些内存,保存返回的值。例如:

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

这个方法具有静态数组的优点,而且在每次调用时都将创建一个新的缓冲区,所以该函数每次调用的内容不会互相干扰,这使它适合多线程的代码。它的缺点在于函数的使用者必须承担内存管理的责任。如果内存正在使用却被释放,或者不再使用的内存还没有被回收,就会发生内存泄露,这会产生令人难以置信的bug。

5. 这可能是最好的方法,就是要求调用者分配内存来保存函数的返回值。

为了提高安全性,调用者应该同时指定缓冲区的大小(就像标准库中fgets()所要求的那样)

void func(char * result, int size){    ...    strncpy(result, "string", size);}...buffer = malloc(size);func(buffer, size);...free(buffer);

这个方法相较于上一个方法,优点在于程序员能在同一个代码块中同时进行”malloc”和”free”操作,内存管理要轻松许多。

0 0
原创粉丝点击