【问题标题】:Segmentation fault in C (generating strings, error occurs while I check for duplicates)C 中的分段错误(生成字符串,检查重复项时发生错误)
【发布时间】:2014-12-02 22:33:03
【问题描述】:

这是一个程序,它按照某些规则生成诸如“aaabaabaaa”(或只是空字符串)之类的单词,一切正常,它生成它,按大小排序,然后按字母顺序但是当我实现阻止生成相同单词的部分时给我“分段错误(核心转储)”

我的问题是什么原因造成的,我该如何解决?

(我在 Ubuntu 14.04 上通过 gcc 编译器使用 Code::Blocks)

整个程序

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

void bsas(int n, char **words);

void as(int n, char **words) {
        int rn = rand();
        strcat(words[n], "a");
        if(rn % 3 == 0) as(n, words);
        if(rn % 3 == 1) bsas(n, words);
}

void bsas(int n, char** words){
        int rn, j;
        for(j=0; j<2; j++){
                if(j == 0)
                        strcat(words[n], "b");
                else
                        strcat(words[n], "a");
                rn = rand();
                if(rn % 3 == 0) as(n, words);
                if(rn % 3 == 1) bsas(n, words);
        }
}

static int compareCombo(const void *  a, const void * b){
        if (strlen(*(const char **) a) < strlen(*(const char **) b))
                return -1;
        else if (strlen(*(const char **) a) > strlen(*(const char **) b))
                return 1;
        else
                return strcmp (*(const char **) a, *(const char **) b);
}

int main()
{
        int rnum = 0, i, j, n;
        char** words;
        srand(time(NULL));
        system("clear");
        printf("\n Opis gramatyki: \n S->aS|bSaS|ε \n");
        getchar();
        printf("Ile chesz wygenerowac lancuchow? "); /*means how much words do you want to generate*/
        scanf("%d", &n);
        words = (char**) malloc(n*sizeof(char*));
        for (i = 0; i < n; i++)
        {
                words[i] = (char*) malloc(40000*sizeof(char));
        }

        for(i=0; i<n; i++){
                rnum = rand();
                if(rnum % 3 == 0) as(i, words);
                if(rnum % 3 == 1) bsas(i, words);
                if(rnum % 3 == 2) ;
                /*:PROBLEM OCCURS when I add this: */
                **for(j = i-1; j >= 0; j--){
                        if(strcmp(words[i], words[j]) == 0){
                                words[i] = "";
                                i--;
                                break;
                        }
                }**
                /*
                   this should check if there are some duplicates among words
                   if there are any it should erase it, and try to generate it again
                 */
        }
        qsort (words, n, sizeof (const char *), compareCombo);
        for(i = 0; i < n; i++){
                printf("%d\t- %s\n", i+1, words[i]);
        }
        return 0;
}

出现错误的部分:

/*:PROBLEM OCCURS when I add this: */
            for(j = i-1; j >= 0; j--){
                if(strcmp(words[i], words[j]) == 0){
                    words[i] = "";
                    i--;
                    break;
                }
            }
            /*
            this should check if there are some duplicates among words
            if there are any it should erase it, and try to generate it again
            */

【问题讨论】:

    标签: c gcc segmentation-fault


    【解决方案1】:

    起初我回答说您在第一次迭代时访问 words[-1] 但后来看到您检查 j>=0.. 关于您的代码,我有 2 个 cmets: 分配每个单词后,请清除缓冲区 - 因为您 strcat 单词可能导致意外行为和内存损坏。 不要通过 words[i] = "" 清除重复的单词;使用:

    strcpy(words[i],"");
    

    这样您就不会丢失之前由 words[i] 指向的分配缓冲区

    【讨论】:

      【解决方案2】:

      代码中实际上有两个错误。

      if(rnum % 3 == 2) ; 行将保持 word[i] 未初始化。然后,您只能希望您分配的 40000 个字节中的一个是零。缓冲区中的某处很可能会出现零,但如果不是,strcmp 将运行超过缓冲区的末尾,从而导致未定义的行为。

      第二个问题是线

      words[i] = "";
      

      这将用一个指向一字节只读缓冲区的指针替换指向 40000 字节读/写缓冲区的指针。当您随后尝试使用asbsas 函数写入该缓冲区时,您将遇到分段错误。纠正问题的一种方法是使用以下行清除单词

      words[i][0] = '\0';
      

      但实际上,您根本不需要清除该单词,因为无论如何缓冲区都未初始化,并且您正在递减 i 以从列表中删除该单词。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-01-21
        • 2011-01-08
        • 2013-12-08
        • 1970-01-01
        • 2015-10-18
        • 2019-07-25
        相关资源
        最近更新 更多