我不知道为啥我会收到分段错误错误

Posted

技术标签:

【中文标题】我不知道为啥我会收到分段错误错误【英文标题】:I have no idea why I'm receiving segmentation fault errors我不知道为什么我会收到分段错误错误 【发布时间】:2014-09-26 10:05:47 【问题描述】:
#include <stdio.h>
#include <cs50.h> //stdlib.h is included in cs50.h so I don't need it
#include <string.h>
#include <ctype.h>
#include <math.h>

int main(int argc, string argv[]) // command line input

    if(argc != 2) // check if there is only one input
    
        printf("error\n");
        return 1;
    

    int commandlength = strlen(argv[1]); // find string length of command string

    string key[commandlength + 1]; // taking the key from the input and putting it in something that will take less typing later

    for(int i = 0; i < commandlength; i++) // check if every char in the string is a letter
    
        if(isalpha(argv[1][i]))
            continue;

        else
        
            printf("error\n");
            return 1;
        
    

    strcpy(key[commandlength], argv[1]); // copy key from command line into a string called key
    string input = GetString();
    int inputlength = strlen(input); // length of string typed in when prompted
    int k = 0; // this will be used to iterate the key separately from i, since the key only iterates when applied to an alpha

    for(int i = 0; i < inputlength; i++)
    
        if(ispunct(input[i]))
            printf("%c", input[i]);

        if(isspace(input[i]))
            printf("%c", input[i]);

        if(isupper(input[i]))
        
            printf("%c", (input[i] + atoi(key[k]) % commandlength - 65) % 26 + 65);
            k++;
        

        if(islower(input[i]))
        
            printf("%c", (input[i] + atoi(key[k]) % commandlength - 97) % 26 + 97);
            k++;
                
    

    printf("\n");
    return 0;

在阅读之前,请记住我是一名学生。获得详细的解释比简单的一行代码说“你去我修好了”要有益得多。我将在我的提交中链接这篇文章,我们确实对学术诚信以及什么是复制与帮助有非常严格的规定,如果能牢记这一点,我将不胜感激。

这个项目的目的是创建一个 vigenere 密码。以下是我的老师提供的指导:

你本周的最后一个挑战是在 vigenere.c 中编写一个使用 Vigenère 密码加密消息的程序。该程序必须接受一个命令行参数:关键字 k,完全由字母字符组成。如果您的程序在没有任何命令行参数、多个命令行参数或一个包含任何非字母字符的命令行参数的情况下执行,您的程序应该立即报错并退出,main 返回 1(因此表示我们自己的测试可以检测到的错误)。否则,您的程序必须继续提示用户输入明文字符串 p,然后它必须根据 Vigenère 的密码用 k 对其进行加密,最终打印结果并退出,main 返回 0。

对于 k 中的字符,您必须将 A 和 a 视为 0,将 B 和 b 视为 1,...,并将 Z 和 z 视为 25。此外,您的程序必须仅将 Vigenère 密码应用于 p 中的字符,如果该字符是一个字母。所有其他字符(数字、符号、空格、标点符号等)必须原样输出。此外,如果您的代码即将将 k 的第 j 个字符应用于 p 的第 i 个字符,但后者被证明是非字母字符,则您必须等待将 k 的第 j 个字符应用于 p 中的下一个字母字符;你还不能前进到 k 中的下一个字符。最后,您的程序必须保留 p 中每个字母的大小写。

我很确定我达到了迭代代码的要求,确保密钥循环(如果它比被加密的短语短),并确保我没有将密钥应用于非字母字符。但是,在提示输入要加密的字符串之前,我得到了一个分段默认值,所以我很确定问题出在代码的上半部分。我已经查看了很多代码,但我仍然无法弄清楚为什么它总是出现段错误。

【问题讨论】:

你尝试调试了吗? 我不知道该怎么做;但是,我知道它成功地阻止了具有非字母字符的密码,并阻止了没有密钥(即在那种情况下为 argc == 1)或有多个(argc > 2)的输入。我也知道在要求加密字符串之前它会出现段错误,所以它让我相信问题出在两者之间。 编译所有警告和调试信息gcc -Wall -g 然后使用调试器 (gdb)。 对于阅读此问题的任何人的信息,埋在 cs50.h 头文件中的某个地方我已经在这个论坛上看到了很多次来自学生的哦,很不幸有这个指令是typedef char *string; 是的,因为这很有帮助。 您应该知道,如果您不知道如何调试,您将无法开发软件。 【参考方案1】:

更改此语句

strcpy(key[commandlength], argv[1]); 

strcpy( key, argv[1] ); 

key[commandlength] 是一个 char 类型的对象,如果你使用这种无效的构造,它的值将用作字符串的地址

strcpy(key[commandlength], argv[1]); 

在循环中使用continue 也不是一个好主意。而不是

for(int i = 0; i < commandlength; i++) // check if every char in the string is a letter

    if(isalpha(argv[1][i]))
        continue;

    else
    
        printf("error\n");
        return 1;
    

我会简单地写

for(int i = 0; i < commandlength; i++) // check if every char in the string is a letter

    if( !isalpha(argv[1][i] ) )
    
        printf("error\n");
        return 1;
    

正如 BLUEPIXY 所指出的,而不是

string key[commandlength + 1]; 

应该有

char key[commandlength + 1]; 

前提是你没有类似的 typedef

typedef char string;

但是如果你确实有这样的 typedef 那么下面的语句

string input = GetString();

将无效,因为您正在尝试调用函数 strlen 进行输入:

int inputlength = strlen(input); 

并且不要在代码中使用幻数,例如在此语句中

printf("%c", (input[i] + atoi(key[k]) % commandlength - 65) % 26 + 65);

我想 65 是“A”。因此,最好使用明确的字符文字 'A' 而不是 65。

【讨论】:

除此之外 - 原始代码应该生成编译器消息 - 不要忽略编译器警告/错误 我做了这些更改,然后删除了 atoi,因为我不再需要它。我将对其进行测试并返回结果。 已测试 - 分段默认值已消失!但是,没有任何东西被正确加密,所以我必须着手处理这些。【参考方案2】:

我不确定string 类型应该是什么(根据main(int argc string argv[]),它看起来像char*。如果是这样,那么您将获得一个带有该行的 char 指针数组 string key[commandlength + 1];

用线strcpy(key[commandlength], argv[1]);

您将字符串从argv[i] 复制到您创建的数组中的最后一个指针。但是由于这个指针(还)没有分配任何内存。此外,它具有随机内容并指向随机存储位置。因此你得到了段错误。

您可能想要的是一个指针,它具有argv[1] 字符串的stringlength 作为内存关联。

【讨论】:

【参考方案3】:

用户johanneshau给出的答案有些正确。 要添加到他/她的答案中,您应该声明一个变量键,如下所示

string key;

而不是

string key[commandlength + 1];

那么你应该为上面的指针变量分配内存,因为 string 是 char * 的 typedef,因此在分配一些内存之前它不能存储任何字符串。

key = (string)malloc(sizeof(char) * (commandlength + 1));

以上行将分配内存来保存输入字符串。

然后您应该使用以下代码将输入字符串复制到其中

strcpy(key,argv[1]);

所以现在你已经将实际的字符串复制到了 key 变量中。

在从函数(语义程序)返回之前,您应该使用 free 函数释放内存,因为我们已经使用堆上的 malloc 函数动态分配了它。

free(key);

【讨论】:

【参考方案4】:

如果你不知道,然后编译你的源代码: "gcc -Wall -g source.c" ;运行你的程序,程序崩溃后,运行“dgb ./prog core”

在gdb中输入“bt”,你会看到出现seg fault的字符串数

如果无法在工作目录中创建核心转储,请运行以下命令:“ulimit -c unlimited”(在 bash 环境中)

【讨论】:

以上是关于我不知道为啥我会收到分段错误错误的主要内容,如果未能解决你的问题,请参考以下文章

我收到“字符串下标超出范围错误”。我不知道为啥

我在 csound 中收到一条错误消息,但我不知道为啥

我收到 tkinter 'bad window path name .!button2' 的错误,我不知道为啥?

CS50 Speller 中的分段错误。为啥?

为啥我会收到“错误:序列化从 getStaticProps 返回的 ___ 时出错”?

我不知道为啥我在发送不和谐的 webhook 时收到 400 bad request 错误。一切似乎都很好,但我对此很陌生