C 使用动态内存分配功能返回时中止陷阱6

C 使用动态内存分配功能返回时中止陷阱6,c,buffer-overflow,sigabrt,dynamic-allocation,C,Buffer Overflow,Sigabrt,Dynamic Allocation,我在OSX Mavericks上使用Apple LLVM 5.1版(clang-503.0.40)调试C中的“Abort trap 6”错误时遇到问题。目标是构造一个数据结构word2class,该结构为num_words词汇表中的每个单词包含该单词所属的类ID数组(任意,但例如:名词、动词等,作为整数ID),以及它的逆类,class2word包含每个类的0您的代码有一些问题: 它无法编译,因为注释掉了几个{: if (A == NULL) { // handle allocation erro

我在OSX Mavericks上使用Apple LLVM 5.1版(clang-503.0.40)调试C中的“Abort trap 6”错误时遇到问题。目标是构造一个数据结构
word2class
,该结构为
num_words
词汇表中的每个单词包含该单词所属的类ID数组(任意,但例如:名词、动词等,作为整数ID),以及它的逆类
class2word
包含每个类的
0您的代码有一些问题:

  • 它无法编译,因为注释掉了几个
    {

    if (A == NULL) { // handle allocation error }
    
    我假设这只是一个转录错误

  • 您没有检查的返回以确保读取了两个参数。文件中的任何语法错误都可能导致损坏

  • 您从每行读取两个字段,
    index
    id
    ,但只使用第一个字段。第二个字段被忽略。此外,您从未在
    cur\u size
    数组中设置任何值,因此它在代码中始终为零

    因此,我要做一个假设:
    index
    是外部数组
    A
    中的索引,
    id
    是对应内部数组的索引,也就是说,您希望能够分配足够大的数组,使
    A[index][id]
    存在

  • <> LI>

    有一个算法问题:一个算法的大小是:代码大小>Max大小(index)< /代码>,如果它小于<代码> CurySosi[index ] < /C> >但不要认为 CursiSosi[index ] < /C> >两倍以上。您需要加倍大小并确保它大于<代码> ID+1 < < /P> 。

  • 您应该保留
    cur_size
    数组,以便稍后检查越界索引

  • calloc
    用零填充内存,但新分配部分的值不确定

  • 在我的平台上,对于第一个参数,
    long-long
    是64位的,但是
    calloc
    realloc
    接受
    size\t
    ,因此我看到了几个“从'\u int64'到'size\t'的转换”,可能会丢失数据”错误。您应该检查以确保
    calloc
    在您的平台上使用
    long

  • 因此,问题1-6的修复可能如下所示:

    long long **A = NULL; // global array of pointers to long longs
    long long *A_cur_size_array = NULL;
    
    long long N = 1000; // for exax1mple
    
    // If your platform has a predefined version of "max", use it instead.
    static long long max_long_long(long long a, long long b)
    {
        // If your platform has a predefined version of "max", use it instead.
        return (a > b) ? a : b;
    }
    
    void construct_A(char *fname) 
    {
        FILE *fin = fopen(fname, "r");
        long long index, id;
        long long *max_size_array;
    
        A_cur_size_array = calloc(N, sizeof(int));
        A = calloc(N, sizeof(long long *));
        max_size_array = calloc(N, sizeof(int));   // init to 0
    
        if (A == NULL || max_size_array == NULL || A_cur_size_array == NULL) 
        { 
            // handle allocation error 
        }
        while (!feof(fin)) 
        {
            if (fscanf(fin, "%lld\t%lld\n", &index, &id) != 2)
            {
                printf("File format error.\n"); 
                exit(1); 
            }
            if (index < 0 || index >= N) 
            { 
                printf("BOUNDS ERROR\n"); 
                exit(1); 
            }
            if (id < 0)
            {
                printf("BOUNDS ERROR\n"); 
                exit(1); 
            }
            if (id >= A_cur_size_array[index])
            {
                A_cur_size_array[index] = id + 1;
                if (A_cur_size_array[index] >= max_size_array[index]) 
                {
                    long long new_max_size = max_long_long(id + 1, 2 * max_size_array[index]);
                    long long i;
                    // dynamically allocate a large enough array of long longs
                    A[index] = (long long*)realloc(A[index], new_max_size * sizeof(long long));
                    if (A[index] == NULL) 
                    { 
                        // handle allocation error 
                    }
                    for (i = max_size_array[index]; i < new_max_size; i++)
                        A[index][i] = 0;
                    max_size_array[index] = new_max_size;
                }
            }
        }
        fclose(fin);
        free(max_size_array);
    }
    
    long long**A=NULL;//指向long long的指针的全局数组
    long long*A_cur_size_array=NULL;
    long N=1000;//例如
    //如果您的平台具有预定义版本的“max”,请改用它。
    静态长最大长(长a、长b)
    {
    //如果您的平台具有预定义版本的“max”,请改用它。
    返回(a>b)?a:b;
    }
    无效构造(char*fname)
    {
    文件*fin=fopen(fname,“r”);
    长索引,id;
    long long*max_size_数组;
    A_cur_size_数组=calloc(N,sizeof(int));
    A=calloc(N,sizeof(long*);
    max_size_array=calloc(N,sizeof(int));//init到0
    if(A==NULL | | | max_size_array==NULL | | A_cur_size_array==NULL)
    { 
    //句柄分配错误
    }
    而(!feof(fin))
    {
    如果(fscanf(fin,%lld\t%lld\n,&index,&id)!=2)
    {
    printf(“文件格式错误。\n”);
    出口(1);
    }
    如果(索引<0 | |索引>=N)
    { 
    printf(“边界错误\n”);
    出口(1);
    }
    if(id<0)
    {
    printf(“边界错误\n”);
    出口(1);
    }
    if(id>=A\u cur\u size\u数组[索引])
    {
    当前大小数组[索引]=id+1;
    if(当前大小数组[索引]>=max\u大小数组[索引])
    {
    long long new_max_size=max_long_long(id+1,2*max_size_数组[索引]);
    龙龙我;
    //动态分配足够大的长long数组
    A[index]=(long-long*)realloc(A[index],新的最大尺寸*长尺寸);
    如果(A[索引]==NULL)
    { 
    //句柄分配错误
    }
    对于(i=max_size_数组[索引];i
    问题实际上在于用于读取单词和类的fscanf()行。我对我发布的代码做了一个简化:在我的实际代码中,word2class存储为每行的
    条目。也就是说,我将单词存储为字符串,而不是长ID。然后,我将单词读入
    字符[MAX\u STRING]
    buffer,然后查找其长字id

    问题是有些单词比MAX_STRING-1长,这会覆盖以空结尾的字符串
    word
    ,从而导致seg错误。由于我使用了
    -Ofast
    优化标志,以某种方式将segfault错误更改为
    Abort trap 6
    错误,问题进一步加剧我编译时没有使用优化标志,我意识到这是一个seg错误,我可以使用
    valgrind
    gdb
    跟踪到fscanf()函数

    解决方案是将最大长度添加到%s fscanf格式字符串中,如下所示:

    #define MAX_STRING 100
    #define MAX_STRING_S "99"  // careful not to overwrite terminating null
    
    ...
    
    // in BuildDataStruct()
    char word[MAX_STRING];
    if (fscanf(fin, "%" MAX_STRING_S "s\t%lld", word, &class) != 2) {
      printf("Format error in class_file\n");
      // continue or exit
    }
    

    这段代码现在可以正确地识别class_文件中的格式错误,并且可以正常工作。

    这是导致问题的实际代码吗?因为1)它无法编译;2)您在读取后从未使用
    id
    ;3)您从未将任何值写入
    cur_size
    数组。您能解释一下是什么吗你想做什么?@dbc不,这是一个简单的工作示例。但我已经更新了我的问题,以显示我正在使用的实际代码,并解释我试图用代码完成的任务。T
    long long **A = NULL; // global array of pointers to long longs
    long long *A_cur_size_array = NULL;
    
    long long N = 1000; // for exax1mple
    
    // If your platform has a predefined version of "max", use it instead.
    static long long max_long_long(long long a, long long b)
    {
        // If your platform has a predefined version of "max", use it instead.
        return (a > b) ? a : b;
    }
    
    void construct_A(char *fname) 
    {
        FILE *fin = fopen(fname, "r");
        long long index, id;
        long long *max_size_array;
    
        A_cur_size_array = calloc(N, sizeof(int));
        A = calloc(N, sizeof(long long *));
        max_size_array = calloc(N, sizeof(int));   // init to 0
    
        if (A == NULL || max_size_array == NULL || A_cur_size_array == NULL) 
        { 
            // handle allocation error 
        }
        while (!feof(fin)) 
        {
            if (fscanf(fin, "%lld\t%lld\n", &index, &id) != 2)
            {
                printf("File format error.\n"); 
                exit(1); 
            }
            if (index < 0 || index >= N) 
            { 
                printf("BOUNDS ERROR\n"); 
                exit(1); 
            }
            if (id < 0)
            {
                printf("BOUNDS ERROR\n"); 
                exit(1); 
            }
            if (id >= A_cur_size_array[index])
            {
                A_cur_size_array[index] = id + 1;
                if (A_cur_size_array[index] >= max_size_array[index]) 
                {
                    long long new_max_size = max_long_long(id + 1, 2 * max_size_array[index]);
                    long long i;
                    // dynamically allocate a large enough array of long longs
                    A[index] = (long long*)realloc(A[index], new_max_size * sizeof(long long));
                    if (A[index] == NULL) 
                    { 
                        // handle allocation error 
                    }
                    for (i = max_size_array[index]; i < new_max_size; i++)
                        A[index][i] = 0;
                    max_size_array[index] = new_max_size;
                }
            }
        }
        fclose(fin);
        free(max_size_array);
    }
    
    #define MAX_STRING 100
    #define MAX_STRING_S "99"  // careful not to overwrite terminating null
    
    ...
    
    // in BuildDataStruct()
    char word[MAX_STRING];
    if (fscanf(fin, "%" MAX_STRING_S "s\t%lld", word, &class) != 2) {
      printf("Format error in class_file\n");
      // continue or exit
    }