简体   繁体   中英

How to print actual(derived) object properties in LLDB

Code example:

class IA
{
public:
    virtual int getA() = 0;
};

class A:public IA
{
public:
    int getA() override
    {
        return m_a;
    }
private:
    int m_a = 10;
};

void main()
{
    A* a = new A();
    IA* ia = a;
}

In GDB with set print object on I can easily print a object contents using ia pointer.

//with print object on
p *ia
$1 = (A) {<IA> = {_vptr$IA = 0xf330c8 <vtable for A+16>}, m_a = 10}

//without print object on
p *ia
$2 = {_vptr$IA = 0xf330c8 <vtable for A+16>}

Is it possible to do the same in lldb? I've failed to find anything in official documentation. That's what i get in lldb:

p *ia
(IA) $0 = {}
p *a
(A) $1 = (m_a = 10)

lldb has two methods for accessing typed values from the target program, expr (aliased to p ) and frame variable (aliased to v ).

expr is a full expression evaluator that uses the clang front & backends to parse and evaluate the expression you pass it "as if it were inserted into the code at the point where you are stopped".

frame var is a C-ish pseudo-language for accessing elements of variables, or registers or memory regions.

Then the resultant value from either method is presented through a common system, first by fetching the "dynamic type" of the result (the equivalent of setting 'print object' on), then passing it through the "data formatters" architecture.

When processing:

(lldb) p *ia

the pointer has been dereferenced by the time it is returned as a value from the expression to the "dynamic type" detection stage, which consequently can't tell it really came from a pointer to A.

lldb made the choice to have expr follow the rules of the source language as closely as possible, which gets in the way here, but means you can pass quite complex expressions to the command and have them work as they would in code.

Among other things, it can do C++ casts, so if you need to have the dynamic type available (eg if you want to call a method that's only in the full type) you can do it by hand:

(lldb) p ((A *)ia)->some_A_method()

gdb's print uses a hand built parser that evaluates expressions from the deepest subexpression out, so it can stop to get the dynamic type of each subexpression as it goes. Doing it that way makes the job of being an accurate C++ parser harder, however. There are always tradeoffs...

OTOH,

(lldb) v *ia
(A) *ia = (m_a = 10)

can fetch the dynamic type because the v parser returns an object: "SBValue" for the dereferenced value of the "SBValue" representing the local variable ia - so the result knows where the value came from, and can fetch all the dynamic types along the way in the printing stage. We haven't taught v to do casting or function calling yet - mostly to keep its parser simple and predictable. But otherwise, v is usually more convenient for variable printing than p .

When you are just printing local variables, or their children, v is also more efficient, and less fragile, since it only has to realize the value's type and fetch its memory, not emulate the current context well enough to satisfy clang.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM