release版本sprintf造成的崩潰

2021-06-19 09:08:36 字數 2098 閱讀 2396

使用sprintf 的常見問題

sprintf 是個變參函式,使用時經常出問題,而且只要出問題通常就是能導致程式崩潰的記憶體訪問錯誤,但好在由sprintf 誤用導致的問題雖然嚴重,卻很容易找出,無非就是那麼幾種情況,通常用眼睛再把出錯的**多看幾眼就看出來了。

1,緩衝區溢位

第乙個引數的長度太短了,沒的說,給個大點的地方吧。當然也可能是後面的引數的問題,建議變參對應一定要細心,而列印字串時,盡量使用」%.ns」的形式指定最大字元數。

2,忘記了第乙個引數

低階得不能再低階問題,用printf 用得太慣了。//偶就常犯。

3,變參對應出問題

通常是忘記了提供對應某個格式符的變參,導致以後的引數統統錯位,檢查檢查吧。尤其是對應」*」的那些引數,都提供了嗎?不要把乙個整數對應乙個」%s」,編譯器會覺得你欺她太甚了(編譯器是obj 和exe 的媽媽,應該是個女的,:p)。

4,strftime

sprnitf 還有個不錯的表妹:strftime,專門用於格式化時間字串的,用法跟她表哥很像,也是一大堆格式控制符,只是畢竟小姑娘家心細,她還要呼叫者指定緩衝區的最大長度,可能是為了在出現問題時可以推卸責任吧。這裡舉個例子:

time_t t = time(0);

//產生"yyyy-mm-dd hh:mm:ss"格式的字串。

char s[32];

strftime(s, sizeof(s), "%y-%m-%d %h:%m:%s", localtime(&t));

sprintf 在mfc 中也能找到他的知音:cstring::format,strftime 在mfc 中自然也有她的同道:

ctime::format,這一對由於從物件導向**得到了贊助,用以寫出的**更覺優雅。

問:我怎樣才知道對於任意的sprintf呼叫需要多大的目標緩衝區?怎樣才能避免sprintf目標緩衝區溢位?

答:對這兩個極好的問題(暫時還)沒有什麼好答案。而這也可能正是傳統stdio庫最大的弱點。

當用於sprintf的格式串已知且相對簡單時,有時可以**出緩衝區的大小。如果格式串中包含乙個或兩個%s,你可以數出固定字元的個數(或用sizeof計算)再加上對插入的字串的strlen呼叫的返回值。對於整型,%d輸出的字元數不會超過

((sizeof(int) * char_bit + 2) / 3 + 1)    /* +1 for '-' */

char_bit在中定義,但是這個計算可能有些過於保守了。它計算的是數字以八進位制儲存需要的位元組數,十進位制的儲存可以保證使用同樣或更少的位元組數。

當格式串更複雜或者在執行前未知的時候,**緩衝區大小會變得跟重新實現sprintf一樣困難,而且會很容易出錯。有一種最後防線的技術,就是用fprintf向一塊記憶體區或臨時檔案輸出同樣的內容,然後檢查fprintf的返回值或臨時檔案的大小,但請參見問題19.13,並提寫保護檔案錯誤。

如果不能確保緩衝區足夠大,就不能呼叫sprintf,以防緩衝區溢位後改寫其他的記憶體區。如果格式串已知,可以用%.ns控制%s擴充套件的長度,或者使用%.*s。參見問題12.11。

要避免溢位問題,可以使用限制長度的sprintf版本,即snprintf。這樣使用:

snprintf(buf, bufsize, "you typed /"%s/"", answer);

snprintf在幾個stdio庫中已經提供好幾年了,包括gnu和4.4bsd。在c99中已經被標準化了。

還有乙個好處是,c99的snprintf提供了**任意sprintf呼叫所需的緩衝區大小的方法。c99的snprintf返回它可能放到緩衝區的字元數,而它又可以用空指標和緩衝區大小0進行呼叫。因此,

nch = snprintf(null, 0, fmtstring, /*other arguments*/);

這樣的呼叫就可以**出格式串擴充套件後所需要的字元數。

另乙個(非標準的)選擇是asprintf函式,在bsd和gnu的c庫中都有提供,它呼叫malloc為格式串分配空間,並返回分配記憶體區的指標。這樣使用:

char *buf;

asprintf(&buf, "%d=%s", 42, "forty-two");

/*now buf points to malloc'ed space containing formatted string*/

**:

release版本和debug版本

程式一般分為debug 版本和release 版本,debug 版本用於內部除錯,release 版本發行給使用者使用 release和 debug 有什麼不同 release版稱為發行版,debug版稱為除錯版。debug中可以單步執行 跟蹤等功能,但生成的可執行檔案比較大,執行速度較慢。rele...

debug版本和release版本

執行 debug版本輸出結果 仔細觀察,可以發現release版本的結果中,a與c的值差為4,debug版本的結果中,a和c的結果直差為8.為什麼?四個位元組被優化掉了。32位系統 呼叫函式是通過棧來傳遞引數,我們列印的位址實際上是在棧裡面位置的位址 64位系統 函式傳參絕大多數不同通過棧來傳輸的,...

程式的Debug 版本和Release 版本

當建立新的專案工作空間時,visual c 自動建立可產生兩種應用程式版本的配置。一種稱作debug 版本,該版本包括幫助使用者除錯程式的資訊。使用程式的debug 版本,可以在出現問題時單步執行 以檢查程式中的資料值。另一種稱作release 版本,它不包括除錯資訊,但開啟了編譯器的 優化選項,以...