C语言函数返回指针导致数组中先前存储的元素值不断变化问题
问题原因及修复方案
核心问题
你遇到的修改覆盖问题本质是返回了栈上局部变量的指针,属于C语言常见的未定义行为:
get_song_name内部定义的char str[9999]是函数栈上的局部数组,函数执行结束后,这块栈空间会被操作系统回收,允许后续函数调用复用这块内存- 你每次调用
get_song_name返回的都是同一块栈内存的地址,所有name[i]指针最终都指向同一个地址,自然每次调用都会覆盖之前的内容,表现为之前下标的值被修改
其他隐含问题
feof用法错误:feof是在文件读操作失败后才会置位,直接放在循环开头会导致最后一次读操作重复执行,你的代码里虽然因为第一次循环就return不会触发这个问题,但属于不良写法- 文件资源泄漏:
fopen打开文件后没有调用fclose关闭,会持续占用文件句柄 - 路径转义错误:Windows路径中的反斜杠需要转义,应该写为
"c:\\Users\\Marian\\Desktop\\beatles",否则会被识别为转义字符 - 没有判断
fopen的返回值,如果文件打开失败会导致后续读操作崩溃
修复方案
方案1:动态分配内存返回堆指针
把存储字符串的缓冲区改为malloc在堆上分配,堆内存不会随函数退出自动回收,需要手动在使用完后释放避免内存泄漏:
char* get_song_name(const char* song) { // 如果strip函数会修改入参,需要先把song拷贝到本地缓冲区再处理 FILE* fp = fopen(song, "r"); if (!fp) return NULL; // 动态分配缓冲区 char* str = malloc(9999); if (!str) { fclose(fp); return NULL; } // 直接用fgets返回值判断是否读取成功,不需要feof if (fgets(str, 9999, fp)) { strip(str); } else { str[0] = '\0'; } fclose(fp); return str; }
使用完name数组后,需要遍历释放每个元素:
for (int i = 0; i < lines; i++) { free(name[i]); }
方案2:传入外部缓冲区存储结果
如果name是二维字符数组,可以直接把每个元素的缓冲区传入函数,不需要动态分配:
// 函数改为接收外部缓冲区参数 void get_song_name(const char* song, char* buf, int buf_len) { FILE* fp = fopen(song, "r"); if (!fp) { buf[0] = '\0'; return; } if (fgets(buf, buf_len, fp)) { strip(buf); } else { buf[0] = '\0'; } fclose(fp); }
调用方式修改为:
for(i=0;i<lines;i++) { char *st = fgets(buff, 250, fp); st = create_path("c:\\Users\\Marian\\Desktop\\beatles", st); get_song_name(st, name[i], 9999); // 直接传入二维数组的行地址 }
内容的提问来源于stack exchange,提问作者noor napso
相关产品推荐
相关产品推荐

