关于C#:返回局部变量的引用

returning reference of local variable

本问题已经有最佳答案,请猛点这里访问。

Possible Duplicate:
Pointer to local variable
Can a local variable's memory be accessed outside its scope?

GCC 4.4.4C89

总的来说,我调用一个函数将一行文本传递给一个函数。我想对它进行一些操作。然而,这意味着这条线没有用。因此,在get string函数中,我复制内容并返回结果。唯一的问题是,结果的内存将丢失并指向一些意外的东西。

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

非常感谢您的建议,

主代码段:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
    if(fgets(line_data, (size_t)STRING_SIZE, fp) == NULL) {
        fprintf(stderr,"WARNING: Text error reading file line number [ %d ]
"
, 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 ]
"
, i);
    }

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

调用此函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
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
"
);
        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;
}

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

您还可以在输入中获取一个缓冲区(及其大小),并用您想要的填充它。


根据经验法则,不应该返回指向函数局部变量的指针。你知道为什么:一旦一个函数返回,为它的变量分配的内存就可以被重用。返回结果缓冲区指针的想法本身就很糟糕。

您应该考虑是否真的需要保留引用字符串的副本。如果您在调用get_string之前测试了"end"字符串怎么办?如果以后需要引用和输出数据,则很容易完成。说:

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

所以get-string实际上可以在缓冲区中工作并返回错误代码(0表示成功)。因为您知道最终结果是一个更小的以nul结尾的字符串,所以您甚至不需要长度参数。

1
int get_string(char* student_record);

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

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

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

1
2
3
4
5
char student_record[512];
...
if (!get_string(student_record)) {
  // error
}


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

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

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

现在,对于您的代码,行memmove(result - 1, result, strlen(result) + 1);会损坏您的堆栈。


您要为结果错误锁定内存:

1
char *result; result = malloc(STRING_SIZE);

正如您所拥有的,结果的内存存在于堆栈上,因此仅在执行位于get_string()内时才存在。

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