C 使用动态内存分配功能返回时中止陷阱6
我在OSX Mavericks上使用Apple LLVM 5.1版(clang-503.0.40)调试C中的“Abort trap 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
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
}