使用realloc()时malloc分配的指针数组内指针丢失问题排查
问题描述
我编写了一个函数,用于从格式为|DATA名称|DATA字节数|DATA|的文件中查找包含指定字符串的数据名称,并在函数外打印找到的名称。该函数接收文件描述符、目标字符串和存储结果的findReturn结构体(包含char**类型的findNames指针数组及数组大小size)作为参数。问题在于,当调用realloc()扩容findNames数组时,已存储在数组中的指针会丢失,导致程序运行出现段错误。
结构体定义
typedef struct{ int size ; char **findNames ; }findReturn;
函数实现
int find(int *fd,char *namepart,findReturn *findResults){ int i = 2 ; int j = 0; int dataSize ; int filesize ; char name[255]; char **temp ; errno = 0 ; if(*fd == -1){ return MISSING_DB ; } filesize = lseek(*fd,0,SEEK_END); lseek(*fd,2,SEEK_SET); while(i < filesize){ read(*fd,name + j,1); i++ ; if(name[j] == '\0'){ if(stringFinder(namepart,name) == SUCCESS){ (findResults->size)++; temp = (char **)realloc(findResults->findNames,findResults->size); if(temp != NULL){ findResults->findNames = temp ; findResults->findNames[findResults->size - 1] = (char*)malloc(strlen(name) * sizeof(char) + 1); strcpy(findResults->findNames[findResults->size - 1],name); } else{ (findResults->size)--; } } read(*fd,&dataSize,sizeof(int)); i += sizeof(int) ; i += dataSize ; lseek(*fd,i,SEEK_SET); j = 0; } else{ j++ ; } } if(errno != 0){ return FAIL ; } return SUCCESS ; }
main函数调用代码
case 'f':{ scanf(" %s", namepart); returnValue = find(&databaseFd,namepart,&findResults) ; if(findResults.findNames != NULL){ printf("\n##\n"); for(i=0; i < findResults.size; i++){ printf("%s\n", findResults.findNames[i]); } } else if(returnValue == MISSING_DB){ fprintf(stderr,"No open db file.\n"); } else if(returnValue == FAIL){ perror("\nUnexpected Error"); return 42 ; } break ;
示例场景
调用函数时输入查找字符串"ile",文件内容为:
00000000: 4442 6669 6c65 3100 0d00 0000 4865 6c6c DBfile1.....Hell 00000010: 6f0a 576f 726c 6421 0a66 696c 6532 000d o.World!.file2.. 00000020: 0000 0048 656c 6c6f 0a57 6f72 6c64 210a ...Hello.World!.
预期输出应为:
## file1 file2
但实际出现段错误,错误信息如下:
==4234==ERROR: AddressSanitizer: SEGV on unknown address 0x00000000be30 (pc 0x000100faae10 bp 0x00016f22f220 sp 0x00016f22e960 T0) ==4234==The signal is caused by a UNKNOWN memory access. #0 0x100faae10 in __sanitizer::internal_strlen(char const*)+0x4 (libclang_rt.asan_osx_dynamic.dylib:arm64e+0x56e10) #1 0x100f72034 in wrap_printf+0x8c (libclang_rt.asan_osx_dynamic.dylib:arm64e+0x1e034) #2 0x100bd3360 in main project3.c:57 #3 0x193ce7f24 (<unknown module>)
调试发现:
首次存储名称后,指针正常:
(lldb) p findResults->findNames[0] (char *) $2 = 0x0000000102300710 "file1"
调用realloc()后,指针丢失:
(lldb) p temp[0] (char *) $5 = 0x000000000000be10 "" (lldb) p findResults->findNames[0] (char *) $6 = 0x000000000000be10 ""
问题解决
核心错误是**realloc的内存大小计算错误**:你当前只分配了findResults->size字节的空间,但findNames是char**类型的数组,每个元素是一个指针(64位系统下占8字节),需要分配的是findResults->size * sizeof(char*)字节,而非单纯的findResults->size字节。
当分配的空间远小于实际需求时,会触发内存越界覆盖,导致之前存储的指针地址丢失,最终引发段错误。
修复步骤
修正
realloc的内存大小计算
修改find函数中realloc的调用代码:// 修正为:数组元素数量 × 单个指针的大小 temp = (char **)realloc(findResults->findNames, findResults->size * sizeof(char*));确保结构体初始值正确
在调用find函数前,必须初始化findReturn结构体,避免realloc处理野指针:findReturn findResults = {0}; // 自动将size设为0,findNames设为NULL
修复后关键代码片段
if(stringFinder(namepart,name) == SUCCESS){ (findResults->size)++; // 修正内存大小计算 temp = (char **)realloc(findResults->findNames, findResults->size * sizeof(char*)); if(temp != NULL){ findResults->findNames = temp ; findResults->findNames[findResults->size - 1] = (char*)malloc(strlen(name) * sizeof(char) + 1); strcpy(findResults->findNames[findResults->size - 1],name); } else{ (findResults->size)--; } }
内容的提问来源于stack exchange,提问作者Dimitris Papadimitriou
相关产品推荐
相关产品推荐

