【发布时间】:2020-01-16 10:04:06
【问题描述】:
在我工作的公司,我们中的一些人受到了 Visual Studio 中的错误/错误的影响。调试器无法显示 std::string 的值/内容。它说“读取字符串字符时出错。”
问题的一些图片: Simple string vars Values in debugger
以下行将始终重现该问题,但通常代码中的每个字符串(至少约 1'000'000 行)都会出现问题。
std::string testVar = "Something";
编辑:很快将尝试制作一个最小可重现示例,但现在我无法制作一个。该问题仅出现在由 93 个项目组成的单一解决方案中。 到目前为止尝试过:具有相同编译器版本(v120)、任何编译器版本、相同预处理器定义、VS2013 和 VS2017 的新解决方案(Professional 和 Enterprise 都产生问题)。现在安装VS2019进行测试。
我从 const char* 构造字符串,所以这可能与内存分配等无关...... 最重要的是,代码有效。 所以,std::string本身功能正常,但调试器无法显示它的值。 据我所见,大小是正确的,但容量始终为 0xcccccccccccccccc。 对于字符串中的字符说:“无法读取内存”。 Detailed view of string in debugger
这个问题只发生在 std::string 上,而不是 std::wstring 或 char * 或其他任何东西。 此外,当我打开一个新解决方案时,std::string 会正确显示。它仅无法在包含 91 多个项目的解决方案中显示。在 VS2017 和 VS2013 中均可重现,但我们使用的是 v120 编译器。尝试了 const 变量并将变量放在堆或堆栈上,没关系。
此外,它只发生在调试版本中,在发布模式下调试器工作正常。
此错误自本周以来一直存在,我们之前甚至超过一周前都没有观察到类似的情况。我们三个人有这个问题,但其他几个人没有。我们几乎都在运行具有相同配置和更新的相同机器。一个区别是工作的 VS 是专业版,而我们使用的是企业版。
我知道这不是一个严重的问题,因为代码可以正常工作,但这有时会使调试变得更加困难。
编辑: 可能很重要,当通过指令进行调试时,调试器不会进入构造函数或任何 std::string 函数(在 xstring 中),它会简单地跳过它,因为它是一个简单的 int 变量赋值,不是函数调用。但是在std::string的源代码中设置断点实际上会起作用,并且调试器会停在那里。
EDIT2 - 找到了错误的原因,但还没有真正的解决方案
在分析了std::string中指针的值后,我发现了调试器提取字符串失败的原因。调试器使用 +8 字节偏移量查找它。 解释一下:假设我创建了一个 std::string,并获取它的指针。
std::string testStr = "test";
std::string* strPtr = &testStr;
那么,strPtr = 0x0000000001bdf4a8。 现在,当我查看调试器的“Locals”窗口并查看字符串的原始视图并在 _Bx 联合中找到指针时,然后: _Buf = 0x0000000001bdf4b0 这是 strPtr+8。这就是它无法解码字符串内容的原因。因为它试图在错误的地址解释它。 如果我这样做:
std::string* fixedStr = reinterpret_cast<std::string*>(reinterpret_cast<char*>(&testStr)-8);
因此,当我手动将指针减少 8 个字节并将其重新转换为字符串时,调试器将正确显示其内容。 (当然,这个字符串损坏了,不能用,只有调试器显示是固定的)
当我打开一个新的解决方案并以相同的方式查看字符串的地址时,调试器会显示与字符串指针相同的 _Buf 地址,这是正常行为。两者的区别在于,当它解码字符串失败时,std::_Container_base 的类型为 std::_Container_base12 并且有内容,而当它工作时,它有 std::_Container_base0 并且内容为零。那些额外的内容可能会导致额外的 8 个字节。
我找到但没有提供解决方案的相关内容(尝试了此处的方法但问题仍然存在): Visual C++ 2010 refuses to show std::string value when debugging. Shows <Bad Ptr>
Visual Studio debugger doesn't display std::string properly in debug
还试图根据这个来搞乱 natvis: How to visualise a simple std::string with natvis?
【问题讨论】:
-
也许是个愚蠢的问题,但是你有没有在这些声明之后放置断点?如果这些行还没有执行,它们将没有任何价值。
-
想法1:仔细检查某处是否有错误的
.natvis。想法 2:这可能最好直接向 Microsoft 报告。 -
发布实际代码会很好。
-
0xcccccccccccccccc - 是调试版本中的 Visual Studio 常量,用于发出“未初始化内存”信号。提示堆栈对象尚未构造或设置为任何值。
-
请创建一个合适的minimal reproducible example 以文本形式而不是图像形式向我们展示。
标签: c++ string visual-studio debugging visual-studio-debugging