警告:函数返回局部变量的地址[默认启用]

aDi*_*dam 5 c dynamic-allocation

#include <string.h>
#include<stdio.h>
#include<stdlib.h>

char *chktype(char *Buffer, int Size)
{
   char *strng = "Content-Type: ";
   int sz;
   char *found = strstr (Buffer, strng);
   char *found1 = strstr(found, "\r\n");
   sz=strlen(found)-strlen(found1);
   char type[sz];
   strncpy(type, found1, sz-1);

   return(type);
}

void main(){

   char *buffer = "HTTP/1.1 200 OK\r\nDate: Tue, 25 Jun 2013 16:27:16
   GMT\r\nExpires: -1\r\nCache-Control: private,
   max-age=0\r\nContent-Type: text/html; 
   charset=UTF-8\r\nContent-Encoding: gzip\r\nServer: 
   gws\r\nX-XSS-Protection: 1; mode=block\r\nX-Frame-Options:
   SAMEORIGIN\r\nTransfer-Encoding: chunked\r\n\r\n";

   char *extension = chktype (buffer, sizeof(buffer));
   printf("%s\r\n", extension);
}
Run Code Online (Sandbox Code Playgroud)

这会产生:

warning: function returns address of local variable [enabled by 
default]
Run Code Online (Sandbox Code Playgroud)

......我无法弄清楚这里有什么问题.当我运行它时,我希望输出text/html; charset=UTF-8只是它的胡言乱语.

警告到底意味着什么?

Cod*_*ray 14

chktype函数为堆栈上的自动变量分配内存,然后返回此变量的地址(即指向此变量的指针).

问题是堆栈上分配的变量会在超出范围时自动销毁(即控制传递到定义函数的花括号之外).

这意味着你实际上是在返回一个指向无效内存位置的指针,这是个坏消息.在C语言中,它是未定义的行为.实际上,它会导致输出不良甚至崩溃.

char *chktype(char *Buffer, int Size)
{
    // This pointer variable is allocated on the stack, but that's okay because
    // it's a pointer to a string literal, which are always constant.
    // (Technically, you should add the "const" qualifier to the declaration.)
    const char *strng = "Content-Type: ";

    int sz;
    char *found = strstr (Buffer, strng);
    char *found1 = strstr(found, "\r\n");
    sz=strlen(found)-strlen(found1);

    // Like all the above variables, the one is also allocated on the stack.
    // But it's the source of your problem here, because it's the one that
    // you are returning at the end of the function.
    // Problem is, it goes away at the end of the function!
    char type[sz];
    strncpy(type, found1, sz-1);
    return(type);
}
Run Code Online (Sandbox Code Playgroud)

char*从函数返回a的正确方法是使用malloc(或calloc)函数从堆中分配新内存.这意味着该函数的调用者将负责释放返回值使用的内存,否则您的程序将泄漏内存.
(始终将此要求放入函数的文档中!即使"文档"表示声明上方的注释.)

例如,将代码更改为如下所示:

char *chktype(char *Buffer, int Size)
{
    // This pointer variable is allocated on the stack, but that's okay because
    // it's a pointer to a string literal, which are always constant.
    // (Technically, you should add the "const" qualifier to the declaration.)
    const char *strng = "Content-Type: ";

    int sz;
    char *found = strstr (Buffer, strng);
    char *found1 = strstr(found, "\r\n");
    sz=strlen(found)-strlen(found1);

    char *type = malloc(sz);  // allocate memory from the heap
    strncpy(type, found1, sz-1);
    return(type);
}
Run Code Online (Sandbox Code Playgroud)

现在,在chktype函数的调用者中,您必须确保free在完成其返回值时调用:

char *type = chktype(...);
// do something
free(type);
Run Code Online (Sandbox Code Playgroud)

请注意,健壮的代码应测试malloc空指针的结果,以确保它无法分配所请求的内存.如果是这样,您需要以某种方式处理错误.为清楚起见,上面没有显示.


Kar*_*k T 8

快速/ Hacky答案(?):

使

char type[sz];
Run Code Online (Sandbox Code Playgroud)

static char type[sz];
Run Code Online (Sandbox Code Playgroud)

答案长:错误非常明显,您将返回一个变量的地址,该变量将在函数返回时立即销毁.有几种方法可以解决这个问题.

一种简单的方法是static通过使类型变量具有程序的生命周期来创建类型,这将解决问题,但这意味着您不能连续两次调用它,您需要在再次调用之前打印或复制结果.

另一种方法是为你的函数中的数组分配内存,char并希望你完成后记住free它.如果不这样做,您将有内存泄漏.这不会受到上述缺点的影响.