2011-08-25 102 views
10

numCheck是1-1000之間的數字。只有當我在charcheck中收集sprintf的結果時,此代碼纔會給我一個段錯誤。如果我只是使用sprintf而不使用結果,我不會遇到seg故障。這裏發生了什麼事?Sprintf分割錯誤

char * numString; 
int charcheck = sprintf(numString, "%d", numCheck); 

回答

7

您需要爲sprintf提供自己的記憶。另外,不要使用sprintf,而是snprintf

char buf[1000] = {0}; 

snprintf(buf, 999, ....); 

另外,您可以動態分配內存:

char * buf = new char[BUFSIZE]; 
snprintf(buf, BUFSIZE-1, ...); 
/* ... */ 
delete[] buf; 
+0

準確地說,爲什麼當我不收集結果時,它會工作? – syl

+0

這是未定義的行爲。有時候未定義的行爲會按照您的預期行事,這可能是最糟糕的情況。 –

+1

爲什麼你推薦'snprintf'比'sprintf'? – Kevin

1

的第一個參數sprintf必須指向一個有效的緩衝。你有一個char*,但它指向垃圾。

你的代碼更改爲:

char numString[80] = { }; 
int charcheck = sprintf(numString, "%d", numCheck); 

這樣numString實際上指向一個有效的緩衝液(在這個例子中80個字符,所有的元素就是被初始化爲0)。

這也將是很好用snprintf這樣你就可以通過你的緩衝區,它的大小,這將有助於防止緩衝區溢出:

您從您傳遞的緩衝區大小減去一個
const int bufsize = 80; 
char numString[bufsize] = { }; 
int charcheck = snprintf(numString, bufsize - 1, "%d", numCheck); 

公告到snprintf,因爲您不希望它使用最後一個插槽,您要確保它是NULL來表示字符串的結尾。

+0

有沒有什麼辦法可以找出我用字符傳遞的整數的大小,這樣我就可以分配正確數量的空間而不是使用像80那樣的任意值? – syl

+0

@user只是分配額外的空間可能會更有效率(你可以根據你存儲的類型來確定一個數字的最大字符數),因爲計算它需要一個'if'級聯。你只需計算出你的號碼的最大數量小於(例如,如果它小於10(但總是'> 0',請注意你)它是1位數字,如果它小於100則是2位數字等等)。但是,在堆棧中分配空間需要一定的時間(並且在這個時間上有一個非常小的常量),只要你不做類似'char numString [9999999999999]'你應該沒問題 –

0

您需要的結果,如

char numString[50]; 
int charcheck = sprintf(numString, "%d", numCheck); 

在你的情況的sprintf的INTERAL運作都嘗試引用NULL這是針對你的情況的指針的默認值分配空間。

1

作爲sprintf的第一個參數給出的指針預計指向一個內存位置,其中sprintf應寫入格式化的字符串。

在這種情況下,您並未初始化numString以指向您爲格式化字符串分配的某些內存。由於numString未初始化,因此可能指向任何位置,並且在您嘗試將格式化輸出寫入該位置時會導致分段錯誤。

0

最直截了當的事情是使用一個數組如上,例如,

char numString[80] = { }; 

由Seth,耶穌和Kerrek建議。

我認爲最後一個答案是很好的解釋:「sprintf的第一個參數預計指向sprintf應該寫入格式化字符串的內存位置。」因此,從使用字符數組,這將迫使分配內存的字符串分開,你也可以使用這個:

char *numstring = (char*) malloc(80); 

這應該讓你明確地釋放分配內存時不再需要它。