Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Innefficient creation of GDB variable #33

Open
AHeimberger opened this issue Jul 23, 2012 · 3 comments
Open

Innefficient creation of GDB variable #33

AHeimberger opened this issue Jul 23, 2012 · 3 comments

Comments

@AHeimberger
Copy link

At the beginning of a debug session -stack-list-variables is called returning the variables.
After that gdb will be informed to create an internal variable with -var-create.
Using the next button will call -var-update --all-values *. That's correct to receive the changelist,
but after that -var-create of all variables is called again.

#### breakpoint reached
(gdb) 
Running command -stack-list-variables --no-values
^done,variables=[ 
{name="twoDimArray"},{name="vec"},{name="deq"},
{name="oneDimArray"},{name="lst"},{name="bits"},
{name="que"},{name="st"},{name="mp"},{name="bitsetsize"}
]

##### creation of gdb internal variables
(gdb) 
Running command -var-create - * bitsetsize
^done,name="var1",numchild="0",value="0",type="const int",thread-id="1",has_more="0"
...
...

##### using next
(gdb) 
Running command -exec-next
^running
*running,thread-id="1"
(gdb) 
*stopped,reason="end-stepping-range",frame={addr="0x0000000000400c41",func="main",
args=[],file="main.cpp",fullname="/home/aheimberger/Sources/Testing/
stl-template-library/main.cpp",line="21"},thread-id="1",stopped-threads="all",core="0"

#### updating variables
(gdb) 
Running command -var-update --all-values "*"
^done,changelist=[
{name="var7.0",value="10",in_scope="true",type_changed="false",has_more="0"},
{name="var7.1",value="5",in_scope="true",type_changed="false",has_more="0"},
{name="var7.2",value="1",in_scope="true",type_changed="false",has_more="0"},
{name="var7.3",value="-5",in_scope="true",type_changed="false",has_more="0"},
{name="var7.4",value="-10",in_scope="true",type_changed="false",has_more="0"}
]

#### calling stack variables again
(gdb) 
Running command -stack-list-variables --no-values
^done,variables=[
{name="twoDimArray"},{name="vec"},{name="deq"},
{name="oneDimArray"},{name="lst"},{name="bits"},
{name="que"},{name="st"},{name="mp"},{name="bitsetsize"} 
]

#### creation of new but already existing variable
(gdb) 
Running command -var-create - * bitsetsize
^done,name="var11",numchild="0",value="0",type="const int",thread-id="1",has_more="0"

Using -var-update --all-values * would now update var11 and var1 from first creation. On each next I will get a further variable to update. In this case it's not a problem off efficiency, because it's just a variable from type int, with no child elements. It will be a problem updating large arrays or dynamic datastructures from the STL for example.

Example

int main() {
    int x = 10;
    x= 20;
    return 0;
}
-break-insert main
-exec-run
-var-create - * "x"
-var-create - * "x"
-exec-next
-var-update --all-values *

Update causes following:

(gdb) 
-var-update --all-values *
^done,changelist=[
{name="var2",value="10",in_scope="true",type_changed="false",has_more="0"},
{name="var1",value="10",in_scope="true",type_changed="false",has_more="0"}
]
@giselher
Copy link
Contributor

At the moment there is a problem with the VariablePool, because it can't remove variables already added to the watch and locals widget at the moment. In any case ricodebug will always get slower with longer debugging sessions.

That said I am not sure if this has anything to do with your problem. But we may be able to solve your problem with a fixed/improved VariablePool. I should actually be working on the VariablePool, but I am currently employed for summer time and don't have much time.

@AHeimberger
Copy link
Author

No problem. What I have seen is, that all var's get stored in a single map. It would be better to safe the var's in a more complex data structure. For example:

# stack level    variables in current stack
# 0             var1                                     <-- int
#                var2                                    <-- std::vector<int>
#                        var2.[0]
#                        var2.[1]
# 1              var3                                    <-- std::vector< std::vector<int> >
#                        var3.[0]
#                        var3.[1]
#                                var3.[1].[0]
#                                var3.[1].[1]
#                var4
#                var5                                   <-- int arr[] = {}
#                                var5.0
#                                var5.1

Why I would choose this Structure. Working with dynamic datastructures from the STL and GDB Pretty Printers has one disatvantage. I do not know if you know from gdb pretty printers. What they do is that they break the complex data structure of an object down to something readable, and usable. Example for an std::vector.

Before:

(gdb) print vec
$2 = {<std::_Vector_base<int, std::allocator<int> >> = {
    _M_impl = {<std::allocator<int>> = {<__gnu_cxx::new_allocator<int>> = {<No data fields>}, <No data fields>}, _M_start = 0x604050, _M_finish = 0x604064, 
      _M_end_of_storage = 0x604070}}, <No data fields>}

I used print for this example code, just remember that the output is complex and not usable for us, because we can't directly evaluate the values of the vector.

Using pretty printers.

-var-create - * vec
^done,name="var1",numchild="0",value="{...}",type="std::vector<int, std::allocator<int> >",thread-id="1",displayhint="array",dynamic="1",has_more="1"
(gdb) 
-var-list-children var1
^done,numchild="5",displayhint="array",children=[child={name="var1.[0]",exp="[0]",numchild="0",type="int",thread-id="1"},child={name="var1.[1]",exp="[1]",numchild="0",type="int",thread-id="1"},child={name="var1.[2]",exp="[2]",numchild="0",type="int",thread-id="1"},child={name="var1.[3]",exp="[3]",numchild="0",type="int",thread-id="1"},child={name="var1.[4]",exp="[4]",numchild="0",type="int",thread-id="1"}],has_more="0"
(gdb) 

There is one problem of using pretty printers. An uninitialized std::vector iterates as long as no segsev occurs. Therefore other debug frontends use a range to list children from a var and to update a var. You may have seen it, if you followed debug trace of Eclipse.

-var-list-children gdName from to
-var-set-update-range gdbName from to
-var-update --all-values gdbName

Using this commands creates a tremendous variable pool. Especially if variable pool is not administrated. For example: Variable Creation of an unitialized std::vector with a range from 0 to 100, created a variable pool with 100 elements and on each gdb next command 100 further elements.

Furthermore it's not possible to call -var-update --all-values * anymore because this would cause an unitialized variable to update the rest of its information. I have to call -var-set-update-range var1 0 100 and afterwards -var-update var1.

At the moment I just fixed the variablepool so I can work with it, but didn't change the data structure. Improvements of this structure would be:

  • you only need to update the variables for a given stack level
  • you can erase all stored variables within a stack level, if you just left the stack level
  • you only need to call -var-update var2. if you do that, you get also informations about var2.[0]

Do you already have a concept?

@giselher
Copy link
Contributor

Sorry for the late reply. After a discussion with Findenig we came to the conclusion that it would be better to just remove all local variables before creating them again. Because by entering a different scope with the same variable name as variable before we can't really determine which variable that is.

int func() {
  int x = 5;
  for (int x = 2; x < 8; i++) {
     ...
  }
}

Pull Request for a simple solution is here: #34

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants