簡體   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