我收到了这段代码:
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <dirent.h>
#include <stdlib.h>
#define W 1031
#define B 256
struct position {
int x;
int y;
struct position *next;
};
struct wordFiles {
char *fileName;
struct position *cor;
struct wordFiles *next;
};
struct wordTree {
char *word;
struct wordFiles *files;
struct wordTree *left;
struct wordTree *right;
};
struct wordTree *hashTable[W];
typedef struct wordFiles *files_Ptr;
typedef struct position *pos_ptr;
typedef struct wordTree *wordTreePtr;
long int power(int a, long b){
long int value,i;
value = 1;
for (i = 0; i < b; i++)
value *= a;
return value;
}
int hashValue (char *word){
long int i=0,s=0,n;
n = strlen(word);
for (i=0; i<n; i++){
s += power(B,n-i-1) * word[i];
}
return (s%W);
}
void readword(char *word , FILE *curr_file, int *x_axis, int *y_axis, int *newline, int *endfile){
char c;
c = (char) malloc(sizeof(char));
if ((fscanf(curr_file, "%s", word))!=1 || fscanf(curr_file, "%c", &c)!=1){
*endfile=1;
}
*x_axis += strlen(word);
if (strlen(word)==1 && c=='\n'){
*newline = 1;
return;
}
if (c==' ') {
*x_axis +=1;
}
else if (c=='\n') {
*newline = 1;
}
return;
}
void coordinateslistInsert (pos_ptr *lp,int x, int y){
pos_ptr prev,curr;
prev = NULL;
curr = *lp;
while (curr != NULL){
prev = curr;
curr = curr->next;
}
pos_ptr n = (pos_ptr) malloc(sizeof(struct position));
if (n == NULL) {
printf("Out of memory\n");
return;
}
n->next = NULL;
n->x = x;
n->y = y;
if (prev==NULL) {
*lp = n;
}
else {
prev->next = n;
}
return;
}
void filelistInsert (files_Ptr *lp, char *filename, int x, int y, int k) {
files_Ptr prev, curr;
prev = NULL;
curr = *lp;
if ( curr!=NULL && k == 1 && strcmp(curr->fileName, filename) == 0 ){
coordinateslistInsert(&(*lp)->cor, x, y);
return;
}
while (curr != NULL){
prev = curr;
curr = curr->next;
}
files_Ptr n = (files_Ptr)malloc(sizeof(struct wordFiles));
if (n == NULL) {
printf("Out of memory\n");
return;
}
n->fileName = filename;
n->next = NULL;
coordinateslistInsert (&(*n).cor , x ,y);
if (prev==NULL) {
*lp = n;
}
else {
prev->next = n;
}
return;
}
void treeBalancedInsert (wordTreePtr *curr_tree, char *word, char *filename, int x, int y) {
int k=0;
if (*curr_tree == NULL) {
*curr_tree =(wordTreePtr) malloc(sizeof(struct wordTree));
if (*curr_tree == NULL) {
printf("Out of memory\n");
exit(1);
}
(*curr_tree)->word=malloc(30*sizeof(char));
(*curr_tree)->left = (*curr_tree)->right = NULL;
strcpy((*curr_tree)->word,word);
filelistInsert (&(*curr_tree)->files , filename,x,y,k);
}
else {
if (strcmp((*curr_tree)->word,word) == 0){
k=1;
filelistInsert (&(*curr_tree)->files , filename,x,y,k);
return;
}
else if (strcmp((*curr_tree)->word,word) < 0)
treeBalancedInsert(&(((*curr_tree)->left)), word, filename, x, y);
else
treeBalancedInsert(&(((*curr_tree)->right)), word, filename,x ,y);
}
}
void search (char *word, int h_value, struct wordTree *hashtable[]){
wordTreePtr n = hashTable[h_value];
while(n!=NULL && strcmp ( n->word , word ) !=0){
if (strcmp ( n->word , word ) > 0 ){
n = n->right;
}
else if(strcmp ( n->word , word ) < 0){
n = n->left;
}
}
if (n==NULL){
printf("NOT FOUND");
return;
}
printf("%s\n",n->word);
files_Ptr k = n->files;
while (k!=NULL) {
pos_ptr q = k->cor ;
while (q!=NULL) {
printf("%s(%d,%d)\n",k->fileName,q->y,q->x);
q = q->next;
}
k = k->next;
}
return;
}
int main(int argc, char *argv[])
{
int j,i;
for (i=0; i<W; i++){
hashTable[i] = NULL;
}
for (j=1; j<argc; j++){
FILE *curr_file=fopen(argv[j], "r+");
int h_value = 0, x_axis = 1, y_axis=1, newline=0,endfile=0;
if (curr_file == NULL) {
perror("Error: ");
return (-1);
}
char *word=NULL , *filename;
filename = (char *) malloc(30*sizeof(char));
filename = argv[j];
while (endfile!=1){
word = (char *) malloc(20*sizeof(char));
readword(word, curr_file, &x_axis, &y_axis, &newline, &endfile);
h_value = hashValue(word);
treeBalancedInsert(&hashTable[h_value], word, filename, x_axis-(unsigned)strlen(word)-1, y_axis);
if (newline==1){
y_axis +=1;
x_axis=1;
newline=0;
}
}
fclose(curr_file);
free(word);
}
char *wordToSearch;
wordToSearch = (char *) malloc(20*sizeof(char));
scanf("%s",wordToSearch);
search(wordToSearch,hashValue(wordToSearch),hashTable);
return 0;
}
它写在Mac上,据说可行。但是当我在我的机器上编译并运行时,它就不会。 它的作用是将文本文件作为参数并对二进制树中的单词进行排序,这些单词根据单词的哈希值放置在哈希表中。然后你可以输入一个单词,它会告诉你它出现的坐标和哪些文件。
无论如何,eclipse上的调试一步一步地停留在filelistInsert的(curr = curr-&gt; next),代码块显示了另外两个问题,一个在treebalancedinsert函数中,它调用filelistinsert函数,在main当它需要treebalanceinsert函数时。 我无法找到filelistinsert中的错误,并且时间紧迫。 (我知道这是一个非常糟糕的问题,但我很绝望)
答案 0 :(得分:3)
变化:
char c;
c = (char) malloc(sizeof(char));
到
char c;
注意:这是程序中的错误,但它并不能解释程序崩溃的原因。
其他地方:
filename = (char *) malloc(30*sizeof(char));
filename = argv[j];
这是内存泄漏,如果您假设filename
是30
个字符数组,那么您可能会遇到麻烦。
答案 1 :(得分:1)
我看到了几个问题。
在我头脑中发出警报的第一件事就是像
这样的线条(*curr_tree)->word=malloc(30*sizeof(char));
和
word = (char *) malloc(20*sizeof(char));
如果您从输入文件中读取超过19个字符的任何单词,您将会出现缓冲区溢出,这会在某些时候引起胃灼热。我有理由相信这是你问题的根源(当我在自己的源文本上运行这个程序时,我在阅读“(*curr_tree)->word=malloc(30*sizeof(char));
”后开始得到段错误,很可能是因为我们溢出了20个字符的缓冲区并且别人的东西。
readword
函数应根据输入文件的内容决定为单词分配多少内存。这意味着你将不得不使readword
函数更聪明一些,并让它在读取输入时分配/重新分配缓冲区,如下所示:
void readword(char **word , FILE *curr_file, int *x_axis, int *y_axis, int *newline, int *endfile){
int c;
size_t bufLen = 0;
const size_t bufExtent=10;
size_t idx = 0;
*word = NULL;
/**
* Read input one character at a time until we see a space or EOF
*/
while ( ( c = fgetc( curr_file ) ) != EOF && !isspace( c ))
{
/**
* Are we at the end of our buffer?
*/
if ( idx == bufLen )
{
/**
* Extend the buffer
*/
char *tmp = realloc( *word, bufLen + bufExtent );
if ( tmp )
{
bufLen += bufExtent;
*word = tmp;
}
else
{
fprintf( stderr, "readword: Could not allocate memory to extend word\n" );
return;
}
}
(*word)[idx++] = c;
}
/**
* If we read a string, 0-terminate it
*/
if ( *word )
{
(*word)[idx] = 0;
*x_axis += strlen(*word);
}
然而,即便如此,我仍然会遇到运行时错误,因此此代码中还有其他时间炸弹。
然后是这个:
filename = (char *) malloc(30*sizeof(char));
filename = argv[j];
这不会将argv[j]
的内容复制到刚刚分配的内存中;相反,它将指针值argv[j]
分配给filename
,覆盖指向您刚刚分配的内存的指针,从而导致内存泄漏。再次,你正在为文件名选择一个任意长度。尝试以下内容:
filename = malloc( strlen( argv[j] ) + 1 );
strcpy( filename, argv[j] );
Style nit:
隐藏typedef后面的指针类型是 not ,除非该类型是不透明的,并且永远不会直接进行引导。如果我在对象声明中看到*
,我立即知道它应该如何在表达式中使用。使用foo_ptr
typedef可能会使代码扫描更好一些,但它会阻碍IMO的低调。多年来我一直被这种方式所困扰,以至于我一般都避免使用typedef。