8
#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

4 回答 4

16

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);
}

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

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

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空指针的结果,以确保它没有分配请求的内存失败。如果是这样,您需要以某种方式处理错误。为清楚起见,上面没有显示。

于 2013-06-26T05:50:35.190 回答
9

快速/哈克答案(?):

制作

char type[sz];

进入

static char type[sz];

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

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

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

于 2013-06-26T05:46:37.873 回答
2

当您声明为时typechar type[sz]这会给您一个局部变量。该内存的生命周期将在函数返回时结束。相反,您需要动态分配内存,例如,使用malloc.

char *type = (char *) malloc (sz * sizeof (char));
于 2013-06-26T05:50:02.823 回答
0

你 return 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()不再需要之后的结果是需要的。

于 2013-06-26T05:47:11.553 回答