C语言中局部变量错误的函数返回地址
我有以下代码:C语言中局部变量错误的函数返回地址,c,C,我有以下代码: char* gen() { char out[256]; sprintf(out, ...); // you don't need to know what's in here I don't think return out; } 当我试图编译时,我得到了这个错误: ERROR: function returns address of local variable 我尝试过让这个返回值char[]和char没有运气。我遗漏了什么吗?当您
char* gen()
{
char out[256];
sprintf(out, ...); // you don't need to know what's in here I don't think
return out;
}
当我试图编译时,我得到了这个错误:
ERROR: function returns address of local variable
我尝试过让这个返回值
char[]
和char
没有运气。我遗漏了什么吗?当您在函数char out[256]中使用以下声明时
一旦函数返回,分配的空间将被释放,因此返回指向out
char
数组的指针是没有意义的
如果要返回指向在函数中创建的字符串的指针,则应在中使用
它为256char
s分配空间,但应在某个时间使用函数手动释放
或者按照注释中的建议,通过传递一个指向要用作函数参数的字符串的
char*
。问题在于,当函数gen
返回(退出)其局部变量(例如out
)时,该变量超出范围,调用方不再能够访问。因此,当您返回out
时,您将返回一个指向不再分配的内存的指针
有两个选项可以从函数“返回”指针/缓冲区:
char * out = malloc(256 * sizeof *out);
// ...
return out;
gen
:
char out[256];
gen(out, sizeof out);
通常还提供传入的缓冲区的大小,因为被调用函数无法知道这一点。这意味着您必须将gen的声明更改为:
void gen(char * out, size_t size){
您还可以将传入缓冲区的大小硬编码为256(因为您现在在gen
函数中对其进行了硬编码):
这意味着您必须向gen
提供类型为char[256]
的变量(并且不提供其他指针或数组)。但它确实允许您在gen
内部执行sizeof out
char * out = malloc(256 * sizeof *out);
// ...
return out;
这样做的好处是gen
的声明不会更改。但这确实意味着调用函数在使用完返回的缓冲区后,必须释放该缓冲区
您的
char
数组变量out
仅存在于函数体内部。当您从函数返回时,
out
buffer的内容无法再访问,它只是函数的本地内容
如果要将函数中的某些字符串返回给调用者,可以在函数中动态分配该字符串(例如,使用malloc()
),并将指向该字符串的指针返回给调用者,例如
char* gen(void)
{
char out[256];
sprintf(out, ...);
/*
* This does NOT work, since "out" is local to the function.
*
* return out;
*/
/* Dynamically allocate the string */
char* result = malloc(strlen(out) + 1) /* +1 for terminating NUL */
/* Deep-copy the string from temporary buffer to return value buffer */
strcpy(result, out);
/* Return the pointer to the dynamically allocated buffer */
return result;
/* NOTE: The caller must FREE this memory using free(). */
}
另一个更简单的选项是将缓冲区指针作为char*
参数传递出去,同时传递缓冲区大小(以避免缓冲区溢出)
在这种情况下,函数可以直接将字符串格式化为作为参数传递的目标缓冲区:
/* Pass destination buffer pointer and buffer size */
void gen(char* out, size_t out_size)
{
/* Directly write into caller supplied buffer.
* Note: Use a "safe" function like snprintf(), to avoid buffer overruns.
*/
snprintf(out, out_size, ...);
...
}
请注意,您在问题标题中明确说明了“C”,但添加了一个[C++]
标记。如果你可以使用C++,最简单的方法就是使用一个字符串类,比如<>代码> STD::String (让它管理所有的字符串缓冲区内存分配/清理)。您是用C
还是C++
编程?决定,相应地标记,请不要再使用这两个标记,这几乎总是错误的。如果这里允许使用c++
,可以使用std::string
@stefan,在这两种语言中,函数返回时局部变量会被销毁。@vonbrand是的,但这不是重点。这个问题显然导致了“如何避免这种情况?/如何返回字符串?”。这两种语言的答案差别很大。我想你的意思是sizeof(char)
(或者更好的是sizeof*out
)而不是sizeof(256)
,因为你只需要256char
s的大小,而不是256int
s的大小。@Kninnug是的,这是我真正想写的。谢谢调用者传递指向缓冲区的指针的问题是,你不知道缓冲区有多大——这是一个等待处理的意外happen@pm100我同意,虽然通过在函数中为缓冲区分配内存也有同样的问题,但调用方不知道返回缓冲区的大小。您可以始终将缓冲区的大小作为参数与缓冲区本身一起提供,也可以使用#define BUFSIZE 256
来确定大小,这始终取决于您的代码结构和要建立的约定。之后您将在何处释放内存?它是在方法本身的本地还是之后?您可以使用C99标准中定义的函数,而不是使用不可移植的Microsoft特定函数,snprintf
@dreamlax:谢谢您的建议。我相应地调整了代码。之后你将如何释放内存?它是在方法本身中还是之后?@CassidyWilliams:函数返回一个指向动态分配字符串的指针(使用malloc()
),您可以在调用站点和任何需要它的地方(在函数体之外)使用该字符串,当您不再需要它时,只需释放内存调用free()
在字符串指针上(为了避免所谓的悬空引用,在调用free()
之后,您可能还希望将指针设置为NULL
)。
/* Pass destination buffer pointer and buffer size */
void gen(char* out, size_t out_size)
{
/* Directly write into caller supplied buffer.
* Note: Use a "safe" function like snprintf(), to avoid buffer overruns.
*/
snprintf(out, out_size, ...);
...
}