2009-01-12 31 views
12

有誰知道將printf樣式函數的輸出重定向到字符串的安全方法嗎?顯而易見的方式會導致緩衝區溢出。安全printf到字符串的最佳方法?

喜歡的東西:

string s; 
output.beginRedirect(s); // redirect output to s 

... output.print("%s%d", foo, bar); 

output.endRedirect(); 

我認爲這個問題是一樣的問,「有多少個字符將打印生產?」 想法?

回答

4

This StackOverflow question也有類似的討論。同樣在那個問題中,我提出了我最喜歡的解決方案,一個「格式」函數,它接受printf的相同參數並返回一個std :: string。

0

微軟爲此推出'safe'crt函數。

你可以使用printf_s()

+2

不適用於任何其他符合標準的實現,所以yuck。 – Bklyn 2009-01-12 22:18:07

+0

此外,唯一的區別是,如果「安全」crt檢測到某些未定義的行爲,它會自行崩潰。這並不能繞過他遇到的問題。 – 2014-08-19 19:47:48

11

snprintf()功能打印成字符串,但只有儘可能給它的長度。

可能是你在找什麼...

+0

比我快。這是老派的做法。 – dmckee 2009-01-12 18:11:18

+0

您可以使用不需要長度的sprintf。此外,這不會與字符串,因爲他問... – 2009-01-12 18:12:41

24

您可以使用:

std::snprintf,如果你是一個char *工作

std::stringstream,如果你想使用字符串(不相同作爲printf,但將允許您使用普通流功能輕鬆操縱字符串)。

boost::format如果你想要一個類似於printf的函數來處理流。 (根據jalf的評論)

1

在C99中,您有snprintf函數,它將緩衝區的大小作爲參數。 GNU C庫有asprintf,爲你分配一個緩衝區。不過,對於C++來說,你可能會更好地使用iostream。

Wikipedia有更多信息。

4

老同學:

snprintf() 

允許你把書面的數量限制,並返回實際寫的大小和

asprintf() 

分配(與malloc())足夠的緩衝,然後成爲您的問題free()。 `asprintf是一個現在在BSD libc中重新實現的GNU libc函數。

6

由於您已將此標記爲C++(而不僅僅是C),因此我會指出在C++中執行此類操作的典型方法是使用stringstream而不是printf系列。無需擔心字符串流的緩衝區溢出問題。

Boost Format庫也可用,如果你喜歡printf風格的格式化字符串,但想要更安全的話。

3

snprintf()返回寫入整個字符串所需的字節數。 所以,作爲一個小小的例子:

#include <strings.h> 
#include <stdio.h> 
#include <stdlib.h> 

int main(int argc, char** argv) 
{ 
    char* buf = 0; 
    size_t bufsize = 0; 
    size_t sz; 

    const char* format="%s and %s."; 
    const char* str_1 ="string 1"; 
    const char* str_2 ="string 2"; 

    sz = snprintf(buf, bufsize, format, str_1, str_2); 
    printf("The buffer needs to be %d bytes.\n", sz); 

    buf=malloc(sz+1); 
    if(!buf) { 
     printf("Can't allocate buffer!\n"); 
     return 1; 
    } 
    bufsize = sz+1; 
    buf[bufsize-1] = '\0'; 
    sz = snprintf(buf, bufsize, format, str_1, str_2); 
    printf("Filled buffer with %d bytes.\n", sz); 
    printf("The buffer contains:\n'%s'\n", buf); 
    return 0; 
} 

輸出:

The buffer needs to be 22 bytes. 
Filled buffer with 22 bytes. 
The buffer contains: 
'string 1 and string 2.' 
0

在Windows上:

StringCchPrintf 
StringCbPrintf 

strsafe.h/lib

1

我發現printf格式比流更容易使用和使用。另一方面,我也很喜歡std :: string。解決方案是使用sprintf,但不能處理任意的緩衝區大小。

我發現我需要處理常見的情況(比如,緩衝區限制爲256個字符),而不是 開銷,並且安全地處理大型緩衝區。爲此,我有一個256字節的緩衝區,作爲成員放在我的課程中,我使用snprinf,傳遞該緩衝區及其大小。如果snprintf成功,我可以立即重新格式化字符串。如果失敗,我分配緩衝區並再次調用snprinf。該緩衝區在類的析構函數中被釋放。

3

The fmt library提供fmt::sprintf功能執行printf的兼容格式(包括根據POSIX specification位置參數),並返回其結果作爲std::string

std::string s = fmt::sprintf("%s%d", foo, bar); 

聲明:我此庫的作者。

相關問題