You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用gdb.pretty_printers按行列打印结构体指针成员?报错求助

解决GDB打印自定义矩阵结构体时的"Cannot convert value to float."异常

问题背景

定义的C结构体:

typedef uint8_t matrix_size_t;
typedef float ElemType;
struct _matrix {
  /* data */
  uint8_t inited;
  matrix_size_t rows;
  matrix_size_t cols;
  ElemType* data;
};

为了按行列格式打印Matrix.data,编写了以下GDB美化打印的Python代码:

import gdb
import numpy as np
import logging


class McuMatrixPrinter:

    def __init__(self, variety, val):
        self.variety = variety
        self.inited = val["inited"]
        self.rows = int(val["rows"])
        self.cols = int(val["cols"])
        self.data = val["data"]
        self.type = self.data.type.unqualified().strip_typedefs()
        self.data = self.data.cast(self.type.pointer())
        logging.info(self.type)
        logging.info(type(self.data))

    def to_string(self):
        if int(self.inited) == 0:
            return "This matrix has not been inited!"
        mat = np.zeros((self.rows, self.cols), dtype=np.float64)
        for row in range(self.rows):
            for col in range(self.cols):
                offset = row * self.cols + col
                item = (self.data + offset).dereference()
                logging.info(type(item))
                mat[row, col] = float(item)
        return "Matrix::%s<%d,%d>\n%s\n" % (self.variety, self.rows, self.cols,
                                            self.data, mat)


def PrintMatrix(val):
    type = val.type
    if type.code == gdb.TYPE_CODE_REF:
        type = type.target()

    type = type.unqualified().strip_typedefs()
    typename = type.tag
    if typename == None:
        return None
    if typename.find("_matrix") != -1:
        return McuMatrixPrinter("Matrix", val)
    return None


def register_matrix_printers(obj):
    "Register eigen pretty-printers with objfile Obj"
    logging.basicConfig(
        level=logging.DEBUG, 
        filename='/tmp/gdbpy.log',
        filemode='a',
        format=
        '%(asctime)s - %(pathname)s[line:%(lineno)d] - %(levelname)s: %(message)s'
    )
    if obj == None:
        obj = gdb
    obj.pretty_printers.append(PrintMatrix)

执行时出现异常:

(gdb) p vector
$1 = Python Exception <class 'gdb.error'> Cannot convert value to float.:

(gdb) p vector
$2 = Python Exception <class 'gdb.error'> Cannot convert value to float.:

问题原因

异常触发在float(item)行:

  1. item是GDB的gdb.Value对象,直接用Python原生float()转换会因为类型不兼容报错;
  2. 代码中冗余的指针类型转换操作,可能导致data指针的实际类型与预期不符;
  3. 字符串返回格式存在错误,直接拼接指针对象会引发额外格式问题。

修复方案

1. 修正指针类型处理

结构体中data已经是ElemType*(即float*),无需额外的类型转换,直接使用原始指针即可。

2. 正确获取浮点数数值

使用gdb.Value对象自带的float()方法提取数值,而非Python原生float()函数。

3. 修正返回字符串格式

移除多余的指针拼接,只保留矩阵的可读格式输出。

修改后的McuMatrixPrinter类代码:

class McuMatrixPrinter:

    def __init__(self, variety, val):
        self.variety = variety
        self.inited = val["inited"]
        self.rows = int(val["rows"])
        self.cols = int(val["cols"])
        # 直接使用原始data指针,无需额外类型转换
        self.data = val["data"]
        logging.info(self.data.type)
        logging.info(type(self.data))

    def to_string(self):
        if int(self.inited) == 0:
            return "This matrix has not been inited!"
        mat = np.zeros((self.rows, self.cols), dtype=np.float64)
        for row in range(self.rows):
            for col in range(self.cols):
                offset = row * self.cols + col
                item = (self.data + offset).dereference()
                logging.info(type(item))
                # 使用gdb.Value的float()方法获取正确数值
                mat[row, col] = item.float()
        # 格式化返回矩阵信息
        return f"Matrix::{self.variety}<{self.rows},{self.cols}>\n{mat}"

额外注意

如果目标是MCU程序,需确认字节序是否与GDB运行环境一致(大部分现代MCU为小端,与PC环境兼容,无需额外处理)。

内容的提问来源于stack exchange,提问作者user14503825

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.30 16:06:28