Visual Studio 调试器中的表达式

Visual Studio 调试器包括表达式计算器,可在“ 快速监视 ”对话框、 “监视 ”窗口或 “即时 ”窗口中输入表达式时工作。 表达式计算器也在 断点 窗口和调试器中的其他许多位置工作。

以下部分介绍 Visual Studio 支持的语言的表达式计算限制。

不支持 F# 表达式

无法识别 F# 表达式。 如果要调试 F# 代码,则需要在将表达式输入调试器窗口或对话框之前将表达式转换为 C# 语法。 将表达式从 F# 转换为 C# 时,请务必记住 C# 使用 == 运算符来测试相等性,而 F# 则使用单个 =

C++表达式

有关在 C++ 中结合使用上下文运算符和表达式的信息,请参阅上下文运算符(C++)。

C++中不支持的表达式

构造函数、析构函数和转换

不能显式或隐式调用对象的构造函数或析构函数。 例如,以下表达式显式调用构造函数并生成错误消息:

my_date( 2, 3, 1985 )

如果转换的目标为类,则无法调用转换函数。 此类转换涉及对象的构造。 例如,如果myFraction是一个定义转换函数运算符CFractionFixedPoint实例,则以下表达式会导致错误:

(FixedPoint)myFraction

无法调用新的或删除运算符。 例如,不支持以下表达式:

new Date(2,3,1985)

预处理器宏

调试器不支持预处理器宏。 例如,如果常量VALUE声明为:#define VALUE 3,则无法在VALUE”窗口中使用。 若要避免此限制,应尽可能将 #define“替换为枚举和函数”。

使用命名空间声明

不能使用 using namespace 声明。 若要访问当前命名空间之外的类型名称或变量,必须使用完全限定的名称。

匿名命名空间

不支持匿名命名空间。 如果您有以下代码,则无法将 test 添加到监视窗口中。

namespace mars
{
    namespace
    {
        int test = 0;
    }
}
int main()
{
    // Adding a watch on test doesn't work.
    mars::test++;
    return 0;
}

使用调试器内部函数维护状态

调试器内部函数提供了一种在表达式中调用某些 C/C++ 函数的方法,而无需更改应用程序的状态。

调试器内部函数:

  • 保证安全:执行调试器内部函数不会损坏正在调试的进程。

  • 允许在所有表达式中使用,即使在不允许副作用和函数计算的情况下也是如此。

  • 在无法进行常规函数调用(例如调试小型转储)的情况下工作。

    调试器内部函数还可以使计算表达式更加方便。 例如,在断点条件中,strcmp(str, "asd") 的书写要比 str[0] == 'a' && str[1] == 's' && str[2] == 'd' 容易得多。 )

Area 内部函数
字符串长度 strlen、wcslen、strnlen、wcsnlen
字符串比较 strcmp、wcscmpstricmp、wcsicmp_stricmp、_strcmpi、_wcsicmp、_wcscmpi、strncmp、wcsncmp、strnicmp、wcsnicmp、_strnicmp、_wcsnicmp
字符串搜索 strchr、wcschrmemchr、wmemchr、strstr、wcsstr
Win32 CoDecodeProxyDecodePointerGetLastErrorTlsGetValue
Windows 8 RoInspectCapturedStackBackTraceWindowsCompareStringOrdinalWindowsGetStringLenWindowsGetStringRawBuffer

这些函数要求正在调试的进程在 Windows 8 上运行。 调试从 Windows 8 设备生成的转储文件,还需要 Visual Studio 计算机运行 Windows 8 操作系统。 但是,如果要远程调试 Windows 8 设备,Visual Studio 计算机可以运行 Windows 7。
WindowsGetStringLen 并且 WindowsGetStringRawBuffer 仅由源级别的执行引擎 (EE)使用。
Miscellaneous __log2 - 返回指定整数的对数基 2,舍入为最接近的下限整数。

__findNonNull - 搜索指针数组,返回第一个非 null 元素的索引。
- 参数:(1)指向数组中第一个元素的指针(void*),(2)数组大小(无符号 int)。
- 返回值:(1) 数组中第一个非 null 元素的基于 0 的索引,如果未找到,则返回 -1。

DecodeHString - 辅助函数,用于格式化 HSTRING 的值。 从堆栈中弹出 HSTRING 值,并推送 StringInfo 结构的字节,使 EE 可以判断字符串的位置。 这仅供 EE 内部使用;它不可供用户直接调用。

DecodeWinRTRestrictedException - 解码 WinRT 受限异常以获取受限说明。
- 参数:一个以 null 结尾的字符串,该字符串代表受限引用字符串的字符(1)。
- 返回值:一个以null结尾的字符串,其中的字符包含要显示的实际错误消息。

DynamicCast - 实现dynamic_cast。
- 参数:(1)指向被转换对象的指针。
- 数据项:CDynamicCastData 对象应作为数据项关联到相应的 ExecuteIntrinsic() 指令。 数据项对我们要转换的类型进行编码,包括要从哪种类型转换到哪种类型,以及是否要评估 natvis 表达式(这是诊断中断无限递归所必需的)。
- 返回值:(1) 指向对象的指针,强制转换为正确的类型,如果要强制转换的对象不是正确类型的实例,则为 NULL。

DynamicMemberLookup - 帮助程序函数,用于动态获取类成员的值

GetEnvBlockLength - 帮助程序函数,用于获取环境块的长度(以字符为单位)。 用于环境变量$env。

Stdext_HashMap_Int_OperatorBracket_idx - stdext::hash_map 的运算符[] 。 假定默认哈希函数的键为“int”。 返回值。 内部运算符[] 仅支持从哈希表中检索现有项 - 它不支持将新项插入表中,因为这可能涉及不必要的复杂性,例如内存分配。 但是,operator[] 可用于修改表中已存在键的值。
- 堆栈参数:(1) stdext::hash_map 对象的地址(2) 表(int)、(3) 一个 HashMapPdb 结构中的键,该结构指定函数实现需要执行查找的成员的字段偏移量。 因为在远程端不可直接访问符号,所以这是必要的。
- 返回值:(1) 如果键位于表中,则表示对应于键的值的地址。 否则为 NULL。

Std_UnorderedMap_Int_OperatorBracket_idx - std::unordered_map的工作方式与 stdext::hash_map 相同,但哈希函数不同。

ConcurrencyArray_OperatorBracket_idx // Concurrency::array<>::operator[index<>] 和 operator(index<>)

ConcurrencyArray_OperatorBracket_int // Concurrency::array<>::operator(int、int、...)

ConcurrencyArray_OperatorBracket_tidx // Concurrency::array<>::operator[tiled_index<>] 和 operator(tiled_index<>)

ConcurrencyArrayView_OperatorBracket_idx // Concurrency::array_view<>::operator[index<>] 和 operator(index<>)

ConcurrencyArrayView_OperatorBracket_int // 并发::array_view<>::operator(int、int、...)

ConcurrencyArrayView_OperatorBracket_tidx // Concurrency::array_view<>::operator[tiled_index<>] 和 operator(tiled_index<>)

TreeTraverse_Init - 初始化新的树遍历。
支持基于扩展的可视化工具,不适用于 .natvis 文件中。

TreeTraverse_Next - 从挂起的树遍历中检索节点。
支持基于扩展的可视化工具,不适用于 .natvis 文件中。

TreeTraverse_Skip - 跳过挂起的树遍历中的节点。
支持基于扩展的可视化工具,不适用于 .natvis 文件中。

C++/CLI - 不支持的表达式

  • 不支持涉及指针或用户定义的强制转换。

  • 不支持对象比较和分配。

  • 不支持重载运算符和重载函数。

  • 不支持装箱和拆箱。

  • Sizeof 不支持运算符。

C# - 不支持的表达式

动态对象

可以在静态类型为动态的调试器表达式中使用变量。 在“监视”窗口中计算实现 IDynamicMetaObjectProvider 的对象时,会添加动态视图节点。 动态视图节点显示对象成员,但不允许编辑成员的值。

不支持动态对象的以下功能:

  • 复合运算符 +=-=%=/=*=

  • 许多类型转换,包括数值型转换和类型参数转换

  • 带有两个以上参数的方法调用

  • 具有两个以上的参数的属性 getter

  • 带参数的属性设置器

  • 分配给索引器

  • 布尔运算符 &&||

匿名方法

不支持创建新的匿名方法。

Visual Basic - 不支持的表达式

动态对象

可以在类型为动态的静态调试器表达式中使用变量。 在监视窗口中计算实现该 IDynamicMetaObjectProvider 对象的对象时,将添加动态视图节点。 动态视图节点显示对象成员,但不允许编辑成员的值。

不支持动态对象的以下功能:

  • 复合运算符 +=-=%=/=*=

  • 很多转换,包括数值转换和类型参数转换

  • 具有两个以上的参数的方法调用

  • 具有两个以上参数的属性获取器

  • 带参数的属性 setter

  • 分配给索引器

  • 布尔运算符 &&||

本地常量

不支持本地常量。

导入别名

不支持导入别名。

变量声明

无法在调试器窗口中声明直接的新变量。 但是,可以在 “即时” 窗口中分配新的隐式变量。 这些隐式变量的范围限定为调试会话,在调试器外部无法访问。 例如,该语句 o = 5 隐式创建一个新变量 o ,并将值 5 分配给它。 此类隐式变量的类型为 Object ,除非调试器可以推断该类型。

不支持的关键字

  • AddressOf

  • End

  • Error

  • Exit

  • Goto

  • On Error

  • Resume

  • Return

  • Select/Case

  • Stop

  • SyncLock

  • Throw

  • Try/Catch/Finally

  • With

  • 命名空间或模块级关键字,例如 End SubModule