当我使用 realloc() 时,我在 malloced 表中的指针丢失了

问题描述 投票:0回答:1

在下面的代码中,我尝试查找存储在包含给定字符串的文件中的数据名称,然后打印在函数外部找到的名称。文件中的数据以|数据的名称|数据的字节数|数据|的形式存储。该函数接收文件的文件描述符作为参数,我们试图在文件名称中找到的字符串和一个结构,该结构包含一个表,其中将存储找到的名称 (** findNames) 以及该表的大小桌子 。 我遇到的问题是,当函数 realloc 用于增加表的大小时,已经存储在那里的指针消失了。

结构:

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 ;
}

主要用途:

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 ;

这是一个例子:

我启动了程序,通过main调用了find函数 给出一个我希望函数找到的字符串

f 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"

重新分配后:

在临时指针中

(lldb) p temp[0]
(char *) $5 = 0x000000000000be10 ""

然后在主桌上

(lldb) p findResults->findNames[0]
(char *) $6 = 0x000000000000be10 ""
c memory memory-management
1个回答
2
投票

一个显而易见的问题是

realloc
调用重新分配
findResults->findNames
正在分配错误大小的内存。它为每个元素分配一个字节,但分配的是元素数乘以每个元素的大小。每个元素的大小可以表示为
sizeof(char *)
sizeof(*findResults->findNames)
sizeof(findResults->findNames[0])
realloc
返回一个
void *
。无需将结果转换为 C 中不同的指针类型。

            temp = realloc(findResults->findNames,findResults->size*sizeof(*findResults->findNames));

如果

findResults->findNames
指向代码中其他地方
malloc
分配的内存,那也需要是正确的大小。

尽管代码正确地检查了

realloc
调用是否成功,但它没有检查后续的
malloc
调用。如果
findResults->size
realloc
调用都成功,我建议只增加
malloc

            if(stringFinder(namepart,name) == SUCCESS){
                temp = realloc(findResults->findNames,
                               (findResults->size + 1) * sizeof(char*));
                if(temp != NULL){
                    findResults->findNames = temp ;
                    findResults->findNames[findResults->size] = 
                                malloc(strlen(name) + 1);
                    if (findResults->findNames[findResults->size] != NULL){
                        strcpy(findResults->findNames[findResults->size],name);
                        findResults->size++; 
                    }
                }
            }
© www.soinside.com 2019 - 2024. All rights reserved.