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

时间:2013-06-26 05:43:33

标签: 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);
}

这会产生:

warning: function returns address of local variable [enabled by 
default]

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

警告的确切含义是什么?

4 个答案:

答案 0 :(得分: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);
}

从函数返回char*的正确方法是使用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);
}

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

char *type = chktype(...);
// do something
free(type);

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

答案 1 :(得分:6)

快速/黑客回答(?):

制作

char type[sz];

进入

static char type[sz];

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

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

另一种方式是,为您的函数中的char数组分配内存,并希望您在完成后记住free。如果您没有内存泄漏。这不会受到上述缺点的影响。

答案 2 :(得分:2)

当您将type声明为char type[sz]时,它会为您提供一个本地变量。函数返回时,该内存的生命周期将结束。相反,您需要动态分配内存,例如,使用malloc

char *type = (char *) malloc (sz * sizeof (char));

答案 3 :(得分:0)

返回type,它指向已在堆栈上分配的数组,并且在函数chktype()返回后无效。

您可能希望在堆上分配结果,如下所示:

char * chktype(const char * buffer, int size)  
{
  char * strng = "Content-Type: ";
  char * found = strstr (buffer, strng);
  char * found1 = strstr(found, "\r\n");
  size_t sz = strlen(found) - strlen(found1);
  char * type = calloc(sz, sizeof(*type));
  if (type)
  {
    strncpy(type, found1, sz - 1);
  }

  return type;
}

但是,在不再需要之后需要free()结果。