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
数组的指针是没有意义的

如果要返回指向在函数中创建的字符串的指针,则应在中使用

它为256
char
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)
    ,因为你只需要256
    char
    s的大小,而不是256
    int
    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, ...);
        ...
    }