如何在命令行中调用我的函数而不发生分段错误?

huangapple go评论60阅读模式
英文:

How can I call my function as a command line without segmentation fault?

问题

It appears you've made some improvements to your code, but you're still encountering a segmentation fault issue. The code you provided looks mostly correct. However, there's a small issue with the printf statements where you are using HTML entities (") for double quotes. You should replace these with regular double quotes (").

Here's the corrected code:

#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 *(const char*)a - *(const char*)b;
}

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

int is_valid_word(const char *jumbled_word, const 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");
        return 1;
    }
    char *dict_filename = argv[1];
    char *jumbles_filename = argv[2);

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

    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);
        return 1;
    }

    char line[MAX_WORD_LENGTH];
    while (fgets(line, sizeof(line), dict_file) != NULL && num_words < MAX_NUM_WORDS) {
        // Remove trailing newline character
        line[strcspn(line, "\n")] = '\0';
        // Copy word into dictionary
        strncpy(dictionary[num_words], line, MAX_WORD_LENGTH - 1);
        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);
        return 1;
    }

    while (fgets(line, sizeof(line), jumbles_file) != NULL) {
        // Remove trailing newline character
        line[strcspn(line, "\n")] = '\0';
        if (strlen(line) > MAX_WORD_LENGTH - 1) {
            printf("Error: Jumbled word %s is too long\n", line);
            continue;
        }
        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);

    free(dictionary);

    return 0;
}

With these corrections, your code should work as intended without the segmentation fault issue.

英文:

I have a code called unscramble that takes two files, Jumbled.txt and dictionary.txt and finds if any words contain the same characters in both the files or not, for instance, here is a sample input for

Jumbled.txt:                                  
Hello
Wassup
Rigga
Boyka
Popeye
dictionary.txt:
olleH
Yello
elloH
lloeH
aggiR
ggiRa
giRag
yokaB
Bakoy
kaBoy
eyePop
poePye

and the output of the code above is:

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

Here is my code that attempts to solve it:

#include &lt;stdio.h&gt;
#include &lt;stdlib.h&gt;
#include &lt;string.h&gt;
#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(&quot;Usage: unscramble &lt;dictionary&gt; &lt;jumbles&gt;\n&quot;);
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, &quot;r&quot;);
if (dict_file == NULL) {
printf(&quot;Error: Could not open dictionary file %s\n&quot;, dict_filename);
exit(1);
}
char line[MAX_WORD_LENGTH];
while (fgets(line, sizeof(line), dict_file) != NULL) {
// Remove trailing newline character
line[strcspn(line, &quot;\n&quot;)] = &#39;\0&#39;;
// 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, &quot;r&quot;);
if (jumbles_file == NULL) {
printf(&quot;Error: Could not open jumbled words file %s\n&quot;, jumbles_filename);
exit(1);
}
while (fgets(line, sizeof(line), jumbles_file) != NULL) {
line[strcspn(line, &quot;\n&quot;)] = &#39;\0&#39;;
char sorted_word[MAX_WORD_LENGTH];
strcpy(sorted_word, line);
sort_word(sorted_word);
int found_match = 0;
for (int i = 0; i &lt; num_words; i++) {
if (is_valid_word(sorted_word, dictionary[i])) {
if (!found_match) {
printf(&quot;%s:&quot;, line);
found_match = 1;
}
printf(&quot; %s&quot;, dictionary[i]);
}
}
if (!found_match) {
printf(&quot;%s: NO MATCHES&quot;, line);
}
printf(&quot;\n&quot;);
}
fclose(jumbles_file);
return 0;
}

However, after converting it into executable format and checking that Jumbled.txt AND dictionary.txt is available in the same directory, I get this error message:

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:~$ 

what should I change and what is my problem?

Edit What I have so far:

#include &lt;stdio.h&gt;
#include &lt;stdlib.h&gt;
#include &lt;string.h&gt;
#define MAX_WORD_LENGTH 50
#define MAX_NUM_WORDS 500000
int compare_char(const void *a, const void *b) {
return *(const char*)a - *(const char*)b;
}
void sort_word(char *word) {
qsort(word, strlen(word), sizeof(char), compare_char);
}
int is_valid_word(const char *jumbled_word, const 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(&quot;Usage: unscramble &lt;dictionary&gt; &lt;jumbles&gt;\n&quot;);
return 1;
}
char *dict_filename = argv[1];
char *jumbles_filename = argv[2];
char (*dictionary)[MAX_WORD_LENGTH] = malloc(MAX_NUM_WORDS * sizeof(*dictionary));
if(!dictionary) {
printf(&quot;Error: malloc failed\n&quot;);
return 1;
}
int num_words = 0;
FILE *dict_file = fopen(dict_filename, &quot;r&quot;);
if (dict_file == NULL) {
printf(&quot;Error: Could not open dictionary file %s\n&quot;, dict_filename);
return 1;
}
char line[MAX_WORD_LENGTH];
while (fgets(line, sizeof(line), dict_file) != NULL &amp;&amp; num_words &lt; MAX_NUM_WORDS) {
// Remove trailing newline character
line[strcspn(line, &quot;\n&quot;)] = &#39;\0&#39;;
// Copy word into dictionary
strncpy(dictionary[num_words], line, MAX_WORD_LENGTH - 1);
num_words++;
}
fclose(dict_file);
// Loop over jumbled words file
FILE *jumbles_file = fopen(jumbles_filename, &quot;r&quot;);
if (jumbles_file == NULL) {
printf(&quot;Error: Could not open jumbled words file %s\n&quot;, jumbles_filename);
return 1;
}
while (fgets(line, sizeof(line), jumbles_file) != NULL) {
// Remove trailing newline character
line[strcspn(line, &quot;\n&quot;)] = &#39;\0&#39;;
if (strlen(line) &gt; MAX_WORD_LENGTH - 1) {
printf(&quot;Error: Jumbled word %s is too long\n&quot;, line);
continue;
}
char sorted_word[MAX_WORD_LENGTH];
strcpy(sorted_word, line);
sort_word(sorted_word);
int found_match = 0;
for (int i = 0; i &lt; num_words; i++) {
if (is_valid_word(sorted_word, dictionary[i])) {
if (!found_match) {
printf(&quot;%s:&quot;, line);
found_match = 1;
}
printf(&quot; %s&quot;, dictionary[i]);
}
}
if (!found_match) {
printf(&quot;%s: NO MATCHES&quot;, line);
}
printf(&quot;\n&quot;);
}
fclose(jumbles_file);
free(dictionary);
return 0;
}

答案1

得分: 4

以下是翻译好的部分:

"The first step is to run your program in a debugger to figure out where it segfaults" :
"第一步是在调试器中运行您的程序,找出它在哪里出现分段错误:"

$ gdb ./unscramble
(gdb) set args dictionary.txt Jumbled.txt
(gdb) r
(gdb) bt
Program received signal SIGSEGV, Segmentation fault.
0x00005555555552c6 in main (argc=&lt;error reading variable: Cannot access memory at address 0x7ffffe82657c&gt;, argv=&lt;error reading variable: Cannot access memory at address 0x7ffffe826570&gt;) at 1.c:26
26      int main(int argc, char *argv[]) {"

这是奇怪的,即内存损坏,甚至在开始之前,所以您查看分配并看到:
"这是奇怪的,即内存损坏,即使在开始之前也是如此,因此您查看分配并看到:"

which is 500k * 50 bytes or 25 MB. The default stack on my system is 8 MB. You could up your stack size with, say, ulimit -s 30000, and your program would run as it. It would be better to reduce memory usage, or use malloc() to allocate space on the heap instead:
"这是500k * 50字节,或25 MB。我的系统上的默认堆栈大小为8 MB。您可以使用ulimit -s 30000来增加堆栈大小,这样您的程序就可以运行。最好减少内存使用,或者改用malloc()来在堆上分配空间:"

    if(!dictionary) {
printf(&quot;malloc failed\n&quot;);
return 1;
}
// ...
free(dictionary);

and it now returns:
"现在它返回:"

Wassup: NO MATCHES
Rigga: aggiR ggiRa giRag
Boyka: yokaB Bakoy kaBoy
Popeye: eyePop poePye"
英文:

The first step is to run your program in a debugger to figure out where it segfaults:

$ gcc -g3 -Wall -W -pedantic -o unscramble unscramble.c
$ gdb ./unscramble
(gdb) set args dictionary.txt Jumbled.txt
(gdb) r
(gdb) bt
Program received signal SIGSEGV, Segmentation fault.
0x00005555555552c6 in main (argc=&lt;error reading variable: Cannot access memory at address 0x7ffffe82657c&gt;, argv=&lt;error reading variable: Cannot access memory at address 0x7ffffe826570&gt;) at 1.c:26
26      int main(int argc, char *argv[]) {

This is strange, i.e. memory corruption, before even starting, so you look at allocations and you see:

	char dictionary[MAX_NUM_WORDS][MAX_WORD_LENGTH];

which is 500k * 50 bytes or 25 MB. The default stack on my system is 8 MB. You could up your stack size with, say, ulimit -s 30000, and your program would run as it. It would be better to reduce memory usage, or use malloc() to allocate space on the heap instead:

    char (*dictionary)[MAX_WORD_LENGTH] = malloc(MAX_NUM_WORDS * sizeof(*dictionary));
if(!dictionary) {
printf(&quot;malloc failed\n&quot;);
return 1;
}
// ...
free(dictionary);

and it now returns:

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

答案2

得分: 1

你将dictionary数组放在main函数中,所以这个数组将存在于main函数的栈上;这在栈上大约占用了23.8M的空间,超出了几乎所有操作系统的通常栈大小限制(在Linux上为8M)。

如果你仍然想要使用二维数组,请将该数组放在main函数外部作为全局变量,这样它就不再存在于main的栈帧中。或者使用malloc来分配这个数组,使它存在于程序的堆中。请参考栈和堆是什么,它们位于哪里?

英文:

You put the dictionary array in main, so this array is going to live on main' s function stack; that's approximately 23.8M on the stack, over the usual stack size limit of almost all the operating systems (8M on Linux).

If you still want to use a bi-dimensional array, put this array outside main as a global variable, so it won't live on main's stack frame anymore. Alternatively use malloc to allocate this array, so it lives in the program's heap. See What and where are the stack and heap?

huangapple
  • 本文由 发表于 2023年2月19日 11:55:44
  • 转载请务必保留本文链接:https://go.coder-hub.com/75497892.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定