0

我知道分段错误是什么,我不需要知道它的定义:) 我只需要知道它在我的代码中来自哪里。该程序旨在获取单词作为输入,从文本文件中读取,写入单独的文本文件,然后打印读取文件和输入中的所有单词。

#include<stdio.h>
#include <string.h>
#include <stdlib.h>

int main(int argc, char*argv[]){
    FILE *read;
    FILE *write;
    char **list=malloc(sizeof(char*));
    char **oldlist=malloc(sizeof(char*));
    char *oldword=malloc(sizeof(char));
    char exit[]="end";
    int a, c, r=0, w=0, n=0, z= 0, y=0, d=0, g=0;

//check arg
for(a=0; a<argc; a++){
    if(strcmp(argv[a], "-r")==0){
        r =1;
        read=fopen("read.txt", "r");
    }
    else if(strcmp(argv[a], "-w")==0){
        w =1;
        write=fopen("write.txt", "w");
    }   
}
if(r==0 && w==0){
    printf("Error: Invalid Command.\n");
}
printf("Read = %d | Write = %d\n", r, w);

//getwords
printf("Enter your words: ");
while(1){
char *word=malloc(sizeof(char));
list=realloc(list, sizeof(char*)*(z+10));
word=realloc(word, sizeof(char)*(z+10));
scanf("%s", word);
              if (strcmp(word,exit)==0){
        break;
              }
              else{
                *(list+z) = word;
            z++;
          }
}   

//read
if (r==1){
    do{
        while(1){
            *(oldword+d)=fgetc(read);
            d++;
        }
    }while(feof(read) != 0);            
}
*(oldword+(d-1))="\0";

printf("Your words are:\n");
            puts(oldword);
    for(c=0; c<n; c++){
            puts(*(list+c));
    }

    //write
    if (w ==1){
        if(w==1){
            fputs(*(oldlist+c),write);
        }
    for(c=0; c<n; c++){
            fputs(*(list+c),write); 
        }
    }
    //end
    free(list);
    fclose(read);
    fclose(write);          
    return 0;

}
4

2 回答 2

3

您为单词分配 1 个字节:

char *word=malloc(sizeof(char));

然后,您将一个字符串读入其中。这是缓冲区溢出,会导致极大的不快(以及 Stack Overflow 上的此类问题)。具体来说,读取长字将践踏“堆”(由等人控制的数据空间)中的控制信息,malloc()并扰乱用于确定哪些空间可供使用而哪些不可用的数据。什么构成“长词”取决于系统;从技术上讲,除了空字符串(只是一个终端'\0')之外的任何字符串都太长了,但是如果单词是 7 个字节或更少,你可能会逃脱蓝色谋杀。


但是 realloc 不应该处理内存问题吗?我正在尝试使字符串输入不受限制。

嗯……作为一种做生意的方式,这有点奇怪,但realloc()word你实际使用它之前,你可以解决一些问题。

word具体来说,在循环第一次溢出内存分配之前,您最多可以读取 9 个字符(包括 9 个字符) 。但是,这距离使其“无限制”还有很长的路要走,而使其无限制并非易事。一个问题是%s在空白字符处停止扫描;总的来说,这对你有利。另一个是您似乎将其z用作您输入的字符串数量的计数,以及您可以输入的字符串的长度。list如果列表超过 10 个条目,则不会重新分配。

您仍然可能遇到各种问题。例如,您对 oldword 的处理不会执行额外的 realloc();它只分配一个字节。然后你有一个完全无界的无限循环(如果它被输入的话)。这个循环是一场灾难:

    while(1){
        *(oldword+d)=fgetc(read);
        d++;
    }
于 2013-03-16T02:39:53.150 回答
2

如果您在(g 标志)上进行调试并在 valgrind 下运行,它应该可以很好地说明它为什么会出现段错误。

于 2013-03-16T02:39:15.293 回答