Very funny, gdb. Ve-ery funny
yosefk.com
yosefk.com
Years ago, I used to be the C++ maintainer for GDB. By the time I left, things like doing this on a live process worked about 90% of the time (up from 0%). It turns out what he's trying to do is harder than one would think, but it should actually work.
Part of the reason it doesn't really work all that often on coredumps is because you often need access to vtables, thunk functions (which you could theoretically execute without a live process in most ABI's, but it doesn't know this). Depending on the class, there may also be runonce constructors (for static data and associated guard variables), etc.
http://www.yolinux.com/TUTORIALS/src/dbinit_stl_views-1.03.t...
Here they have some functions that inspect vector by means of _M_impl and friends, why can't gdb do this?
As for std::vector, GDB can and does do this now, through python based pretty printers.
That gdb script is completely unnecessary for this now. Most distros ship with gdb + appropriate pretty printers pre-installed, but they are also available in the libstdc++ repo.
See https://sourceware.org/gdb/wiki/STLSupport
If you use this, print on a vector just works, no extra commands or anything needed.
Code:
#include <vector>
using namespace std;
int main()
{
vector<int> beans;
beans.resize(5);
beans[3] = 4;
beans [4] = 66;
}
Build command: g++ -g 156.cpp
gdb debugging session: GNU gdb (Ubuntu/Linaro 7.4-2012.04-0ubuntu2.1) 7.4-2012.04
SKIPPED OUT WARRANT INFO HERE
Reading symbols from /badcode/a.out...done.
(gdb) break 156.cpp:10
Breakpoint 1 at 0x4008e6: file 156.cpp, line 10.
(gdb) run
Starting program: /badcode/a.out
Breakpoint 1, main () at 156.cpp:10
10 beans [4] = 66;
(gdb) print beans[3]
$2 = (int &) @0x60401c: 4
(gdb) print beans[4]
$3 = (int &) @0x604020: 0It's possible the parent meant "why can't GDB make v[0] do an inspection directly on the structure". The simple answer is: "It can't possibly know what the function call does". So you'd have to teach it, specifically, that std::vector is special, or provide a mechanism to override the native calls with python scripting (IE be able to say "here is a replacement for T &operator[int] on std::vector that is in python, and works without a live process").
GDB actually does real overload resolution (it has to, otherwise in some 'simple' cases, it'd have to ask you 100 questions about what functions you are trying to call), making that strategy more complicated.
If your only mechanism for reproduction is a core dump, yes this is a pain in the ass. But this shouldn't be true, even remotely, since you always have things like gdbserver/etc.
Now I understand it's a different problem, but sometimes I think you sw guys live in the dark ages.
Actually, there are a few debuggers that can step backwards, but its not mainstream and the memory overhead is apparently enormous.
I think that the closest analogue to a waveform view in software may actually be printf()/log-based debugging, in the sense that there's a sort of temporal vs. spatial tradeoff going on: with waveform views or logs (temporal view), you see only the signals/data you've chosen to post, but you can easily see sequences through time, which is useful for many sorts of systems. With a traditional debugger (spatial), you can poke around in memory arbitrarily at a breakpoint, but it's more difficult to see time (you have to explicitly step forward, and usually can't back up). Both are useful.
Well those using gdb are, yes. (ducks)
Anyone got any pointers on this?
This wikipedia article mentions few approaches: http://en.wikipedia.org/wiki/Application_checkpointing
This page has many more projects, though most are probably dead by now: http://checkpointing.org/
Both are incomplete, googling "linux checkpointing" returns things not mentioned in either, like https://ckpt.wiki.kernel.org/index.php/Main_Page
"DMTCP (Distributed MultiThreaded Checkpointing) is a tool to transparently checkpoint the state of multiple simultaneous applications, including multi-threaded and distributed applications. It operates directly on the user binary executable, without any Linux kernel modules or other kernel modifications."
Huh? vector::at() is boundary-checked. So you can choose whether you want to pay for boundary-checking or not.
I kid...mostly.
http://gcc.gnu.org/onlinedocs/libstdc++/manual/bk01pt12ch30s...
comment reproduced here without further context
I certainly hope it was intentional. :D
GDB can never be as nice as a language specific, graphical point and click debuggers that some programming environments have which are built in conjunction with the compiler/interpreter for that language.
And the problem is not only GDB, it's the whole infrastructure that is involved, binary formats, debug symbols and protocols, binutils, etc. It is easy to point the finger at GDB but there's only so much that GDB can do in the environment(s) that it works in.
There's plenty of room for improvement but it's not only GDB that would require work, it's the entire software ecosystem.
Debugging std::vector isn't too bad. You can dig in to the...
Whenever a programmer says "[X] isn't too bad" this is the possible signature of an opportunity.
I really doubt LLDB can discover what code operators execute if the compiler does not include it at the binary.
(lldb) print v[0]
error: call to a function 'std::__1::vector<int, std::__1::allocator<int> >::operator[](unsigned long)' ('_ZNSt3__16vectorIiNS_9allocatorIiEEEixEm') that is not present in the target
error: The expression could not be prepared to run in the target
(lldb) version
lldb-300.2.53That's such a dirty lie. Example: GDB has reverse step. That's such a amazing debugging feature that VisualStudio users often refuse to believe that it's real, when you try to describe it to them.
In most languages compilers are allowed to do whatever they want as long as the semantic outcome stays the same.
Isn't that how they used to build emacs, there was some multistage bootstrapping procedure that culminated in undump'ing a thing that got turned into a binary.
To elaborate: the programs would do all of their initialization and loading of things that would be used in any run, then dump themselves. The result of undump was an executable that had already done all of its boilerplate loading and was ready to process its arguments and inputs. It was bigger, since it had a bunch of heap stored, but it was better than hammering away on your CPU at 1 million instructions per second.