numCheck是1-1000之間的數字。只有當我在charcheck中收集sprintf的結果時,此代碼纔會給我一個段錯誤。如果我只是使用sprintf而不使用結果,我不會遇到seg故障。這裏發生了什麼事?Sprintf分割錯誤
char * numString;
int charcheck = sprintf(numString, "%d", numCheck);
numCheck是1-1000之間的數字。只有當我在charcheck中收集sprintf的結果時,此代碼纔會給我一個段錯誤。如果我只是使用sprintf而不使用結果,我不會遇到seg故障。這裏發生了什麼事?Sprintf分割錯誤
char * numString;
int charcheck = sprintf(numString, "%d", numCheck);
您需要爲sprintf
提供自己的記憶。另外,不要使用sprintf
,而是snprintf
:
char buf[1000] = {0};
snprintf(buf, 999, ....);
另外,您可以動態分配內存:
char * buf = new char[BUFSIZE];
snprintf(buf, BUFSIZE-1, ...);
/* ... */
delete[] buf;
的第一個參數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
來表示字符串的結尾。
有沒有什麼辦法可以找出我用字符傳遞的整數的大小,這樣我就可以分配正確數量的空間而不是使用像80那樣的任意值? – syl
@user只是分配額外的空間可能會更有效率(你可以根據你存儲的類型來確定一個數字的最大字符數),因爲計算它需要一個'if'級聯。你只需計算出你的號碼的最大數量小於(例如,如果它小於10(但總是'> 0',請注意你)它是1位數字,如果它小於100則是2位數字等等)。但是,在堆棧中分配空間需要一定的時間(並且在這個時間上有一個非常小的常量),只要你不做類似'char numString [9999999999999]'你應該沒問題 –
您需要的結果,如
char numString[50];
int charcheck = sprintf(numString, "%d", numCheck);
在你的情況的sprintf的INTERAL運作都嘗試引用NULL這是針對你的情況的指針的默認值分配空間。
作爲sprintf
的第一個參數給出的指針預計指向一個內存位置,其中sprintf
應寫入格式化的字符串。
在這種情況下,您並未初始化numString
以指向您爲格式化字符串分配的某些內存。由於numString
未初始化,因此可能指向任何位置,並且在您嘗試將格式化輸出寫入該位置時會導致分段錯誤。
最直截了當的事情是使用一個數組如上,例如,
char numString[80] = { };
由Seth,耶穌和Kerrek建議。
我認爲最後一個答案是很好的解釋:「sprintf的第一個參數預計指向sprintf應該寫入格式化字符串的內存位置。」因此,從使用字符數組,這將迫使分配內存的字符串分開,你也可以使用這個:
char *numstring = (char*) malloc(80);
這應該讓你明確地釋放分配內存時不再需要它。
準確地說,爲什麼當我不收集結果時,它會工作? – syl
這是未定義的行爲。有時候未定義的行爲會按照您的預期行事,這可能是最糟糕的情況。 –
爲什麼你推薦'snprintf'比'sprintf'? – Kevin