[英]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
结束后写入。 尽管极有可能不会导致程序崩溃,但这仍然是未定义的行为,您应该插入检查数组边界以防止它发生。
调试代码以使其正确且健壮。
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.
}
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.