可能重复:
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;
}
答案 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
}