“Segmentation fault(core dumped)” (problem with argv)

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

"Segmentation fault(core dumped)" (problem with argv)

问题

我尝试调试它,我知道与argv相关,但我不确定*发生了什么*

#include <cs50.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>

string replace();

int main(int argc, string argv[])
{
  if (strlen(argv[2]) != 26)
  {
    printf("密码必须为26个字符\n");
    return 0;
  }

要明确,调试显示问题发生在以下行上

if (strlen(argv[2]) !=26

给出的问题是“分段错误(核心已转储)”。仅在执行程序后输入文本时才会发生。

所以后面的文本在这里:

  string plaintext = get_string("明文:");
  string word = plaintext;
  string result = replace(word);
}

string replace(string word, int argc, string argv[])
{
  string coded = NULL;
  for(int i = 0; i < strlen(word); i++)
  {
    int c = tolower(word[i]);
    int n = c - 97;
    if (n < 0 || n > 26)
    {
      n = c;
    }
    coded[i] = argv[2][n];
  }
  printf("编码: %s", coded);
  return 0;
}

我基本上想将明文字符串转换为使用命令行参数输入的密码。我知道我有一些错误(比如标点符号不会转换),因为我是新手,但我有信心我可以自己解决这些问题。我只想弄清楚为什么它会给我这个特定的错误。
英文:

So I tried debugging it and I know it's related to the argv but I'm not sure what is happening.

#include &lt;cs50.h&gt;
#include &lt;stdio.h&gt;
#include &lt;string.h&gt;
#include &lt;ctype.h&gt;

string replace();

int main(int argc, string argv[])
{
  if (strlen(argv[2]) != 26)
  {
    printf(&quot;The cipher must be 26 characters\n&quot;);
    return 0;
  }

To be clear, debug says the problem occurs on the line that says

if (strlen(argv[2]) !=26

The problem given is "segmentation fault(core dumped). This only happens when I enter text after executing the program.

So the later text is here:

  string plaintext = get_string(&quot;Plaintext: &quot;);
  string word = plaintext;
  string result = replace(word);
}

string replace(string word, int argc, string argv[])
{
  string coded = NULL;
  for(int i = 0; i &lt; strlen(word); i++)
  {
    int c = tolower(word[i]);
    int n = c - 97;
    if (n &lt; 0 || n &gt; 26)
    {
      n = c;
    }
    coded[i] = argv[2][n];
  }
  printf(&quot;coded: %s&quot;, coded);
  return 0;
}

I basically want to turn whatever the plaintext string is into a code using a cipher that was inputted in the command line argument. I know that I have some errors (like punctuation will not convert) because I'm new to this, but I feel confident I can figure those out on my own. I just want to figure out why it's giving me this specific error.

答案1

得分: 2

在你的程序中,你在注释部分提到你是这样调用程序的:

./substitution YTNSHKVEFXRBAUQZCLWDMIPGJO

这意味着:

  • argc 的值为 2
  • argv[0] 将指向字符串 "./substitution"
  • argv[1] 将指向字符串 "YTNSHKVEFXRBAUQZCLWDMIPGJO"
  • argv[2] 的值为 NULL(即它不指向任何有效的字符串)

因此,下面这行代码:

if (strlen(argv[2]) != 26)

并没有引用有效的字符串,当你在无效引用上使用 strlen 时,可能会导致分段错误。这似乎就是发生的情况。

因此,出于这个原因,你应该使用 argv[1] 而不是 argv[2]

通常情况下,建议在访问 argv 数组之前始终检查 argc("argument count",参数计数)的值。否则,如果用户没有传递任何命令行参数(除了程序名称),并且你尝试读取 argv[1],那么你将使用无效的引用,可能导致分段错误。

因此,我建议你将以下代码行:

int main(int argc, string argv[])
{
  if (strlen(argv[2]) != 26)
  {
    printf("The cipher must be 26 characters\n");
    return 0;
  }

修改为以下内容:

int main(int argc, string argv[])
{
    if (argc < 2)
    {
        printf("You must specify at least one argument!\n");
        exit(EXIT_FAILURE);
    }

    if (strlen(argv[1]) != 26)
    {
        printf("The cipher must be 26 characters\n");
        exit(EXIT_FAILURE);
    }

请注意,你必须包含 #include <stdlib.h> 以使用 exit 函数。使用 exit 而不是 return 的好处在于它可以用于立即终止程序,即使在 main 函数之外也可以使用。与 exit 不同,return 语句只能在 main 函数内部使用,因此通常最好为了一致性使用 exit,即使在这种情况下使用 return 也足够。否则,如果出于某种原因你决定将代码移到另一个函数中,它将停止工作。

另一个可能导致分段错误的问题是,在 replace 函数中,你似乎没有替换原始字符串中的字符,而是尝试创建一个新字符串来写入转换后的字符。但是,在CS50第二周,你还没有学会如何为编译时未知大小的字符串分配内存,以及如何复制这样的字符串。此外,你还没有学会如何从函数中返回字符串。这将在CS50的第四周中学习,那时你还会学到指针是什么。因此,我不建议尝试创建字符串的副本,因为这也不是作业要求。相反,我建议你简单地覆盖现有字符串的字符,因为这才是作业的预期解决方式。

英文:

In the comments section, you stated that you are calling your program like this:

./substitution YTNSHKVEFXRBAUQZCLWDMIPGJO

This means that

  • argc will have the value 2
  • argv[0] will refer ("point") to the string &quot;./substitution&quot;
  • argv[1] will refer ("point") to the string &quot;YTNSHKVEFXRBAUQZCLWDMIPGJO&quot;
  • argv[2] will have the value NULL (i.e. it will not point to any valid string)

Therefore, the line

if (strlen(argv[2]) != 26)

is not referring to a valid string and may cause a segmentation fault when you use strlen on that invalid reference. This appears to be exactly what is happening here.

For this reason, you should use argv[1] instead of argv[2].

Generally, it is a good idea to always check the value of argc ("argument count") before accessing the array argv ("argument vector"). Otherwise, if the user dies not pass any command-line arguments (other than the program name) and you try to read argv[1], you will be using an invalid reference and you may be causing a segmentation fault.

Therefore, I recommend that you change the lines

int main(int argc, string argv[])
{
  if (strlen(argv[2]) != 26)
  {
    printf(&quot;The cipher must be 26 characters\n&quot;);
    return 0;
  }

to the following:

int main(int argc, string argv[])
{
    if ( argc &lt; 2 )
    {
        printf( &quot;You must specify at least one argument!\n&quot; );
        exit( EXIT_FAILURE );
    }

    if ( strlen(argv[1]) != 26 )
    {
        printf( &quot;The cipher must be 26 characters\n&quot; );
        exit( EXIT_FAILURE );
    }

Note that you must #include &lt;stdlib.h&gt; to use the function exit. Using exit instead of return has the advantage that it can be used to immediately terminate your program also outside the function main. In contrast to exit, the return statement can only do this when used inside the function main, so it is generally better to use exit for consistency, even if using return is sufficient in this case. Otherwise, if you for some reason decide to move the code into another function, it will stop working.

Another issue, which can also lead to a segmentation fault, is that in the function replace, you appear to be not replacing the characters in the original string, but rather attempting to create a new string to which to write the converted characters. However, in week 2 of CS50, you have not yet learnt how to allocate memory for a string whose size is unknown at compile-time, and how to copy such a string. Also, you have not yet learnt how to return a string from a function. You will only learn this in week 4 of CS50, in which you also learn what pointers are. Therefore, I do not recommend that you attempt to create a copy of the string, as this is also not required by the assignment. Instead, I recommend that you simply overwrite the characters of the existing string, as that is how the assignment is intended to be solved.

huangapple
  • 本文由 发表于 2023年3月12日 06:31:19
  • 转载请务必保留本文链接:https://go.coder-hub.com/75709972.html
匿名

发表评论

匿名网友

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

确定