2012-03-25 111 views
0

我正在make一個makefile的創建者,但是我被困在sprintf上的這個錯誤中,最奇怪的是我有多個sprintf之前有錯誤,並且他們工作正常。Sprintf的分割錯誤

下面的代碼:

if (WIFEXITED(stat) ){ 

    if (WEXITSTATUS(stat)) { 

     if (cFiles == 0 && cFolders == 0) { 
      Crear(path); 
     } 

     cFolders = 1; 
     TEMP = malloc(sizeof(char)*(strlen(direntp->d_name) + 25)); 

     if (TEMP == NULL) { 
      perror("Malloc Error: "); 
      exit(1); 
     } 

     if (sprintf(TEMP, "\n%s/%s.a: force\n\t$(MAKE) -C %s\n",direntp->d_name, direntp->d_name, direntp->d_name) < 0) { 
     perror("Sprintf Error: "); 
     exit(1); 
     } 

     write(STDOUT_FILENO,TEMP,strlen(TEMP)); 
     f.name = malloc(sizeof(char)*(strlen(direntp->d_name)*2 + 3)); 

     if (f.name = NULL) { 
      perror("Malloc Error: "); 
      exit(1); 
     } 
      //This is the one with the problem!!!  
      if (sprintf(f.name, "%s/%s.a", direntp->d_name, direntp->d_name) < 0) { 
      perror("Sprintf Error: "); 
      exit(1); 
     } 

     l = AddToList(l,&f); 
    } 
} 
+0

我最好的猜測是其中一個字符串不是空終止。當我第一次學習C時,我遇到了這個問題。 – forivall 2012-03-25 06:07:20

回答

1

它似乎並不像你分配TEMP足夠大

TEMP = malloc(sizeof(char)*(strlen(direntp->d_name) + 25)); 

應該是:

TEMP = malloc(sizeof(char)*(strlen(direntp->d_name)*3 + 25 + 1)); 

您打印d_name三次,而且您還需要額外的空字符作爲空終止符。

同樣,在這條線:

f.name = malloc(sizeof(char)*(strlen(direntp->d_name)*2 + 3)); 

應該

f.name = malloc(sizeof(char)*(strlen(direntp->d_name)*2 + 3 + 1)); 

佔空終止。

使用聲稱這樣可以幫助確保你的計算是正確的:

int TEMP_size = strlen(direntp->d_name)*3 + 25 + 1; 
    TEMP = malloc(sizeof(char)*TEMP_size); 

    if (TEMP == NULL) { 
     perror("Malloc Error: "); 
     exit(1); 
    } 

    if (sprintf(TEMP, "\n%s/%s.a: force\n\t$(MAKE) -C %s\n",direntp->d_name, direntp->d_name, direntp->d_name) < 0) { 
     perror("Sprintf Error: "); 
     exit(1); 
    } 
    assert(strlen(TEMP)+1==TEMP_size); 
+0

對不起,我發佈的代碼是舊的,TEMP分配是固定的,但分段錯誤不是來自TEMP,而是來自sprintf(f.name .....)。這就是我發現奇怪的,即使使用f.name = malloc(sizeof(char)*(strlen(direntp-> d_name)* 2 + 3 + 1))仍然會啓動相同的錯誤。 – 2012-03-25 17:42:38

0

「%s /%SA」,所以我想如果「%s」爲長度爲n,則整個字符串將取n * 2 + 1 + 1 + 1 + 1 = 2n + 4而不是2n + 3 ...不要忘記終止'\ 0',,, ,但至於是否應該導致分段錯誤。 。我不知道......

//呀,很多關於字節這段代碼分配的一些錯誤......

0

你沒有這個sprintf的分配enougth內存:

sprintf(TEMP, "\n%s/%s.a: force\n\t$(MAKE) -C %s\n",direntp->d_name, direntp->d_name, direntp->d_name 

您分配的sizeof(direntp-> d_name)+25,但我看到25字符+ 3 *的sizeof(direntp-> d_name)+1額外字符(你\ 0即表明您字符串的結尾)

問候

+0

謝謝,但就像我在其他評論中說的那樣,這不是錯誤,儘管TEMP現在有更正seg錯誤來自sprintf(f.name .....) – 2012-03-25 17:44:03

+0

sprintf(f.name,「% s /%sa「,direntp-> d_name,direntp-> d_name,我看到2 * strlen(direntp-> d_name)+ 3 char + 1額外字符(\ 0作爲字符串結尾),您分配了2 * strlen(direntp - > d_name)+ 3 char只有你錯過了你的字符串的\ 0空間,編輯arf沒有看到你曾嘗試過這種方式 – grifos 2012-03-25 21:38:47

0

除了以前的答案的一些注意事項:

  1. 大多數現代類Unix系統中有asprintf()和vasprintf()在斯坦它自己分配緩衝區的dard庫。使用它們比計算所需的大小更簡單,分配和調用sprintf(),即使它們過度分配一點。

  2. 填充緩衝區,然後使用write()將其打印到標準輸出看起來像簡單的printf()上的非現實複雜化。除非你使用stdio無法穩定處理的東西(作爲非阻塞I/O),否則使用stdio執行此類任務會更好。

  3. 您正在執行的任務更適合某種腳本語言(Perl,Python,Tcl,Ruby,無論),除非某些外部奇怪的情況迫使您使用C; C被認爲是以Unix的方式來完成更接近內核和低層次的領域。見例如"The Art of Unix Programming"的推理。

+0

這是我大學的一個項目,這就是爲什麼我必須使用C,我知道asprintf )更好,但我有一些限制,因爲我可以使用哪些命令。 – 2012-03-25 17:34:37