[英]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.