如何在没有分段错误的情况下在 Ubuntu 中将我的函数作为命令行调用?

问题描述 投票:0回答:2

我有一个名为 unscramble 的代码,它接受两个文件 Jumbled.txtdictionary.txt 并查找两个文件中是否有任何单词包含相同的字符,例如,这是

的示例输入
Jumbled.txt:                                  
Hello
Wassup
Rigga
Boyka
Popeye

dictionary.txt:
olleH
Yello
elloH
lloeH
aggiR
ggiRa
giRag
yokaB
Bakoy
kaBoy
eyePop
poePye

上面代码的输出是:

Hello: olleH elloH lloeH
Wassup: NO MATCHES
Rigga: aggiR ggiRa giRag
Boyka: yokaB Bakoy kaBoy
Popeye: eyePop poePye

这是我试图解决它的代码:

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

#define MAX_WORD_LENGTH 50
#define MAX_NUM_WORDS 500000

int compare_char(const void *a, const void *b) {
    return *(char*)a - *(char*)b;
}

void sort_word(char *word) {
    qsort(word, strlen(word), sizeof(char), compare_char);
}

int is_valid_word(char *jumbled_word, char *word) {
    char sorted_jumbled_word[MAX_WORD_LENGTH];
    char sorted_word[MAX_WORD_LENGTH];
    strcpy(sorted_jumbled_word, jumbled_word);
    strcpy(sorted_word, word);
    sort_word(sorted_jumbled_word);
    sort_word(sorted_word);
    return strcmp(sorted_jumbled_word, sorted_word) == 0;
}

int main(int argc, char *argv[]) {
    if (argc != 3) {
        printf("Usage: unscramble <dictionary> <jumbles>\n");
        exit(1);
    }
    char *dict_filename = argv[1];
    char *jumbles_filename = argv[2];

    char dictionary[MAX_NUM_WORDS][MAX_WORD_LENGTH];
    int num_words = 0;
    FILE *dict_file = fopen(dict_filename, "r");
    if (dict_file == NULL) {
        printf("Error: Could not open dictionary file %s\n", dict_filename);
        exit(1);
    }
    char line[MAX_WORD_LENGTH];
    while (fgets(line, sizeof(line), dict_file) != NULL) {
        // Remove trailing newline character
        line[strcspn(line, "\n")] = '\0';
        // Copy word into dictionary
        strcpy(dictionary[num_words], line);
        num_words++;
    }
    fclose(dict_file);

    // Loop over jumbled words file
    FILE *jumbles_file = fopen(jumbles_filename, "r");
    if (jumbles_file == NULL) {
        printf("Error: Could not open jumbled words file %s\n", jumbles_filename);
        exit(1);
    }
    while (fgets(line, sizeof(line), jumbles_file) != NULL) {
        line[strcspn(line, "\n")] = '\0';
        char sorted_word[MAX_WORD_LENGTH];
        strcpy(sorted_word, line);
        sort_word(sorted_word);
        int found_match = 0;
        for (int i = 0; i < num_words; i++) {
            if (is_valid_word(sorted_word, dictionary[i])) {
                if (!found_match) {
                    printf("%s:", line);
                    found_match = 1;
                }
                printf(" %s", dictionary[i]);
            }
        }
        if (!found_match) {
            printf("%s: NO MATCHES", line);
        }
        printf("\n");
    }
    fclose(jumbles_file);

    return 0;
}

但是,将其转换为可执行格式并检查同一目录中是否存在 Jumbled.txt AND dictionary.txt 后,我收到此错误消息:

xxxxxxxxx@LAPTOP-xxxxxxxx:~$ gcc -Wall -W -pedantic -o unscramble unscramble.c  
xxxxxxxxx@LAPTOP-xxxxxxxx:~$ vim Jumbled.txt
xxxxxxxxx@LAPTOP-xxxxxxxx:~$ vim dictionary.txt
xxxxxxxxx@LAPTOP-xxxxxxxx:~$ vim unscramble.c
xxxxxxxxx@LAPTOP-xxxxxxxx:~$ ./unscramble dictionary.txt Jumbled.txt
Segmentation fault
xxxxxxxxx@LAPTOP-xxxxxxxx:~$ 

我应该改变什么,我的问题是什么?

c ubuntu gcc command-line
2个回答
1
投票

第一步是在调试器中运行您的程序以找出它的段错误:

Program received signal SIGSEGV, Segmentation fault.
0x00005555555552c6 in main (argc=<error reading variable: Cannot access memory at address 0x7ffffe82657c>, argv=<error reading variable: Cannot access memory at address 0x7ffffe826570>) at 1.c:26
26      int main(int argc, char *argv[]) {

这很奇怪,即内存损坏,甚至在开始之前,所以您查看分配并看到:

    char dictionary[MAX_NUM_WORDS][MAX_WORD_LENGTH];

500k * 50 字节或 25 MB。我系统上的默认堆栈是 8 MB。要么减少常量,这样您就不会使用超过 8 MB,要么使用 malloc() 来分配堆上的空间。我在这里使用一维数组:

    char (*dictionary)[MAX_WORD_LENGTH] = malloc(MAX_NUM_WORDS * sizeof(*dictionary));
    if(!dictionary) {
        printf("malloc failed\n");
        return 1;
    }

现在返回:

Hello: olleH elloH lloeH
Wassup: NO MATCHES
Rigga: aggiR ggiRa giRag
Boyka: yokaB Bakoy kaBoy
Popeye: eyePop poePye

0
投票

您将 dictionary 数组放入 main 中,因此该数组将存在于 main 的函数堆栈中;这大约是堆栈上的 23.8M,超过了几乎所有操作系统的通常堆栈大小限制(Linux 上为 8M)。

如果您仍然想使用二维数组,请将此数组作为全局变量放在 main 之外,这样它就不会再存在于 main 的栈帧中了。或者使用 malloc 分配这个数组,所以它存在于程序的堆中。请参阅堆栈和堆是什么以及在哪里?

© www.soinside.com 2019 - 2024. All rights reserved.