警告:函数返回局部变量的地址 [默认启用] [重复]
Posted
技术标签:
【中文标题】警告:函数返回局部变量的地址 [默认启用] [重复]【英文标题】:warning: function returns address of local variable [enabled by default] [duplicate] 【发布时间】:2013-06-23 03:15:21 【问题描述】:#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
,但它是乱码。
警告的确切含义是什么?
【问题讨论】:
您不应该从函数返回本地数组。如图所示,一种方法是将它们声明为静态,这将使它们在整个执行期间持续存在。另一种是使用 malloc 分配它们。 你还能期待什么?您的代码一团糟,没有人可以阅读它,我敢肯定,即使您也看不到。 格式化。 另外,回滚到 v1。没有人想要那些??
s。我们已经有他们了。
【参考方案1】:
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
的结果是否有空指针,以确保它没有分配请求的内存失败。如果是这样,您需要以某种方式处理错误。为清楚起见,上面没有显示。
【讨论】:
谢谢你。我现在明白 iwa 做错了什么。我做了那部分,我得到了一个内容标题作为字符串。这是输出。 '内容类型:文本/html; charset=UTF-8' 现在如何从字符串中删除前 17 个字符?我想从字符串中删除“Content-Type:”,或者我可以通过从第 18 个字符和 onwad 复制字符串来做同样的事情。我怎样才能做到这一点?? @aDiAdam 是的,像以前一样使用strncpy
函数。从第 18 个字符开始复制。您将获得一个新字符串,该字符串在原始字符串中没有前 17 个字符。您不能在 C 中就地删除它们。String handling is a pain in the butt in low-level languages,这就是人们使用 C++ 的原因,它为您提供了一个内置的 string
类。
难道没有其他方法可以以某种方式将 malloc-free 责任保持在原始功能的范围内吗?封装等。?【参考方案2】:
快速/Hacky 答案(?):
制作
char type[sz];
进入
static char type[sz];
长答案:错误很明显,您返回的是一个变量的地址,该变量将在函数返回后立即销毁。有几种方法可以解决这个问题。
一种简单的方法是创建类型static
,这可以解决问题,通过使类型变量具有程序的生命周期,但这意味着你不能调用它连续两次,您需要在再次调用之前打印或复制结果。
另一种方法是在您的函数中为char
数组分配内存,并希望您在完成后记得free
。如果不这样做,您将有内存泄漏。这不会受到上述缺点的影响。
【讨论】:
我认为这是不可能的,因为我正在为数组使用可变长度,不是吗?? @aDiAdam 啊,是的,我没有注意到……你是对的。【参考方案3】:当您将type
声明为char type[sz]
时,即为您提供了一个局部变量。该内存的生命周期将在函数返回时结束。相反,您需要动态分配内存,例如使用malloc
。
char *type = (char *) malloc (sz * sizeof (char));
【讨论】:
我。 e. Pretty please don't do it! 另外,“给你一个局部变量”也不是问题。 KarthikT 的解决方案也使用了局部变量,但它是正确的。问题是它具有自动存储期限。【参考方案4】:你返回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()
之后的结果就不需要了。
【讨论】:
好的,我使用了 malloc,它可以工作,现在类型包含“Content-Type: text/html; charset=UTF-8” 我想从这个字符串中删除前 17 个字符,我该怎么做去吧?? @aDiAdam: 字符串长度少于 17 个字符怎么办? @aDiAdam:char * type = chkType(...); size_t n = MIN(17, strlen(type); memmove(type, type + n * sizeof(*type), n * sizeof(*type));
不,我想要的是一个字符串 "text/html; charset=UTF-8" 所以我可以将第 18 个字符从他的字符串复制到另一个字符串。或者我 smhow 从同一个字符串中删除“Content-Type:”。对不起,我对字符串库函数有点生疏了。你能详细说明一下你写的 memove() 部分吗?我将不胜感激
我在strlen(type)
之后错过了)
。详情请见man memmove
。以上是关于警告:函数返回局部变量的地址 [默认启用] [重复]的主要内容,如果未能解决你的问题,请参考以下文章
警告:返回的局部变量“角度”的地址 [-Wreturn-local-addr]