I wrote an infinite loop like the following
for (size_t i = words-1; i >= 0; --i) {
... data[i] ...
}
and it would also access OOB memory. The executable crashes with a coredump. Using gdb with the coredump shows me it crashes when i is a huge number.
However, lldb can successfully run the same executable w/o any crash... Did LLDB 'interpret' the code and fix the issue for me?
No, that would be a horrible thing for a debugger to do! Debuggers in general, and lldb in particular, try hard to run your program as closely as possible to how it runs normally. There are a couple of intrusive jobs the debugger has to do when running "flat out" - e.g. it has to pause when there are shared library loads to read in the new libraries, and the debugger gets first crack at signals sent to the program. So particularly in multi-threaded programs the debugger might perturb timings. But it should never change the instruction flow of code in your program.
If you can make up a test case showing a crash when run in command line but not in lldb, please file a bug with the lldb bug tracker:
https://bugs.llvm.org
and include the example.
Related
I have a multithreaded C program, which consistently generates a segmentation fault at a specific point in the program. When I run it with gdb, no fault is shown. Can you think of any reason why the fault might occur only when not using the debugger? It's pretty annoying not being able to use it to find the problem!
Classic Heisenbug. From Wikipedia:
Time can also be a factor in heisenbugs. Executing a program under control of a debugger can change the execution timing of the program as compared to normal execution. Time-sensitive bugs such as race conditions may not reproduce when the program is slowed down by single-stepping source lines in the debugger. This is particularly true when the behavior involves interaction with an entity not under the control of a debugger, such as when debugging network packet processing between two machines and only one is under debugger control.
The debugger may be changing timing, and hiding a race condition.
On Linux, GDB also disables address space randomization, and your crash may be specific to address space layout. Try (gdb) set disable-randomization off.
Finally, ulimit -c unlimited and post-mortem debugging (already suggested by Robie) may work.
Perhaps when using gdb memory is mapped in a location which your over/under flow doesn't trample on memory that causes a crash. Or it could be a race condition that is no longer getting tripped. Although it sounds unintuitive, you should be happy your program was nice enough to crash on you.
Some suggestions
Try a static code analyzer such as the free
cppcheck
Try a malloc() debugger like
libefence
Try running it through valgrind
By debugging it you are changing the environment that it is running in. It sounds like you are dealing with some sort of race condition, and by debugging it things are scheduled slightly differently so you don't encounter the issue. That, or things are being stored in a slightly different way so it doesn't occur. Are you able to put some debugging output in the code to assist in figuring out the problem? That may have less of an impact and allow you to find your issue.
I have totally had this problem before! It was a race condition, and when I was stepping though the code with a debugger the thread i was in was slow enough to not trigger the race condition. Pretty awful.
If you're using gcc, try using the -Wall option to get all warnings. If you use an IDE like Eclipse, it would do that automatically.
I am debugging an application to fix a segmentation fault that I suspect to be caused by a race condition.
I'd like to put some print statements in the code, but I know for experience that adding calls to printf is not recommended since this could change the behavior of the threads and in some case hide the bug.
Looking at other options, I have seen that with gdb it is possible to use break points to print something and then automatically continue the execution:
break foo
commands
silent
printf "Called foo: x is %d\n",x
cont
end
Is this any better then putting a printf in my code?
I know that gdb has a also Tracepoints but they only work with gdbserver and this is an additional level of complication that I would prefer to avoid at the moment.
Additional information: the application is written in C and it runs on Linux.
Is this any better then putting a printf in my code?
No, it's much worse. Every breakpoint that is hit in GDB triggers the following chain of events:
context switch from running thread to GDB
GDB stops all other threads (assuming default all-stop mode)
GDB evaluates breakpoint commands
GDB resumes all threads (this is itself a complicated multi-step process, which I would not go into here).
This is at least an order of magnitude more expensive and disruptive than a simple printf call, and is very likely to hide whatever race you were trying to debug.
The bottom line is that GDB is in general completely unsuitable for debugging data races.
I second the ThreadSanitizer recommendation by Christopher Ian Stern.
The only problem with this bug is that I am doing the debug on a production machine where I cannot install other SW.
First, ThreadSanitizer instruments your existing program. It has a runtime library, but that could be statically linked into your binary. There is nothing that you need to install on your production machine.
Second, ThreadSanitizer detects data races even when they do not cause visible behavior changes. It may well turn out that you don't need to run on your production machine at all: simply running your tests (you do have tests, right?) on your development machine may prove to be sufficient.
Since you are on Linux, I would recomend ThreadSanitizer. That is using a recent version of gcc or clang and passing -fsanitize=thread to the build. This isn't a printf repacment but should tell you explicitly about any race conditions in your code. Even after you solve this problem if you are working with multithreaded code, you will want to have this tool available. Alternately, or in addition, I have had good results with Valgrind's http://valgrind.org Data Race Detector, but I would start with ThreadSanitizer.
I'm using gdb for debugging
I get a segmentation fault, and then I want to set another break point in the main function and run the program from the beginning
however, although I have finished the current run
and it shows "THe program is not being run"
when I input 'list'
it shows a code snippet of a libarary file
it means currently I'm not in the main function
If I re-run the program, even if I set the break point at the beginning of the main()
it still get segmentation fault, it means the program is running within the library file
so how to return to the main() function?
thanks!
tips: I'm using libpcap.h and I have a '-lpcap' option when compiling
BTW, when I use break 9
to set a breakpoint at 9, gdb runs the program to the 11-th line? what is wrong with this inaccuracy? thanks!
Simply re-issue the run command. You will lose program state, but not breakpoints which seems to match what you need.
"BTW, when I use break 9 to set a breakpoint at 9, gdb runs the program to the 11-th line" - from this, and other information you've provided, it sounds like perhaps the source code is out of sync with gdb's mapping of addresses to source lines. Have you by any chance been editing the program? Have you recompiled it and restarted gdb? Have you seen any warnings similar to "executable is more recent than source"?
If I re-run the program, even if I set the break point at the
beginning of the main() it still get segmentation fault, it means the
program is running within the library file
Actually it means that you either failed to set breakpoint on main function or program execution not reaches main and gets segmentation fault. Try the following steps:
Rebuild program from scratch with debug info (-g gcc option). Reset breakpoint and watch for any warnings from gdb.
If program still crashes with breakpoint set on main look at stack trace (bt command in gdb). It is probably happening before main and you will not see main in stack trace.
I'm developing in C++(g++) with a non-opensource lib.
every time I run the program, the lib will crash (it double-free some memory).
it's ok for my program now. but it's bad for profiling. I use -pg to profiling the program. As a result of the crash, no 'gmon.out' is generated. so I cannot profile it at all.
Question:
How to profiling a 'crashy' program (with gprof).
PS. valgrind is ok to analysis a crashy program.
regards!
There's a function you can call from your program to dump profile data (the same one that's automatically installed as an atexit handler when you link with -pg), but I don't know what it's called offhand.
The easyist thing to do it, just insert an exit(0); call at a suitable point in your program. Alternatively, you can set a breakpoint and use call exit(0) in GDB (except that debugging the program will affect the profile data if you stop it in the middle).
I have a program which produces a fatal error with a testcase, and I can locate the problem by reading the log and the stack trace of the fatal - it turns out that there is a read operation upon a null pointer.
But when I try to attach gdb to it and set a breakpoint around the suspicious code, the null pointer just cannot be observed! The program works smoothly without any error.
This is a single-process, single-thread program, I didn't experience this kind of thing before. Can anyone give me some comments? Thanks.
Appended: I also tried to call pause() syscall before the fatal-trigger code, and expected to make the program sleep before fatal point and then attach the gdb on it on-the-fly, sadly, no fatal occurred.
It's only guesswork without looking at the code, but debuggers sometimes do this:
They initialize certain stuff for you
The timing of the operations is changed
I don't have a quote on GDB, but I do have one on valgrind (granted the two do wildly different things..)
My program crashes normally, but doesn't under Valgrind, or vice versa. What's happening?
When a program runs under Valgrind,
its environment is slightly different
to when it runs natively. For example,
the memory layout is different, and
the way that threads are scheduled is
different.
Same would go for GDB.
Most of the time this doesn't make any
difference, but it can, particularly
if your program is buggy.
So the true problem is likely in your program.
There can be several things happening.. The timing of the application can be changed, so if it's a multi threaded application it is possible that you for example first set the ready flag and then copy the data into the buffer, without debugger attached the other thread might access the buffer before the buffer is filled or some pointer is set.
It's could also be possible that some application has anti-debug functionality. Maybe the piece of code is never touched when running inside a debugger.
One way to analyze it is with a core dump. Which you can create by ulimit -c unlimited then start the application and when the core is dumped you could load it into gdb with gdb ./application ./core You can find a useful write-up here: http://www.ffnn.nl/pages/articles/linux/gdb-gnu-debugger-intro.php
If it is an invalid read on a pointer, then unpredictable behaviour is possible. Since you already know what is causing the fault, you should get rid of it asap. In general, expect the unexpected when dealing with faulty pointer operations.