为什么下面的代码行导致我的程序出错?

时间:2013-05-23 07:43:07

标签: c

在以下代码中:

#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

为什么这一行导致seg错误?

6 个答案:

答案 0 :(得分:5)

主要的是您需要在再次呼叫atoi(pch)之前运行strtok

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

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

感兴趣的另一个细节是input最后可能包含换行符。这对于atoi来说不是问题,但它会导致循环迭代4次并在nums结束后写入。虽然它很可能不会导致程序崩溃,但这仍然是未定义的行为,您应该插入数组边界检查以防止它。

答案 1 :(得分:3)

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

提示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会崩溃?现在你已经缩小了你的问题范围。继续缩小范围,直到找到它为止。

答案 2 :(得分:1)

保持换行

变化

pch = strtok(NULL, " ");

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

答案 3 :(得分:1)

你必须检查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++;
    }

答案 4 :(得分:0)

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

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

答案 5 :(得分:0)

使用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]);
*/