Visual Studio 无法显示 std::string 的值

Posted

技术标签:

【中文标题】Visual Studio 无法显示 std::string 的值【英文标题】:Visual Studio can't show the value of std::string 【发布时间】: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

https://developercommunity.visualstudio.com/content/problem/782573/visual-studio-debugger-doesnt-display-stdstring-pr.html

还试图根据这个来搞乱 natvis: How to visualise a simple std::string with natvis?

【问题讨论】:

也许是个愚蠢的问题,但是你有没有在这些声明之后放置断点?如果这些行还没有执行,它们将没有任何价值。 想法1:仔细检查某处是否有错误的.natvis。想法 2:这可能最好直接向 Microsoft 报告。 发布实际代码会很好。 0xcccccccccccccccc - 是调试版本中的 Visual Studio 常量,用于发出“未初始化内存”信号。提示堆栈对象尚未构造或设置为任何值。 请创建一个合适的minimal reproducible example 以文本形式而不是图像形式向我们展示。 【参考方案1】:

解决方案: 问题是由这个预处理器定义引起的:

_HAS_ITERATOR_DEBUGGING=0

这导致 std::string 与 std::_Container_base12 的继承差异和 std::_Container_base0。这是故意的,当然是设计使然。但由于某种原因,调试器不知道这一点,并试图像往常一样解释 std::string。

我无法删除宏,因为很多代码都因此而发疯,但是当我查看它的文档时,我意识到它已被弃用。新的 preproc。定义是:

_ITERATOR_DEBUG_LEVEL

将此值定义为 0 而不是旧值并没有解决问题,但将其定义为 1 解决了它(默认为 2)。结果我不得不禁用一些警告,稍后我必须查看,但问题已解决。

旧:

未能找到问题的根本原因,但更新自 VS2013/VS2017 用 v120 构建工具到 VS2019 v142 解决了。

很可能旧的构建工具与它有关。

【讨论】:

以上是关于Visual Studio 无法显示 std::string 的值的主要内容,如果未能解决你的问题,请参考以下文章

Visual Studio 在 python 中显示错误“无法访问”

Visual Studio 2022 有时会显示“应用程序无法正确启动”

无法在 SSIS 2012 中显示 Visual Studio Tools for Application Editor

无法显示Visual Studio 2008 Tools for Applications编辑器 - MSBuildToolsPath

用visual studio 2005做网站老是出现无法显示网页,怎么回事??

SSIS 2019查找转换编辑器的Visual Studio 2019表单无法正确显示-挤在一起的行