返回局部变量的引用

时间:2010-08-03 15:50:46

标签: c pointers

  

可能重复:
  Pointer to local variable
  Can a local variable's memory be accessed outside its scope?

gcc 4.4.4 c89

在main中,我调用一个函数将一行文本传递给一个函数。我想对它进行一些操作。但是,这意味着这条线是没用的。所以在我的get_string函数中,我复制内容并返回结果。唯一的问题是,该结果的内存将丢失并指向意外的事情。

我只是想知道如何将结果传回,没有并且仍然保留数据的序数行?

非常感谢任何建议,

来自main的

代码片段:

    if(fgets(line_data, (size_t)STRING_SIZE, fp) == NULL) {
        fprintf(stderr, "WARNING: Text error reading file line number [ %d ]\n", i);
    }

    if(get_string(line_data) != NULL) {
        if(strcmp(get_string(line_data), "END") == 0)
            break;
    }
    else {
        fprintf(stderr, "WARNING: Cannot get name of student at line [ %d ]\n", i);
    }

    /* Fill student info */
    strncpy(stud[i].name, line_data, (size_t)STRING_SIZE);

调用此函数

char* get_string(char *line_data)
{
    char *quote = NULL;
    char result[STRING_SIZE] = {0};

    strncpy(result, line_data, (size_t)STRING_SIZE);

    /* Find last occurance */
    if((quote = strrchr(result, '"')) == NULL) {
        fprintf(stderr, "Text file incorrectly formatted for this student\n");
        return NULL;
    }
    /* Insert nul in place of the quote */
    *quote = '\0';

    /* Overwite the first quote by shifting 1 place */
    memmove(result - 1, result, strlen(result) + 1);

    return result;
}

4 个答案:

答案 0 :(得分:2)

只需返回strdup(结果)。 它将分配和复制您的字符串。 但是,您必须在外部函数中使用它后释放结果。

你也可以在输入中使用缓冲区(带有它的大小),并用你想要的填充它。

答案 1 :(得分:1)

你想要为结果malloc内存:

char *result; result = malloc(STRING_SIZE);

正如你所拥有的那样,结果的内存存在于堆栈中,因此只有在执行内部时才会出现get_string()

在返回NULL之前,您还需要释放结果以防止内存泄漏。

答案 2 :(得分:1)

对于你的直接问题 - 使用malloc(3)并告诉用户该函数取消分配返回指针(这有点容易发生内存泄漏,因为它很容易忽略C中的返回值),或者提供第二个参数作为接收缓冲区:

char* get_string( const char* line_data, char* receive_buf, size_t buf_size );

第三个参数是让函数知道接收缓冲区有多大。

现在你的代码 - 行memmove(result - 1, result, strlen(result) + 1);会破坏你的代码。

答案 3 :(得分:1)

根据经验,你永远不应该返回指向函数局部变量的指针。您知道原因:一旦函数返回,为其变量分配的内存可以重用于其他内容。返回指向结果缓冲区的指针的想法本来就很糟糕。

您应该考虑是否真的需要来保留所引用字符串的副本。如果在调用get_string之前测试了“END”字符串怎么办?如果您需要稍后引用和输出数据,则可以轻松完成。说:

printf("\"%s\"", student_record);

因此get_string实际上可以在缓冲区中工作并返回错误代码(0表示成功)。由于您知道最终结果是较小的nul终止字符串,因此您甚至不需要长度参数。

int get_string(char* student_record);

如果您确实需要保留引用字符串的副本,则需要传递另一个缓冲区。我仍然会返回一个int来表示成功(0)或失败(比如-1)。

int get_string( const char* line_data, char* student_record, size_t buf_size );

我个人更喜欢让调用者分配自己的缓冲区。它使它有机会使用固定长度的缓冲区(更简单的内存管理)。例如:

char student_record[512];
...
if (!get_string(student_record)) {
  // error
}