使用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*/
方法的使用常見問題
方法返回常用操作 1 system.out.println getvaiue 直接呼叫方法的值列印 2 int result getvalue 賦值給int變數,然後列印出來 system.out.println result 3 返回多條資料用陣列。返回同一型別的陣列,public static ...
使用element ui的常見問題
給元件繫結的事件為什麼無法觸發?在 vue 2.0 中,為自定義元件繫結原生事件必須使用.native修飾符 click me 從易用性的角度出發,我們對button元件進行了處理,使它可以監聽click事件 click me 但是對於其他元件,還是需要新增.native修飾符。2.如何在 tabl...
oracle使用常見問題
oralce常見問題 1.使用者被鎖,解鎖方法 alter user username account unlock 2.啟動 lsnrctl status start stop c documents and settings administrator lsnrctl status 3.開啟本地...