2014-03-06 50 views
2

我製作了一個程序,將字符串分解爲由空格分隔的令牌,然後將每個單獨的字符串複製到一個字符串數組中。使用字符串數組的分段錯誤C

程序工作正常,直到達到for-loop,併成功將第一個字符串添加到數組中並打印出來後,程序崩潰。我調試它,發現

args[i] = malloc((strlen(comm_str) + 1) * sizeof(char)); 

返回SEGFAULT然後執行第二次循環。同時調用堆棧打印出以下幾點:

地址:75F943F9,功能:strlen的(),文件:C:\ WINDOWS \ SysWow64資料\ msvcrt.dll.`

我試圖糾正自己的程序,但沒有結果。我首先想到的是,循環嘗試訪問出界區域,但我認爲我正確地使用了malloc。

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

int main(){ 

    char **args = NULL; 
    char input[] = "cmdline -s 20 -r -t parameter -p 20 filename"; 

    int num = 0; 
    char *comm_str = strtok(input, " ");       /*Tokens command line*/ 

    while(comm_str != NULL){          /*Counts number of tokens*/ 
     num++; 
     printf("%s %d\n", comm_str, strlen(comm_str)); 
     comm_str = strtok(NULL, " "); 
    } 
    printf("\n"); 

    args = malloc(num * sizeof(char*));       /*Allocates memory for the first string entry*/ 
    if(!args){ 
     return 0; 
    } 

    comm_str = strtok(input, " ");         /*Starts tokening from beginning*/ 
    for(int i = 0; i < num; i++){ 
     args[i] = malloc((strlen(comm_str) + 1) * sizeof(char)); /*Allocates memory for strings*/ 
     if(!args[i]){ 
      for(int b = 0; b < i; b++){ 
       free(args[b]); 
      } 
      free(args); 
      return 0; 
     } 
     strcpy(args[i], comm_str); 
     printf("%s\n", args[i]); 
     comm_str = strtok(NULL, " "); 
    } 

    printf("%d\n", num); 

} 
+0

「返回段錯誤*然後* [...]」 - 再來? –

+0

您可能會忘記正確分配內存。 args [0 ... num-1]也應該是malloc'd。 「然後返回SEGFAULT ......」聽起來不對。 – vpit3833

+0

我認爲'then'是'when'的拼寫錯誤 – Barmar

回答

4

strtok正如您所知,正在改變字符串。

計算出字數後,字符串將包含一個單詞。因此下一個strtok將返回NULL。

以非破壞性的方式計算參數的數量,或者創建一個字符串的副本。

+0

知道了!不知道strtok改變了原來的字符串,但是現在我已經制作了它的第二個副本,並按照預期工作。謝謝你的幫助。 – user3332718

0

第一個問題是你沒有包含相關的函數原型。這將使它假設一切都是一個整數。見下:

$ gcc -Wall x.c -o x 
x.c: In function ‘main’: 
x.c:9:5: warning: implicit declaration of function ‘strtok’ [-Wimplicit-function-declaration] 
x.c:9:22: warning: initialization makes pointer from integer without a cast [enabled by default] 
x.c:13:9: warning: implicit declaration of function ‘strlen’ [-Wimplicit-function-declaration] 
x.c:13:37: warning: incompatible implicit declaration of built-in function ‘strlen’ [enabled by default] 
x.c:13:9: warning: format ‘%d’ expects argument of type ‘int’, but argument 3 has type ‘long unsigned int’ [-Wformat] 
x.c:14:18: warning: assignment makes pointer from integer without a cast [enabled by default] 
x.c:18:5: warning: implicit declaration of function ‘malloc’ [-Wimplicit-function-declaration] 
x.c:18:12: warning: incompatible implicit declaration of built-in function ‘malloc’ [enabled by default] 
x.c:23:14: warning: assignment makes pointer from integer without a cast [enabled by default] 
x.c:24:5: error: ‘for’ loop initial declarations are only allowed in C99 mode 
x.c:24:5: note: use option -std=c99 or -std=gnu99 to compile your code 
x.c:25:27: warning: incompatible implicit declaration of built-in function ‘strlen’ [enabled by default] 
x.c:27:13: error: ‘for’ loop initial declarations are only allowed in C99 mode 
x.c:28:17: warning: implicit declaration of function ‘free’ [-Wimplicit-function-declaration] 
x.c:28:17: warning: incompatible implicit declaration of built-in function ‘free’ [enabled by default] 
x.c:30:13: warning: incompatible implicit declaration of built-in function ‘free’ [enabled by default] 
x.c:33:9: warning: implicit declaration of function ‘strcpy’ [-Wimplicit-function-declaration] 
x.c:33:9: warning: incompatible implicit declaration of built-in function ‘strcpy’ [enabled by default] 
x.c:35:18: warning: assignment makes pointer from integer without a cast [enabled by default] 
x.c:40:1: warning: control reaches end of non-void function [-Wreturn-type] 

我建議你在繼續之前解決這個問題。

+0

我已經包含#include ,#include 和#include 並且我的編譯器不返回任何警告。 – user3332718

1

按照手冊頁的strtok: 「使用這些功能時一定要謹慎,如果你使用它們,請注意: 這些功能修改他們的第一個參數 這些功能不能在常量字符串中使用。」

因此,您第一次解析查找num時,您修改了您的輸入字符串,因此第二次解析導致SEGFAULT的垃圾。此外,你不應該使用常量字符串:

char input[] = "cmdline -s 20 -r -t parameter -p 20 filename"; 
0

strtok替換每個' '在你的情況下,NULL。考慮以下幾點:

char input[] = "cmdline -s 20 -r -t parameter -p 20 filename"; 
size_t inputSize = strlen(input); 

for(int i = 0; i < inputSize; i++) 
    printf("%02X ", input[i]); 
printf("\n\n"); 

char *comm_str = strtok(input, " "); 
while(comm_str != NULL) 
    comm_str = strtok(NULL, " "); 

for(int i = 0; i < inputSize; i++) 
    printf("%02X ", input[i]); 
printf("\n\n"); 

輸出:

 
63 6D 64 6C 69 6E 65 20 2D 73 20 32 30 20 2D 72 20 2D 74 20 70 61 72 61 6D 65 74 65 72 20 2D 70 20 32 30 20 66 69 6C 65 6E 61 6D 65 

63 6D 64 6C 69 6E 65 00 2D 73 00 32 30 00 2D 72 00 2D 74 00 70 61 72 61 6D 65 74 65 72 00 2D 70 00 32 30 00 66 69 6C 65 6E 61 6D 65