我正在广泛使用fmtlib中的fmt::format。在将Visual Studio 2022从17.3.5更新到17.4.0后,我在发布构建版本中遇到了如下代码的问题:
const std::string s1 = format("{}.{}", "abc", "test" );
虽然s1和s1.c_str()在调试构建中是“abc.test”,但在使用fmtlib的发布构建中,只有s1是“abc.test”,s1.c_str()返回“abc.test”,后跟一些垃圾(例如“abc.testð_àô”)。
我写了一个小测试程序:
#include <iostream>
#include <string>
#ifdef USE_STD_FORMAT
#include <format>
using std::format;
#else
#include <fmt/format.h>
using fmt::format;
#endif
void check(const std::string& s, const std::string& expected)
{
if (s != expected)
std::cout << "FAILED I: '" << s << "' != '" << expected << "'\n";
else if (strcmp(s.c_str(), expected.c_str()) != 0)
std::cout << "FAILED II: '" << s.c_str() << "' != '" << expected.c_str() << "'\n";
}
void test(const char* p1, const char* p2)
{
const std::string s1 = format("{}.{}", p1, p2);
const std::string s2 = std::string(p1).append(".").append(p2);
check(s1, s2.c_str());
}
int main()
{
std::cout << "_MSC_FULL_VER: " << _MSC_FULL_VER << "\n";
#if USE_STD_FORMAT
std::cout << "using std::format\n";
#else
std::cout << "using fmt::format\n";
#endif
test("abc", "test");
test("abc", "test");
}
使用VS2022 17.3.5构建,输出为:
C:\Temp\VS2022_17.4\x64>C:\Temp\VS2022_17.4\x64\Debug\VS2022_17.4.exe
_MSC_FULL_VER: 193331630
using fmt::format
C:\Temp\VS2022_17.4\x64>C:\Temp\VS2022_17.4\x64\Release\VS2022_17.4.exe
_MSC_FULL_VER: 193331630
using fmt::format
C:\Temp\VS2022_17.4\x64>C:\Temp\VS2022_17.4\x64\Release_StdFormat\VS2022_17.4.exe
_MSC_FULL_VER: 193331630
using std::format
使用VS2022 17.4.0构建,输出为
C:\temp\VS2022_17.4\x64>C:\temp\VS2022_17.4\x64\Debug\VS2022_17.4.exe
_MSC_FULL_VER: 193431933
using fmt::format
C:\temp\VS2022_17.4\x64>C:\temp\VS2022_17.4\x64\Release\VS2022_17.4.exe
_MSC_FULL_VER: 193431933
using fmt::format
FAILED II: 'abc.testð_àô ' != 'abc.test'
FAILED II: 'abc.testð_àô ' != 'abc.test'
C:\temp\VS2022_17.4\x64>C:\temp\VS2022_17.4\x64\Release_StdFormat\VS2022_17.4.exe
_MSC_FULL_VER: 193431933
using std::format
因为它在两个Visual Studio版本中都可以使用std::format,并且在两个格式版本中都可以使用VS2022 17.3.6,所以我不知道这是Visual Studio中的问题还是fmtlib中的问题,或者是我的代码中的问题。
1条答案
按热度按时间nkhmeac61#
这是Microsoft STL中的一个错误,引用https://developercommunity.visualstudio.com/t/Code-using-fmtlib-format-breaks-after-Vi/10198870:
问题是std::string的构造函数本身没有添加空终止符,因此当使用非空终止的char * 构造时,c_str()将返回垃圾,直到命中零字节。