繁体   English   中英

为什么以下代码行导致我的程序出现段错误?

[英]Why does the following line of code cause my program to seg fault?

在下面的代码中:

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

int main (int argc, const char * argv[]) {

    char input[20];
    fgets(input, sizeof(input), stdin);
    char * pch;
    pch = strtok(input, " ");
    int i = 0;
    int nums[3];
    while (pch != NULL)
    {
        printf ("%s\n",pch);
        pch = strtok(NULL, " ");
        //nums[i] = atoi(pch);
        i++;
    }


    return 0;
}

输入

1 2 3

给出:

1
2
3

当我取消注释行时,我得到:

1
2
3

Segmentation fault: 11

为什么这条线会导致段故障?

最主要的是您需要再次调用strtok 之前运行atoi(pch)

printf ("%s\n",pch);
nums[i++] = atoi(pch);
pch = strtok(NULL, " ");

否则,对atoi的最后一次调用会将null指针作为参数传递,并且atoi崩溃。

另一个有趣的细节是input可能在末尾包含换行符。 对于atoi不会出现问题,但这会使您的循环迭代4次并在nums结束后写入。 尽管极有可能不会导致程序崩溃,但这仍然是未定义的行为,您应该插入检查数组边界以防止它发生。

调试代码以使其正确且健壮。

提示1:避免在原始阵列中进行无效的内存访问

if (i >= 0 && i < 3)
{
   // The value of i is a Valid index for "int nums[3];"
   nums[i] = atoi(pch);
}
else
{
   // The value of i is NOT a Valid index for "int nums[3];", so why even try?
   // Using "nums[i]" here would cause undefined behaviour.
}

提示2:缩小问题范围

int currentInt = atoi(pch);
nums[i] = currentInt;

其中哪几行崩溃?

如果是第二个,您应该可以通过上面建议的范围检查来防止它。

如果是第一个int currentInt = atoi(pch);,则意味着atoi正在崩溃,因为其返回值恰好是int,因此将结果分配给currentInt是安全的。

为什么atoi会崩溃? 现在,您已缩小了范围。 继续缩小范围,直到找到它。

保持换行

更改

pch = strtok(NULL, " ");

pch = strtok(NULL, " \n");

您必须检查strtok的返回值(如果没有更多的令牌,则返回NULL)并检查i,因为此var不得超过3,因为nums数组仅分配给3 int。

while (pch != NULL && i < 3)
    {
        printf ("%s\n",pch);
        pch = strtok(NULL, " ");
        if (pch != NULL)
          nums[i] = atoi(pch);
        i++;
    }

因为您在数组边界之外循环

int i = 0;
int nums[3];
while (pch != NULL)
{
    printf ("%s\n",pch);
    pch = strtok(NULL, " ");  
    nums[i] = atoi(pch);      // i == 3 will cause the issue
    i++;
}

试一试

int i = 0;
int nums[3];
for (pch = strtok(input, " "); pch != NULL && i < 3; pch = strtok(NULL," "))
{
    printf ("%s\n",pch);
    nums[i++] = atoi(pch); 
}

使用strtok您每次都会得到一个字符并将其放入数组中。
但是, strtok在分隔符或字符串结尾之前返回字符串。
对于最后一个值,即3 ,它还附加了一个\\n ,并且您试图将其作为单个字符放入。

只需将值放入数组,然后再获取下一个

int i = 0;
int nums[3];
while (pch != NULL)
{
    printf ("%s\n",pch);
    nums[i] = atoi(pch);
    pch = strtok(NULL, " ");
    i++;
}
/*// Testing the array
for(i = 0; i< 3; i++)
   printf("%d ",nums[i]);
*/

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM