2014-09-04 51 views
1

由於sprintf會導致一些緩衝區溢出,因此我需要將項目中的所有sprintf更改爲snprintf。但我得到了一些麻煩如下:如何確定snprintf dest緩衝區大小

void foo(char *a, uchar *string) 
{ 
    sprintf(string, 'format', src_str); 
} 

的問題是,當目標字符串的函數,如何確定緩衝區大小或字符串的最大長度後,我們改變的snprintf的參數..

+4

您必須將緩衝區大小傳遞給函數。 – Kevin 2014-09-04 18:22:53

+1

調用'int len = snprintf(NULL,0,....)',然後'char buf [len]; snprintf(buf,len,....);'現在至少'buf'具有完整的字符串。至於有多少符合'字符串' - 你是獨立的。 – chux 2014-09-04 19:40:52

+0

除了向函數添加新的大小參數外,還有一個選項是創建一個'struct ustring'來存放指針和緩衝區大小。如果你喜歡,你可以將字符串大小添加到結構體中,這允許你使用更快的函數,比如'memcpy'而不是'strcpy'。 – 2014-09-04 23:04:55

回答

2

如果您可以選擇自行分配目標緩衝區,則可以使用strlen()來檢查源字符串的長度,以防其爲null-terminatd併爲其分配足夠大的緩衝區並終止空字符。如果可用,您也可以直接使用asprintf。 如果您沒有該選項,則必須將目標緩衝區的大小作爲參數傳遞,因爲如果只有指向它的指針,則無法從函數內可靠地確定其大小(除非目標緩衝區始終在一個獨特的可識別的方式)。

+0

是的,對於字符串我可以使用strlen()來檢查它的大小,但是如果它指向一個數組,strlen()會遇到一些麻煩。 – unnugi 2014-09-04 20:18:24

+0

您能否澄清一下在哪裏以及在這裏涉及哪種數組? strlen通常會處理所有形式的以null結尾的字符串。 – midor 2014-09-04 20:36:32

+0

嗨Midor,有沒有可能*字符串是指向一個字符串數組,當foo被調用? – unnugi 2014-09-04 20:48:43

1

調用_scprintf(...)會告訴你該字符串有多大,而不實際使用緩衝區。

然後你分配一個這樣大小的緩衝區,然後調用snprintf。

+1

此解決方案不符合XPG7或C11標準。使用snprintf()函數會。 – 2014-09-04 19:52:53

+0

當調用foo時,如果字符串指向一個數組,看起來-scprintf()將不起作用。'string =&Array [len]; foo((char *)a,string);' – unnugi 2014-09-04 20:34:36

0

如果您無法使用正確的參數調用snprintf,只需將sprintf更改爲snprintf即可獲得任何優惠。您的foo函數還需要額外的參數,就像snprintf需要一個超過sprintf的額外參數。由於數組在被用作函數的參數時衰減爲指針,因此任何大小的信息都會丟失。

如果您在整個程序中調用foo幾百次,這可能會讓您感到痛苦,但是如果您想確保避免緩衝區溢出,則需要確保對陣列進行操作的任何函數都完全知曉的大小。

如果使用GCC或鐺,你可以通過改變它的原型放在foo功能的棄用警告:

void __attribute__((deprecated)) foo(char *a, uchar *string); 

然後,您可以創建一個新的功能,例如foo_n,它有大小的額外參數。當你編譯你的代碼時,GCC會爲每個使用函數foo發出一個警告,所以你知道用foo_n替換它們。

1.有可能是__attribute__((deprecated))部分後去參數列表,但鐺似乎接受它作爲示出了高於它。