簡體   English   中英

在python gdb腳本中索引c ++向量

[英]Indexing c++ vector in python gdb script

我想編寫一個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_evalgdb.parse_and_eval加載元素,每個方法都可以,但是速度太慢。

問題在於,暴露給Python的C ++對象不是“一流” Python對象-因此,它們不具有映射到相應機制以在對象的“ C ++”類中獲取項目的Python __getitem__方法。

另一方面,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中為gdb.Value對象創建一個包裝器類,該包裝器將實現自動執行此操作的__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_vectorgdb.Value -object拿着std::vector<T>此函數返回的Python列表gdb.Value類型的-objects T 基於此博客文章: https : //hgad.net/posts/object-inspection-in-gdb/

我發現這要比為所有i調用gdb.parse_and_eval['v[i]']快得多

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM