簡體   English   中英

如何避免使用C中非空終止的緩沖區調用fopen()?

[英]How to avoid calling fopen() with a buffer that is not null-terminated in C?

我們來看看這個例子:

static FILE *open_file(const char *file_path)
{
    char buf[80];
    size_t n = snprintf(buf, sizeof (buf), "%s", file_path);
    assert(n < sizeof (buf));
    return fopen(buf, "r");
}

這里, assert()是一個接一個。 snprintf的聯機幫助頁:

“成功返回后,這些函數返回打印的字符數(不包括用於結束輸出到字符串的空字節)。”

因此,如果它返回80,則字符串將填充緩沖區,並且不會被\\ 0終止。 這將導致問題,因為fopen()假定它以null結尾。

防止這種情況的最佳方法是什么?

防止這種情況的最佳方法是什么?

很簡單,不要給它一個非空終止字符串。 除了學術問題,您可以控制自己編寫的代碼。 你不必以各種可能的方式防止自己破壞項目,你只需要不要破壞自己。

如果每個人都檢查並仔細檢查代碼中的所有內容,那么性能損失將是不可思議的。 fopen沒有這樣做的原因。

因此,如果它返回80,則字符串將填充緩沖區,並且不會被\\0終止

這是不正確的:無論你為file_path傳遞什么,字符串都將以null結尾。 顯然,字符串將以sizeof(buf)-1切斷。

請注意, snprintf也可以返回80以上的數字。 這意味着您要打印的字符串比您提供的緩沖區長。

防止這種情況的最佳方法是什么?

您已經在這樣做了: assert不是防止未終止字符串所必需的。 您可以使用返回值來確定是否發生了截斷,並傳遞更大的緩沖區來補償:

// Figure out the size
size_t n = snprintf(NULL, 0, "%s", file_path);
// Allocate the buffer and print into it
char *tmpBuf = malloc(n+1);
snprintf(tmpBuf, n+1, "%s", file_path);
// Prepare the file to return
FILE *res = fopen(tmpBuf, "r");
// Free the temporary buffer
free(tmpBuf);
return res;

這里有幾個問題。

第一個assert()用於捕獲問題,作為設計器測試的一部分。 它不適用於生產代碼。

其次,如果文件路徑不完整,那么你真的想調用fopen()嗎?

通常,做的是在預期的字符數中加一。

static FILE *open_file(const char *file_path)
{
    char buf[80 + 1] = {0};

    size_t n = snprintf(buf, 80, "%s", file_path);
    assert(n < sizeof (buf));
    return fopen(buf, "r");
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM