请问为什么这段代码运行会显示SIGSEGV?
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#include <string.h>
int total=0;
struct index
{
char word[51];
struct index *ne;
};
struct conter
{
char word[51];
int n,pos[800000];
struct conter *ne;
};
unsigned int hash(char *str)
{
unsigned int ha=0;
char *p;
for(p=str; *p!='\0'; p++)
ha = 37*ha + *p;
return ha % 800000;
}
struct index *newindex(char* str)
{
int i;
struct index *p=(struct index*)malloc(sizeof(struct index));
p->ne=NULL;
for(i=0;str[i]!='\0';i++)
{
p->word[i]=str[i];
}
p->word[i]='\0';
return p;
}
void append(struct index *head,struct index *newElement)
{
struct index *p;
for(p=head;p->ne!=NULL;p=p->ne);
p->ne=newElement;
}
struct conter *newconter(char *str,int pos)
{
struct conter *p=(struct conter *)malloc(sizeof(struct conter));
p->ne=NULL;
p->n=1;
p->pos[0]=pos;
strcpy(p->word,str);
return p;
}
void count(struct conter *miss[],char *str,int pos)
{
unsigned int h=hash(str);
if(miss[h]==NULL)
{
miss[h]=newconter(str,pos);
total++;
return;
}
struct conter *p;
for(p=miss[h];p!=NULL;p=p->ne)
{
if(!strcmp(str,p->word))
{
p->pos[p->n++]=pos;
return;
}
}
p=newconter(str,pos);
total++;
p->ne=miss[h];
miss[h]=p;
}
int emp(const void *a, const void *b)
{
struct conter** t1=(struct conter * *)a;
struct conter** t2=(struct conter * *)b;
int n=(*t1)->n-(*t2)->n;
if(n)
return -n;
return strcmp((*t1)->word,(*t2)->word);
}
void printcon(struct conter * con, FILE * file)
{
int i;
fprintf(file,"%s %d %d", con->word, con->n, con->pos[0]);
for (i = 1; i < con->n; i++)
{
fprintf(file, " %d", con->pos[i]);
}
fprintf(file, "\n");
}
int main()
{
FILE *in,*out;
in=fopen("dictionary.txt","r");
char temp[51];
char t;
struct index *words[800000];
struct conter *miss[800000];
int i,o,pos;
unsigned int h;
for(i=0;i<800000;i++)
{
words[i]=NULL;
miss[i]=NULL;
}
while(!feof(in))
{
i=0;
do
{
t=fgetc(in);
if(t==EOF)
break;
}while(!((t>='A'&&t<='Z')||(t>='a'&&t<='z')));
do
{
if(t>='A'&&t<='Z')
t+='a'-'A';
temp[i]=t;
i++;
t=fgetc(in);
}while(((t>='A'&&t<='Z')||(t>='a'&&t<='z'))&&i<=50);
temp[i]='\0';
h=hash(temp);
if(words[h]==NULL)
words[h]=newindex(temp);
else
append(words[h],newindex(temp));
}
fclose(in);
in=fopen("article.txt","r");
pos=-1;
while(!feof(in))
{
i=0;
do
{
t=fgetc(in);
pos++;
if(t==EOF)
break;
}while(!((t>='A'&&t<='Z')||(t>='a'&&t<='z')));
o=pos;
do
{
if(t>='A'&&t<='Z')
t+='a'-'A';
temp[i]=t;
i++;
t=fgetc(in);
pos++;
}while(((t>='A'&&t<='Z')||(t>='a'&&t<='z'))&&i<=30);
temp[i]='\0';
h=hash(temp);
if(words[h]==NULL)
{
count(miss,temp,o);
continue;
}
struct index *p;
for(p=words[h];p!=NULL;p=p->ne)
{
if(!strcmp(temp,p->word))
break;
}
if(p==NULL)
{
count(miss,temp,o);
}
}
fclose(in);
out=fopen("misspelling.txt","w");
i=0;
o=0;
struct conter *a;
struct conter **missa=(struct conter * *)malloc(sizeof(struct conter*)*total);
for(i=0;i<10000;i++)
{
a=miss[i];
while(a!=NULL)
{
missa[o++]=a;
a=a->ne;
}
}
qsort(missa,total,sizeof(struct conter*),emp);
for(i=0;i<total;i++)
{
printcon(missa[i],out);
}
fclose(out);
return 0;
}
以下引用自GPT的回答:
这段代码中的SIGSEGV错误是由于内存访问越界引起的。在程序的最后,你定义了一个大小为total
的missa
数组,然后使用qsort
对其进行排序。但是,你没有为total
变量赋值,因此missa
数组的大小未知。接着,在for
循环中,你遍历了800,000个miss
数组元素,这会导致访问missa
数组时越界。
为了解决这个问题,你需要在程序中添加代码,将total
变量赋值为实际的值。在count
函数中,每当你添加一个新的conter
节点时,你可以增加对total
的计数。修改后的代码如下:
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#include <string.h>
int total = 0;
struct index
{
char word[51];
struct index *ne;
};
struct conter
{
char word[51];
int n, pos[800000];
struct conter *ne;
};
unsigned int hash(char *str)
{
unsigned int ha = 0;
char *p;
for (p = str; *p != '\0'; p++)
ha = 37 * ha + *p;
return ha % 800000;
}
struct index *newindex(char *str)
{
int i;
struct index *p = (struct index *)malloc(sizeof(struct index));
p->ne = NULL;
for (i = 0; str[i] != '\0'; i++)
{
p->word[i] = str[i];
}
p->word[i] = '\0';
return p;
}
void append(struct index *head, struct index *newElement)
{
struct index *p;
for (p = head; p->ne != NULL; p = p->ne);
p->ne = newElement;
}
struct conter *newconter(char *str, int pos)
{
struct conter *p = (struct conter *)malloc(sizeof(struct conter));
p->ne = NULL;
p->n = 1;
p->pos[0] = pos;
strcpy(p->word, str);
return p;
}
void count(struct conter *miss[], char *str, int pos)
{
unsigned int h = hash(str);
if (miss[h] == NULL)
{
miss[h] = newconter(str, pos);
total++;
return;
}
struct conter *p;
for (p = miss[h]; p != NULL; p = p->ne)
{
if (!strcmp(str, p->word))
{
p->pos[p->n++] = pos;
return;
}
}
p = newconter(str, pos);
total++;
p->ne = miss[h];
miss[h] = p;
}
int emp(const void *a, const void *b)
{
struct conter **t1 = (struct conter **)a;
struct conter **t2 = (struct conter **)b;
int n = (*t1)->n - (*t2)->n;
if (n)
return -n;
return strcmp((*t1)->word, (*t2)->word);
}
void printcon(struct conter
*con, FILE *file)
{
int i;
fprintf(file, "%s %d %d", con->word, con->n, con->pos[0]);
for (i = 1; i < con->n; i++)
{
fprintf(file, " %d", con->pos[i]);
}
fprintf(file, "\n");
}
int main()
{
FILE *in, *out;
in = fopen("dictionary.txt", "r");
char temp[51];
char t;
struct index *words[800000];
struct conter *miss[800000];
int i, o, pos;
unsigned int h;
for (i = 0; i < 800000; i++)
{
words[i] = NULL;
miss[i] = NULL;
}
while (!feof(in))
{
i = 0;
do
{
t = fgetc(in);
if (t == EOF)
break;
} while (!((t >= 'A' && t <= 'Z') || (t >= 'a' && t <= 'z')));
do
{
if (t >= 'A' && t <= 'Z')
t += 'a' - 'A';
temp[i] = t;
i++;
t = fgetc(in);
} while (((t >= 'A' && t <= 'Z') || (t >= 'a' && t <= 'z')) && i <= 50);
temp[i] = '\0';
h = hash(temp);
if (words[h] == NULL)
words[h] = newindex(temp);
else
append(words[h], newindex(temp));
}
fclose(in);
in = fopen("article.txt", "r");
pos = -1;
while (!feof(in))
{
i = 0;
do
{
t = fgetc(in);
pos++;
if (t == EOF)
break;
} while (!((t >= 'A' && t <= 'Z') || (t >= 'a' && t <= 'z')));
o = pos;
do
{
if (t >= 'A' && t <= 'Z')
t += 'a' - 'A';
temp[i] = t;
i++;
t = fgetc(in);
pos++;
} while (((t >= 'A' && t <= 'Z') || (t >= 'a' && t <= 'z')) && i <= 30);
temp[i] = '\0';
h = hash(temp);
if (words[h] == NULL)
{
count(miss, temp, o);
continue;
}
struct index *p;
for (p = words[h]; p != NULL; p = p->ne)
{
if (!strcmp(temp, p->word))
break;
}
if (p == NULL)
{
count(miss, temp, o);
}
}
fclose(in);
out = fopen("misspelling.txt", "w");
i = 0;
o = 0;
struct conter *a;
struct conter **missa = (struct conter **)malloc(sizeof(struct conter *) * total);
for (i = 0; i < 800000; i++)
{
a = miss[i];
while (a != NULL)
{
missa[o++] = a;
a = a->ne;
}
}
qsort(missa, total, sizeof(struct conter *
), emp);
for (i = 0; i < total; i++)
{
printcon(missa[i], out);
}
fclose(out);
return 0;
}
这样,missa
数组的大小就会正确地与total
相对应,并且不会导致内存访问越界错误。