lan*_*oxx 5 c++ qt visual-studio-2013
我正在调试Visual Studio 2013中的Qt应用程序.我安装了Qt的官方Visual Studio插件.我可以看到内容QString,但对于任何其他QObject如a QDir或QFileInfo对象,我无法看到它的内容.
我做错了什么或者这根本不可能?
当我展开一个QDir实例时,我只能看到一个名为的成员d_ptr,它引用了一个QDirPrivate我无法检查的对象.我还不能调用的其他功能QDir或QFileInfo诸如path(),或filePath()在从调试器的运行时间.当我尝试Visual Studio声称该函数的地址已被优化.
无论如何调试这个而不向程序添加几十个日志语句?
UPDATE
在最后一个回答中详细说明这是不可能的,今天我找到了一种让调试器显示私有(隐藏)信息的方法.
注意:我保留下面的旧帖子,因为它暴露了我遵循的整个路径以达到此解决方案,我认为值得记录错误和错误的结论,所以没有其他人再次制作它们;).
假设你有一个QDir d;变量.您可以通过在Watch窗口中进行手动转换来检查其内部数据:
(Qt5Cored.dll!QDirPrivate*)d.d_ptr.d
Run Code Online (Sandbox Code Playgroud)
不幸的是,它没有显示任何有用的信息,因为您将面临内部成员的相同问题(私人数据未被打印).
但是,从这一点开始,您现在可以修改.natvis文件以在悬停时显示所需数据:
<?xml version="1.0" encoding="utf-8"?>
<AutoVisualizer xmlns="http://schemas.microsoft.com/vstudio/debugger/natvis/2010">
<Type Name="QDir">
<DisplayString>path={((Qt5Cored.dll!QDirPrivate*)d_ptr.d)->dirEntry.m_filePath}</DisplayString>
</Type>
</AutoVisualizer>
Run Code Online (Sandbox Code Playgroud)
我无法在Watch窗口中打印此信息(如果我Expand在.natvis文件中添加了一个似乎被省略的部分),但至少你有关于调试时间的这些信息.
我建议您查看要检查的类型的私有头文件或Watch窗口(如答案开头所述),以便您可以将正确的数据添加到.natvis文件中.
以前的分析有什么问题?
我认为关键是手工铸造.我提到了那个
dirEntry是一部分QDirPrivate,所以很明显调试器无法检查它.
这是部分正确的.问题是调试器不知道在哪里找到QDirPrivate它,因为它不是Qt的导出符号; 一旦我们明确指出(通过(Qt5Cored.dll!QDirPrivate*)演员表)它就能够检查它.
原始答案
AFAIK对于那些课程是不可能的.不幸的是,有一些私有结构没有导出,似乎调试器无法查看.
注意:我正在使用Qt 5.6.1,所以我将使用qt.io存储库中的源代码来匹配我的示例.
我们QDir举个例子:它在qdir.h中定义,它是Qt的公共API的一部分.它声明在同一个文件中,QDirPrivate但它的完整定义是在qtdir_p.h中,它不是公共API的一部分.
即使加载了符号,这个类的定义仍然对调试器来说是模糊的.请参阅下面我使用的.natvis文件示例:
<?xml version="1.0" encoding="utf-8"?>
<AutoVisualizer xmlns="http://schemas.microsoft.com/vstudio/debugger/natvis/2010">
<Type Name="QDir">
<DisplayString>Path: {d_func()->dirEntry.m_filePath}</DisplayString>
</Type>
</AutoVisualizer>
Run Code Online (Sandbox Code Playgroud)
但调试器在尝试观察时显示以下内容QDir d(qApp->applicationDirPath());:
错误:类"QDirPrivate"没有成员"dirEntry"
评估'd_func() - > dirEntry.m_filePath'时出错
但是dirEntry 是其中的一部分QDirPrivate,因此显然调试器无法检查它.dirEntry是类型QFileSystemEntry,在qfilesystementry_p.h(另一个私有类)中定义.
最后,如果您查看Qt VS Tools 中的qt5.natvis文件并在源代码中找到相应的类,您将看到所有包含的类公开了.natvis文件使用的结构的定义.
UPDATE
这些类的唯一公共API是方法,遗憾的是,不支持从调试器调用函数.引用Microsoft员工在MSDN论坛中的响应:
从调试器调用函数正在玩火.您可能会遇到跨线程依赖关系死锁(即使您没有任何显式的交叉线程依赖关系,也有内存分配等共享锁).这就是C++调试器不支持隐式funceval的原因.
实际上,如果您尝试调用QDir::absolutePath()监视窗口或.natvis文件中的任何方法,您将看到以下错误消息:
错误:函数QDir :: absolutePath没有地址,可能是由于编译器优化.
不是那么优雅的办法
一种可能的解决方案是使用存储这些私有值的包装类.您需要使用包装器替换每个对象,但可能有所帮助.
下面你会找到一个非常简单的例子QDir(你需要完成所需的构造函数并保存你想要的信息).请记住,Qt中的这类类型被设计为不可扩展,因此没有虚拟方法(因此请注意重新实现其中的一些并使用转换为基类的对象).
class MyQDir : public QDir {
public:
MyQDir(const QString& path) : QDir(path) {
m_absolutePath = absolutePath();
}
private:
QString m_absolutePath;
};
Run Code Online (Sandbox Code Playgroud)
并按照.natvis文件显示MyQDir悬停时的路径:
<?xml version="1.0" encoding="utf-8"?>
<AutoVisualizer xmlns="http://schemas.microsoft.com/vstudio/debugger/natvis/2010">
<Type Name="MyQDir">
<DisplayString>Path: {m_absolutePath}</DisplayString>
</Type>
</AutoVisualizer>
Run Code Online (Sandbox Code Playgroud)
最后,我认为剩下的唯一解决方案是将信息打印到console(qDebug()).
作为旁注,本教程将介绍如何编写自定义.natvis文件.这是2015年,但我已经完美地使用了2017年.我希望它也适用于2013年.
小智 6
我对 qt5.natvis 有以下扩展,它公开了 QDir、QFile 和 QFileInfo 的一些内容,建立在上面的原始建议的基础上:
<Type Name="QFileInfoPrivate">
<DisplayString Condition="0 == this"><null></DisplayString>
<DisplayString>{fileEntry}</DisplayString>
<StringView>fileEntry</StringView>
<Expand>
<Item Name="QSharedData">*((Qt5Cored.dll!QSharedData *) this)</Item>
<Item Name="fileEntry">fileEntry</Item>
<!--
<Item Name="metaData">metaData</Item>
<Item Name="fileListsInitialized">fileListsInitialized</Item>
<Item Name="fileEngine">fileEngine</Item>
<Item Name="fileNames">fileNames</Item>
<Item Name="fileOwners">fileOwners</Item>
<Item Name="cachedFlags">cachedFlags</Item>
<Item Name="isDefaultConstructed">isDefaultConstructed</Item>
<Item Name="cache_enabled">cache_enabled</Item>
<Item Name="fileFlags">fileFlags</Item>
<Item Name="fileSize">fileSize</Item>
<Item Name="fileTimes">fileTimes</Item>
-->
</Expand>
</Type>
<Type Name="QFileInfo">
<DisplayString>{*((Qt5Cored.dll!QFileInfoPrivate *) d_ptr.d)}</DisplayString>
<StringView>*((Qt5Cored.dll!QFileInfoPrivate *) d_ptr.d)</StringView>
<Expand>
<Item Name="QFileInfoPrivate">*((Qt5Cored.dll!QFileInfoPrivate *) d_ptr.d)</Item>
</Expand>
</Type>
<Type Name="QFileSystemEntry">
<DisplayString Condition="0 == this"><null></DisplayString>
<DisplayString>{m_filePath}</DisplayString>
<StringView>m_filePath</StringView>
<!--
<Expand>
<Item Name="m_filePath">m_filePath</Item>
<Item Name="m_nativeFilePath">m_nativeFilePath</Item>
<Item Name="m_lastSeparator">m_lastSeparator</Item>
<Item Name="m_firstDotInFileName">m_firstDotInFileName</Item>
<Item Name="m_lastDotInFileName">m_lastDotInFileName</Item>
</Expand>
-->
</Type>
<Type Name="QDirPrivate">
<DisplayString Condition="0 == this"><null></DisplayString>
<DisplayString>{dirEntry}</DisplayString>
<StringView>dirEntry</StringView>
<Expand>
<Item Name="QSharedData">*((Qt5Cored.dll!QSharedData *) this)</Item>
<Item Name="dirEntry">dirEntry</Item>
<Item Name="nameFilters">nameFilters</Item>
<Item Name="absoluteDirEntry">absoluteDirEntry</Item>
<!--
<Item Name="metaData">metaData</Item>
<Item Name="fileListsInitialized">fileListsInitialized</Item>
<Item Name="fileEngine">fileEngine</Item>
<Item Name="files">files</Item>
<Item Name="fileInfos">fileInfos</Item>
<Item Name="sort">sort</Item>
<Item Name="filters">filters</Item>
-->
</Expand>
</Type>
<Type Name="QDir">
<DisplayString>{*((Qt5Cored.dll!QDirPrivate *) d_ptr.d)}</DisplayString>
<StringView>*((Qt5Cored.dll!QDirPrivate *) d_ptr.d)</StringView>
<Expand>
<Item Name="QDirPrivate">*((Qt5Cored.dll!QDirPrivate *) d_ptr.d)</Item>
</Expand>
</Type>
<Type Name="QFilePrivate">
<DisplayString Condition="0 == this"><null></DisplayString>
<DisplayString>{fileName}</DisplayString>
<StringView>fileName</StringView>
<Expand>
<Item Name="QFileDevice">*((Qt5Cored.dll!QFileDevice *) this)</Item>
<Item Name="fileName">fileName</Item>
</Expand>
</Type>
<Type Name="QFile">
<DisplayString>{*((Qt5Cored.dll!QFilePrivate *) d_ptr.d)}</DisplayString>
<StringView>*((Qt5Cored.dll!QFilePrivate *) d_ptr.d)</StringView>
<Expand>
<Item Name="QFilePrivate">*((Qt5Cored.dll!QFilePrivate *) d_ptr.d)</Item>
</Expand>
</Type>
Run Code Online (Sandbox Code Playgroud)