2009-04-11 69 views
4

是否有可能对复杂结构甚至C++数组执行“转储”,以便直观地检查出它们里面的内容?C++中的变量转储

我正在考虑类似于PHP中的print_r()或var_dump()。

干杯, -fin

回答

1

一般不可能在C++中,因为它需要使用反射,其C++所没有的。您当然可以编写自己的函数来转储特定的数据结构。

8

简短的回答是:不,你自己手动编写这样的程序。

这通常不是一个坏主意,但如果您经常添加/更改成员,那么它通常会遇到与课程不同步的问题。这是不可避免的,因为C++缺乏对struct的任何形式的自省。

如果你决定这样做,最好的办法是编写一个std::ostream& operator<<(std::ostream& os, MyClass const&)的重载,这将使您的类可以打印到任何IOStreams输出流。

+0

与供应运营商唯一的问题<<()是它那种意味着运营>>()存在,在这种情况下,它可能不会。我更喜欢命名的DumpOn(ostream&os)函数。 – 2009-04-11 14:03:14

3

除了其他答案之外,根据您的需要以及您是否关心可移植性,您可能会考虑从编译器生成的调试信息中获取所需的信息。您可以从构建中解析COFF/ELF /格式文件,并为您提供所需的信息,以确定对象中变量的名称和类型。

3

如果向C++(使用第三方库或供应商扩展)添加反射,则可以编写例程以使用该反射数据来转储任意结构。例如,我有一些代码使用CERN的Reflex库来遍历类或结构的成员,并将它们转储到YAML

4

通常调试器足够聪明来做到这一点。

在GDB你可以使用:

print structure 

和NTSD你可以做超酷:

dt -r structure 

如果你仅仅使用这个调试目的,我强烈建议学习使用调试器。即使你想记录你的东西(即打印数十亿次),你也可以设置一个断点宏。

在NTSD:

bp yourdll!yourobject::yourfunction "dt -r structure;g" 

而且我敢肯定是有办法做到这一点的GDB以及

0

事实上,在您在您的处置有GDB的环境和你编译启用调试符号的源代码(例如-ggdb),你可以使用你的调试器(例如gdb从命令行或者ddd当你需要图形化的东西时)。

考虑这段代码:

#include <string> 
#include <vector> 

struct test 
{ 
    int a; 
    float b; 
    std::string c; 
}; 

int main() 
{ 
    std::vector<int> v; 

    test t; 
    t.a=1; 
    t.b=2.0; 
    t.c="hello there"; 


    return 0; 
} 

当问GDB礼貌它可以给我下面的输出:

 
(gdb) break 20 
Breakpoint 1 at 0x8048622: file bla.cpp, line 20. 
(gdb) run 
Starting program: /home/edb/a.out 

Breakpoint 1, main() at bla.cpp:21 
21  return 0; 
(gdb) print t 
$1 = {a = 1, b = 2, c = {static npos = 4294967295, 
    _M_dataplus = {> = {> = {}, }, _M_p = 0x96b6014 "hello there"}}} 
(gdb) ping v 
Undefined command: "ping". Try "help". 
(gdb) print v 
$2 = { >> = { 
    _M_impl = {> = {> = {}, }, _M_start = 0x0, _M_finish = 0x0, 
     _M_end_of_storage = 0x0}}, } 

编辑:请注意,这个数据可以从一个调试器背景下,在运行时生成这些转储文件时,您需要预见自己的转储/格式化功能,通常通过在C++中重载运算符来完成。

0

为什么不使用二进制文件? fstream有二进制模式,您可以转储除struct,class,namespace或STL列表(如向量,队列)之外的任何类型。 想要转储结构,类,名称空间(或STL列表)为二进制?创建一个函数,然后转储文件中的每个变量!结束!那不会那么难...... 但想要更多帮助?看看这个代码片段!

#include <iostream> 
#include <fstream>//ofstream,ifstream 
using namespace std; 
ifstream myBdumpin ("data.bin"/*filename*/, ios::in);//ifstream = input 
ofstream myBdumpout ("data.bin"/*filename*/, ios::out);//ofstream = output 
int main() 
{ 
    char a[8]="Binary!" 
    myBdumpout << a; 
    char b[8]; 
    myBdumpin >> b; 
    if(a == b)cout << "It worked!" << endl; 
    else cout << "It failed..." << endl; 
    return 0; 
} 

它应该工作...