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

Visual Studio can't show the value of std::string

在我工作的公司,我们中的一些人在 Visual Studio 中受到了 bug/error 的影响。调试器无法显示 std::string 的 value/content。它说 "Error reading characters of string."

问题的一些图片: Simple string vars Values in debugger

下一行总是会重现问题,但通常代码中的每个字符串(至少 ~1'000'000 行)都会有问题。

std::string testVar = "Something";

编辑:将尽快尝试制作一个最小可复制示例,但现在我无法制作。该问题仅出现在由 93 个项目组成的单个解决方案中。 到目前为止已尝试:具有相同编译器版本 (v120)、任何编译器版本、相同预处理器定义、VS2013 和 VS2017 的新解决方案(专业版和企业版都会产生该问题)。现在安装VS2019测试一下

我从 c​​onst char* 构造字符串,所以这可能与内存分配等无关...最重要的是,代码有效。所以, std::string 本身可以正常运行,但调试器无法显示它的值。 据我所知,大小是正确的,但容量始终是 0xcccccccccccccccc。 对于字符串中的字符表示:"Unable to read memory"。 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" window 并查找字符串的原始视图并在 _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:

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

_HAS_ITERATOR_DEBUGGING=0

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

我无法删除宏,因为很多代码因此而变得疯狂,但当我查看它的文档时,我意识到它已被弃用。新的预处理器。定义是:

_ITERATOR_DEBUG_LEVEL

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

旧:

Didn't manage to get the root cause of the issue, but updating from VS2013/VS2017 with v120 build tools to VS2019 v142 solved it.

Most likely the old build tools had something to do with it.