C++对象转为字符串

4

我希望将一个C++对象的内容(实现了循环缓冲区)输出到字符串以进行日志记录。我原本计划手动完成此操作,但是后来注意到在GDB调试器中运行print-object命令会给出一个漂亮格式化的输出,例如:

(gdb) print audioDebugMessageQueue
$1 = {
  writePointer = 1, 
  readPointer = 0, 
  keys = {{
      samples = {0.155292124, 0.106764726}, 
      timeStamp = 1322767911, 
      numFrames = 1024
    }, {
      samples = {0, 0}, 
      timeStamp = 0, 
      numFrames = 0
    }, {
      samples = {0, 0}, 
      timeStamp = 0, 
      numFrames = 0
    }, {
      samples = {0, 0}, 
      timeStamp = 0, 
      numFrames = 0
    }, {
      samples = {0, 0}, 
      timeStamp = 0, 
      numFrames = 0
    }, {
      samples = {0, 0}, 
      timeStamp = 0, 
      numFrames = 0
    }, {
      samples = {0, 0}, 
      timeStamp = 0, 
      numFrames = 0
    }, {
      samples = {0, 0}, 
      timeStamp = 0, 
      numFrames = 0
    }, {
      samples = {0, 0}, 
      timeStamp = 0, 
      numFrames = 0
    }, {
      samples = {0, 0}, 
      timeStamp = 0, 
      numFrames = 0
    }}
}

如果GDB可以访问我的对象的漂亮转储,我认为我也可以。但是如何做到呢?顺便说一下,我在iOS上。

这个是在GDB中实现的,它是对exe文件的二进制代码的解释。我很确定你不能在你的C++程序中使用它,除非你在GDB的源代码中找到那段代码并“偷”了它:? 但还是要点赞+1。 - Kiril Kirov
2个回答

2
gdb之所以能够给你这样漂亮的输出,是因为如果指示(使用gcc的-g选项),编译器会生成一些关于如何解释程序中的二进制结构的额外信息,除了正常的代码。调试器读取并解释这些额外信息,然后在打印对象时使用它来输出您的对象。请注意,如果您的文件中不包含调试信息(即如果您不使用-g),则即使您告诉它变量位于哪里(另一个调试信息包含的信息),gdb也无法提供这样漂亮的打印。

现在,您可以编写代码来读取程序的调试信息,然后使用它来显示类(或者,如果许可证允许,甚至使用现有代码)。但是,除非您正在使用它来处理非常多不同类型的对象(并且可以接受必须使用带有调试信息的编译器的限制,这可能有助于人们进行反向工程),否则仅手动编写打印代码几乎肯定更容易。

当然,另一个选择是要求安装gdb,并从程序中调用它以生成输出。然而,这可能不是您想要做的(它将绕过任何许可问题)。


如果你想要做得非常疯狂,你可以编写一个程序,根据调试信息为你的类型生成代码流插入运算符,就像蛇吃自己的尾巴一样。如果有人真的这样做了,我会由衷地祝贺他们,然后在我的嘴里呕吐一些东西。 - zinglon

1

为你的每个类编写流插入运算符,然后为你的类本身编写,最后为容器编写。

给定

class C {
   public: 
   int a;
   sometype b;

}

typedef std::vector< C > Cvector;

你可能想要这样的东西:

template<class E, class T>
std::basic_ostream<E,T> &operator <<( std::basic_ostream<E,T> &s, const sometype & a ) { /* ... */ }

template<class E, class T>
std::basic_ostream<E,T> &operator <<( std::basic_ostream<E,T> &s, const C& a_c ) 
{
     s << std::hex << std::setw(8) << a_c.a << std::endl
       << a_c.b;
}

template<class E, class T>
std::basic_ostream<E,T> &operator <<( std::basic_ostream<E,T> &s, const Cvector & cvec  ) 
{
     for ( iterator i = cvec.begin(); i != cvec.end(); ++i )
          s << *i << std::endl;
}

[考虑以下伪代码...]


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接