You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用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字节。

当分配的空间远小于实际需求时,会触发内存越界覆盖,导致之前存储的指针地址丢失,最终引发段错误。

修复步骤

  1. 修正realloc的内存大小计算
    修改find函数中realloc的调用代码:

    // 修正为:数组元素数量 × 单个指针的大小
    temp = (char **)realloc(findResults->findNames, findResults->size * sizeof(char*));
    
  2. 确保结构体初始值正确
    在调用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.22 10:27:06