从C中的函数返回一个字符串
我有一个ac函数,我想返回一个字符串。
如果我在返回之前打印字符串,那么我会看到croc_data_0186.idx
如果我尝试打印返回的字符串,那么我会看到croc_data_á☼
谁能看到我做错了什么?
问题function:
char* getSegmentFileName(FILE *file, int lineLength, int lineNumber) { char* fileNameString; fseek(file, lineNumber * lineLength, SEEK_SET); char line[lineLength]; fgets(line, lineLength, file); char *lineElements[3]; lineElements[0] = strtok(line, ":"); lineElements[1] = strtok(NULL, ":"); lineElements[2] = strtok(NULL, ":"); fileNameString = lineElements[2]; printf ("getSegmentFileName fileNameString is: %s \r\n", fileNameString); return fileNameString; }
调用代码:
int indexSearch(FILE *file, char* value, int low, int high, char* segmentFileName) { ... segmentFileName = getSegmentFileName(file, lineLength, mid); printf ("indexSearch: segmentFilename3 is: %s \r\n", segmentFileName); ... }
您正在返回指向本地数据的指针,该指针在函数返回后无效。 您必须正确分配字符串。
这可以在调用函数中完成,通过向被调用函数提供缓冲区,并将字符串复制到提供的缓冲区。 像这样:
char segmentFileName[SOME_SIZE]; getSegmentFileName(file, lineLength, mid, segmentFileName);
和getSegmentFileName
函数:
void getSegmentFileName(FILE *file, int lineLength, int lineNumber, char *segmentFileName) { /* ... */ strcpy(segmentFileName, fileNameString); }
另一种解决方案是在getSegmentFileName
为字符串分配内存:
return strdup(fileNameString);
但是你必须记得以后free
字符串。
这是因为您正在返回指向local的指针。 这是未定义的行为。
strtok
返回指向line
字符数组的指针。 您将该指针放入fileNameString
,并返回给调用者。 此时内线内存变为无效:可以将任何垃圾写入其中。
要避免此问题,您应该为返回值传递缓冲区/长度对,或者对要返回的字符串使用strdup()
。 在后一种情况下,您应该记住通过strdup()
释放为返回的字符串分配的内存。
在相关主题上,您应该避免使用strtok
,因为它不是可重入的,并且会在multithreading环境中引起问题。 请考虑使用strtok_r
。
您正在返回指向函数返回时不再存在的局部变量的指针。 你必须为它进行malloc
存储并返回它。 或者,您可以让调用者通过缓冲区来填充。 在任何情况下,调用者都有责任以后free
内存。
这是因为你返回了无效的指针。
char* fileNameString;
只是一个指针。
char line[lineLength];
生活在堆栈上并充满了fgets()
调用。
char *lineElements[3]; lineElements[0] = strtok(line, ":"); lineElements[1] = strtok(NULL, ":"); lineElements[2] = strtok(NULL, ":");
在这里存储指向该数组的指针。 其中之一是
fileNameString = lineElements[2];
哪个你
return fileNameString;
然后。
解决方案是
-
要么malloc足够的空间在函数内部,要么将你的字符串复制到新的内存块或
-
让调用者提供您将数据写入的缓冲区。
问题是你返回一个堆栈变量,当函数返回时丢失。 实现此目的的一种方法是在函数参数中使用char * arg,具有足够的保留空间,并使用它来存储所有信息并将其返回。
Line是一个局部变量,在函数末尾被删除。
你应该使用malloc,或者将它strcpy到作为参数传递的字符串指针。
有3种方法可以解决这个问题
1)使’fileNameString’静态
static char fileNameString[100];
2)函数’getSegmentFileName’的调用者应该将字符缓冲区’segmentFileName’传递给被调用者,即
getSegmentFileName(file, lineLength, mid, segmentFileName);
在这种情况下,您需要更改函数参数
char* getSegmentFileName(FILE *file, int lineLength, int lineNumber, char *segmentFileName) { ..... strcpy(segmentFileName, fileNameString); // copying the local variable 'fileNameString' to the function argument // so that it wont be lost when the function is exited. return fileNameString; // there is no need to return anything and you can make this function void // in order not to alter ur program I am putting the return also }
3)通过这种方式,您可以为fileNameString动态分配内存。 动态内存在堆中分配,并且在函数返回时不会丢失。 所以你可以在indexSearch函数中安全地使用它。
char* getSegmentFileName(FILE *file, int lineLength, int lineNumber) { char *fileNameString = (char *)malloc(100 * sizeof(char)); // allocate memory for 100 character string ..... return fileNameString; }
在这种情况下,您将需要使用free
fileNameString指向的内存