c++ - 将 (size_t)-1 传递给 snprintf_s

标签 c++ c visual-c++

这里有一个关于 C++ Stackwalker 的问题: https://github.com/JochenKalmbach/StackWalker

#define _TRUNCATE ((size_t)-1)

enum
{
    STACKWALK_MAX_NAMELEN = 1024
}; 

void StackWalker::OnSymInit(LPCSTR szSearchPath, DWORD symOptions, LPCSTR szUserName)
{
    CHAR   buffer[STACKWALK_MAX_NAMELEN];
    size_t maxLen = STACKWALK_MAX_NAMELEN;
#if _MSC_VER >= 1400
    maxLen = _TRUNCATE;
#endif
    _snprintf_s(buffer, maxLen, "SymInit: Symbol-SearchPath: '%s', symOptions: %d, UserName: '%s'\n",
        szSearchPath, symOptions, szUserName);
}

maxlen 首先设置为 1024,然后如果 VC++ 版本 >= 1400(它是),则将其设置为(无符号)-1,换句话说至少为 UINT_MAX。

然后maxlen传给了_snprintf_s,所以如果字符串大于1024个字符会再次造成缓冲区溢出。

我是不是漏掉了什么?将 maxlen 设置为 UINT_MAX 的原因可能是什么?使用安全字符串函数但没有安全性?

最佳答案

_snprintf_s(一个 Visual Studio 特定函数)的重载只能在 C++ 中使用,前提是可以从第一个参数推导出缓冲区长度。

参见 documentationRemarks 下的第二段有关 _TRUNCATE 魔法值及其作用的描述。

但请注意,对于早期版本的 VS,代码使用 _snprintf 实现此功能,它对宏 _TRUNCATE 一无所知:

#if _MSC_VER < 1400
// ...
#define _snprintf_s _snprintf

为了能够使用_snprintf,他必须安排缓冲区长度才能通过。 snprintf 没有可以推断字符缓冲区参数长度的模板化重载。此外,他需要 #define _TRUNCATE 因为在那些相同的旧版本中,它不存在于 stdlib.h 中。

总而言之,对于不必要的复杂非标准库函数,这让我觉得这是一个非常笨拙的解决方法。

关于c++ - 将 (size_t)-1 传递给 snprintf_s,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52326480/

相关文章:

c - 如何从字符串中删除所有出现的特定字符?

c++ - 具有对齐成员的对象的动态分配 - 可能的解决方案?

c++ - 如何使用 wstring 重命名文件?

c++ - 为什么 COM 接口(interface)契约是不可变的?

多次递归调用函数

c++ - 将参数从一个函数传递到另一个函数(没有模板)- C++

python - 如何使 C 包装器(用 32 位 Python 编写)在运行 64 位 Python 的新机器上工作?

c++继承 - 具有不同参数类型的相同方法名称

c++ - 在 C++ 的头文件中使用常量并在程序中询问它们的地址的任何潜在危险

c++ - 参数中的函数指针