#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
但是它的乱码。
警告的确切含义是什么?
答案 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()
结果。