我想编写一个python脚本来分析算法的调试器状态,但是我不知道如何使索引向量的基本示例起作用。
例如,调试以下文件 (gdb_test.cpp( 时:
#include <iostream>
#include <vector>
int main()
{
std::vector<int> v = {1, 2, 3, 4, 5};
std::cout << v.size() << std::endl;
for (const auto& element : v)
{
std::cout << element << std::endl;
}
}
使用 gdb 并获取以下脚本 (print_vector.py(,该脚本旨在打印出由名称提供的输入向量的前三个元素:
import gdb
class print_vector(gdb.Command):
def __init__(self):
super(print_vector, self).__init__('print_vector',
gdb.COMMAND_SUPPORT,
gdb.COMPLETE_FILENAME)
def invoke(self, arg, from_tty):
# Access the variable from gdb.
frame = gdb.selected_frame()
args = arg.split('; ')
val = frame.read_var(args[0])
for i in range(3):
print(val[0])
print_vector()
使用命令:
g++ gdb_test.cpp -std=c++11 -g
gdb ./a.out
(gdb) b gdb_test.cpp:10
(gdb) r
(gdb) source print_vector.py
(gdb) print_vector v
我收到错误
Python Exception <class 'gdb.error'> Cannot subscript requested type.:
Error occurred in Python command: Cannot subscript requested type.
这是指print(val[0])
行。问题是gdb.Value
对象不能作为列表进行索引。还有其他方法可以访问元素吗?
我也尝试过像val['at'][0]
和val['at(0)']
这样的东西,两者都不起作用。通过一次调用逐个加载元素以gdb.parse_and_eval
每个元素都可以工作,但速度太慢。
公开的C++对象不是"第一类"Python 对象 - 因此,它们没有映射到相应机制的 Python __getitem__
方法来获取对象的 "C++" 类中的项。
另一方面,API 确实公开了一个 parse_and_eval
方法,该方法将处理字符串,就好像它是在C++源中键入的一样 - 因此允许人们以简单的方式使用 Python 中的v[i]
-
对于上面的示例,您可以将 Python 源代码更改为:
import gdb
class print_vector(gdb.Command):
def __init__(self):
super(print_vector, self).__init__('print_vector',
gdb.COMMAND_SUPPORT,
gdb.COMPLETE_FILENAME)
def invoke(self, arg, from_tty):
# Access the variable from gdb.
frame = gdb.selected_frame()
args = arg.split('; ')
valname = args[0]
for i in range(3):
content_value = gdb.parse_and_eval(f"{valname}[{i}]")
print(int(content_value))
print_vector()
看看这个工作。对于更复杂的代码,可能值得在 Python for gdb 中创建一个包装类。将实现自动执行此操作的__getitem__
的值对象。
我最终在 c++11 中使用以下函数:
def vector_to_list(std_vector):
out_list = []
value_reference = std_vector['_M_impl']['_M_start']
while value_reference != std_vector['_M_impl']['_M_finish']:
out_list.append(value_reference.dereference())
value_reference += 1
return out_list
如果std_vector
是包含std::vector<T>
的gdb.Value
对象,则此函数返回类型为 T
的 gdb.Value
对象的 python 列表。基于这篇博文:https://hgad.net/posts/object-inspection-in-gdb/
我发现这比为所有i
调用gdb.parse_and_eval['v[i]']
要快得多