C++ Visual Studio可以';t显示std::string的值

C++ Visual Studio可以';t显示std::string的值,c++,string,visual-studio,debugging,visual-studio-debugging,C++,String,Visual Studio,Debugging,Visual Studio Debugging,在我工作的公司,我们中的一些人受到Visual Studio中的错误的影响。调试器无法显示std::string的值/内容。它表示“读取字符串的字符时出错。” 本期部分图片: 下一行将始终重现该问题,但通常代码中的每个字符串(至少1'000'000行)都会有该问题 std::string testVar = "Something"; 编辑:我将尝试尽快制作一个最小的可复制示例,但目前我无法制作一个。这个问题只存在于由93个项目组成的单一解决方案中。 迄今为止已经尝试过:具有相同编译器版本(v

在我工作的公司,我们中的一些人受到Visual Studio中的错误的影响。调试器无法显示std::string的值/内容。它表示“读取字符串的字符时出错。”

本期部分图片:

下一行将始终重现该问题,但通常代码中的每个字符串(至少1'000'000行)都会有该问题

std::string testVar = "Something";
编辑:我将尝试尽快制作一个最小的可复制示例,但目前我无法制作一个。这个问题只存在于由93个项目组成的单一解决方案中。 迄今为止已经尝试过:具有相同编译器版本(v120)、任何编译器版本、相同预处理器定义的新解决方案,VS2013和VS2017(专业版和企业版都会产生此问题)。现在安装VS2019来测试它

我从const char*构造字符串,因此这可能与内存分配等无关最重要的是,代码可以正常工作。因此,std::string本身可以正常工作,但调试器无法显示其值。 据我所知,大小是正确的,但容量始终为0xCCCC。 因为字符串中的字符是:“无法读取内存”。

此问题仅发生在std::string上,而不发生在std::wstring或char*或其他任何情况下。 另外,当我打开一个新的解决方案时,std::string将正确显示。它只能在包含91个以上项目的解决方案中显示。可在VS2017和VS2013中复制,但我们使用的是v120编译器。尝试常量变量,并将变量放在堆或堆栈上,这并不重要

此外,它只发生在调试构建中,在发布模式下,调试器工作正常

这个错误从本周起就存在了,我们以前甚至一周多以前都无法观察到类似的情况。我们中有3个人有这个问题,但其他几个人没有。我们都在用相同的配置和更新运行几乎相同的机器。一个区别是,工作VS是专业的,我们使用企业版

我知道这不是一个严重的问题,因为代码可以正常工作,但这有时会使调试更加困难

编辑: 可能很重要的是,当通过单步执行指令进行调试时,调试器不会单步执行构造函数或任何std::string函数(在xstring中),它只会单步执行,因为它是一个简单的int变量赋值,而不是函数调用。但是在std::string的源代码中设置断点实际上是可行的,调试器将停止在那里

EDIT2-找到了错误的原因,但还没有真正的解决方案

在分析std::string中指针的值之后,我找到了调试器无法提取字符串的原因。调试器使用+8字节偏移量查找它。 解释一下:假设我创建了一个std::string,并得到它的指针

std::string testStr = "test";
std::string* strPtr = &testStr;
然后,strprtr=0x0000000001bdf4a8。 现在,当我查看调试器的“Locals”窗口,查找字符串的原始视图并在_Bx联合中找到指针时,然后: _Buf=0x0000000001bdf4b0 这是STRPR+8。这就是它无法解码字符串内容的原因。因为它试图在错误的地址解释它。 如果我这样做:

std::string* fixedStr = reinterpret_cast<std::string*>(reinterpret_cast<char*>(&testStr)-8);
std::string*fixedStr=reinterpret\u cast(reinterpret\u cast(&testStr)-8);
因此,当我手动将指针减少8个字节并将其重新转换为字符串时,调试器将正确显示其内容。(当然,此字符串已损坏且无法工作,只有调试器显示已修复)

当我打开一个新的解决方案并以相同的方式查看字符串的地址时,调试器会显示与字符串指针相同的_Buf地址,这是正常的行为。两者之间的区别在于,当它无法解码字符串时,std::_Container_base的类型为std:_Container_base 12并包含内容,而当它工作时,它的类型为std:_Container_base 0且内容为零。这些额外的内容可能会导致额外的8字节

我找到了相关的东西,但没有提供解决方案(尝试了这里的方法,但问题仍然存在):

还试图和natvis混在一起 解决方案: 此问题是由以下预处理器定义引起的:

_HAS_ITERATOR_DEBUGGING=0
这导致std::string继承与std:_Container_base12和 std::_容器_基础0。这是有意的,当然是有意的。但由于某种原因,调试器不知道这一点,并试图像往常一样解释std::string

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

_ITERATOR_DEBUG_LEVEL
将此值定义为0而不是旧值并不能解决问题,但将其定义为1解决了问题(默认值为2)。我不得不禁用一些警告,这将在以后进行研究,但问题已经解决。

旧的:

未能找到问题的根本原因,但正在从 VS2013/VS2017使用v120构建工具将VS2019 v142解决了这个问题

很可能是旧的构建工具与此有关


也许这是个愚蠢的问题,但在这些声明之后有断点吗?如果这些行还没有执行,它们就没有任何价值。想法1:仔细检查是否有坏的
.natvis
。想法2:这可能最好直接向Microsoft报告。发布实际代码会更好。0xCCCC-是调试构建中的Visual Studio常量,表示“未初始化内存”。这是一个堆栈对象尚未构造或设置为任何值的提示。请创建一个适当的脚本,以文本而不是图像的形式向我们显示。