Thread: catch segmentation fault with gdb

  1. #1
    Registered User
    Join Date
    Apr 2011
    Posts
    74

    catch segmentation fault with gdb

    Hi,

    I am working on a distributed application in C. My program gives segmentation fault and aborts execution.

    But, when I try to run it through gdb, it keeps on running although without giving a useful output.

    I realize that I do not put much information in my query. But, what general causes could generate this behaviour.

    I am interested to find the cause of segmentation fault.

    thanks,

  2. #2
    SAMARAS std10093's Avatar
    Join Date
    Jan 2011
    Location
    Nice, France
    Posts
    2,694
    Posting the code that is prone to seg can help
    Code - functions and small libraries I use


    It’s 2014 and I still use printf() for debugging.


    "Programs must be written for people to read, and only incidentally for machines to execute. " —Harold Abelson

  3. #3
    Registered User
    Join Date
    Apr 2011
    Posts
    74
    the problem is, it is rather big code, and it is not clear which part may have the problem, but I will paste the part from which I have last output
    Code:
    
    void ready_queue_print_msg_queue(unsigned char queue_no) {
    
    	READY_QUEUE_IDX **idx_temp;
    
    	idx_temp = &(ready_queues[queue_no].list_base);
    	PRINTF("\n Start=");
    	while (1) {
    		if (*idx_temp == NULL){
    			PRINTF(" NULL\n");
    			break;
    		}
    	
    		PRINTF(" %d ->", MDB_Get_runtime_id((*idx_temp)->message_DB_pointer) & 0xff);
    		
    		/* Increment */
    		idx_temp = &((*idx_temp)->link);
    	}
    	return ;
    }
    This function basically prints out items of a linked list. It prints the items fine. But, after this function is finished, I do not see any further outputs from the program.

    thanks

  4. #4
    Registered User
    Join Date
    Nov 2010
    Location
    Long Beach, CA
    Posts
    5,909
    Well, seg faults are caused by your program trying to access memory it doesn't have access to. That's the way the operating system deals with such errors.

    The C programming language, on the other hand, simply states that such errors result in undefined behavior. Undefined means anything or nothing can happen. It may not even compile, it may crash, or fail silently, it may give incorrect results or even appear to work. One possible scenario is that it crashes when you run it normally, but appears to work (or at least doesn't crash) when run in the debugger.

    You might try putting in some fprintf statements to print to stderr, for debugging. Note, that is fprintf, and stderr. stderr is not buffered, so output shows up immediately. Trying to use stdout for debugging can be problematic because calling printf does not guarantee that the output will show up immediately on the screen. That makes it hard to pinpoint where the problem is, because your output doesn't accurately reflect where the program crashed. Thus you use stderr to debug since it shows up right away.

  5. #5
    Registered User
    Join Date
    Apr 2011
    Posts
    74
    thanks anduril462, I will try your suggestions.

  6. #6
    SAMARAS std10093's Avatar
    Join Date
    Jan 2011
    Location
    Nice, France
    Posts
    2,694
    You have a list. Probably the insertion function is not ok. I would check that function again.
    Code - functions and small libraries I use


    It’s 2014 and I still use printf() for debugging.


    "Programs must be written for people to read, and only incidentally for machines to execute. " —Harold Abelson

  7. #7
    Registered User
    Join Date
    Nov 2010
    Location
    Long Beach, CA
    Posts
    5,909
    Quote Originally Posted by zahid990170 View Post
    the problem is, it is rather big code, and it is not clear which part may have the problem, but I will paste the part from which I have last output
    How big is "rather big"? 500 lines, e.g., is not that big, but I probably wouldn't post 5000 lines. Ideally, you would post the minimum amount of code that compiles and exhibits the problem, so we can check it ourselves. Note, if your program is thousands of lines long, it should be broken up into modules. Extract the list code to it's own .c file and test that independently of the rest of the code. Do likewise with other logically separate aspects of your code. That allows you to test individual modules before integrating them into the final product. It also makes it easier to narrow down problems to one specific area.

    This function basically prints out items of a linked list. It prints the items fine. But, after this function is finished, I do not see any further outputs from the program.
    There is no need for idx_temp to be a double pointer in that function, nor do you need an infinite (while(1)) loop with a break. Just do:
    Code:
    READY_QUEUE_IDX *idx_temp;
    
    idx_temp = ready_queues[queue_no].list_base;
    print start
    while (idx_temp != NULL) {
        print element
        idx_temp = idx_temp->link;
    }
    print NULL
    EDIT: Also, just because that is the last sign of "life" you see from your program, does not mean that is where the crash is. That is why I mentioned printing to stderr instead of stdout. If your list prints correctly, there is a very good chance it is built correctly. If it weren't, your print function would probably show incorrect data.
    Last edited by anduril462; 01-23-2013 at 12:51 PM.

  8. #8
    Registered User ledow's Avatar
    Join Date
    Dec 2011
    Posts
    435
    Running in a debugger changes the way a program runs. Sometimes it causes problems like this, where you see a bug outside the debugger but can't reproduce it inside.

    The usual ways to find such things include:

    1) Looking at your code
    2) Not ignoring compiler warnings and errors
    3) Inserting statements all over it, such as a debug build would do, so that you know what functions it entered and when and, thus, get a clue as to where the segfault lies.
    4) Running the code through valgrind and static analysers and fixing the problems it reports.

    Personally, I have a very simple macro that I insert into the top and bottom of every function (after running into "undebuggerable" errors twice in the same project) - when switched on it turns into a printf statement with the function name, when switched off it turns into whitespace. When I hit a problem, I turn on the macro and - thrown out to txt files and stdout and stderr - I get a list of what functions were executed in what order and how long the program spent in there (and if the crash is VERY early, I switch it to become a "MsgBox" statement on Windows so that I can just run the program, and click OK on every function name and note for myself exactly what function it crashes in).

    Because it's a macro, it doesn't need any debugger at all (and, in fact, I use it on remote devices that don't even have a debugger installed to trace platform-specific problems), I can get it to print out whatever I want (I also use it as a primitive profiler too, by just printing the clock time as well as the function name), and it's easily turn-off-and-on-able. And because it can be something as simple as a printf, it doesn't affect the program enough to cause bugs to "shift", like a full debugger does.

    But, honestly, most of my problems I find by just running in a debugger and single-stepping. Just running a debugger is like just "firing a gun" to see what's wrong with the gun - you're unlikely to see the point where a problem occurs. But if you single-step, or function-step, inside the debugger, while looking at the variables passed to the functions it'll take a while on a large program (P.S. I consider "large" to be 10,000 lines or more) but you're likely to find a lot of problems. And valgrind and compiler warnings will find things wrong with your program that you wouldn't have spotted in a million years.

    Please tell me that your program compiles using -Wall (or equivalent - to see all warnings and errors) and that you have none that you haven't explicitly looked into and determined can't be fixed at all. A clean, zero-warnings compile is the FIRST step to debugging a program.



    Oh, just as an side-note: "*idx_temp == NULL" - probably best to check that idx_temp itself isn't NULL before you try to dereference it with *.
    Last edited by ledow; 01-25-2013 at 03:34 AM.

    - Compiler warnings are like "Bridge Out Ahead" warnings. DON'T just ignore them.
    - A compiler error is something SO stupid that the compiler genuinely can't carry on with its job. A compiler warning is the compiler saying "Well, that's bloody stupid but if you WANT to ignore me..." and carrying on.
    - The best debugging tool in the world is a bunch of printf()'s for everything important around the bits you think might be wrong.

  9. #9
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    Or consider using a core file.
    Code:
    #include <stdio.h>
    #include <stdlib.h>
    
    void bar ( ) {
      if ( rand() % 10 == 0 ) {
        int *c = NULL;
        *c = 0;
      }
    }
    
    void foo ( ) {
      if ( rand() % 10 ) {
        bar();
      }
    }
    
    int main ( ) {
      while ( 1 ) {
        foo();
      }
      return 0;
    }
    
    
    
    $ gcc -W -Wall -g foo.c
    $ ulimit -c unlimited
    $ ./a.out 
    Segmentation fault (core dumped)
    $ gdb a.out core
    GNU gdb (Ubuntu/Linaro 7.3-0ubuntu2) 7.3-2011.08
    Copyright (C) 2011 Free Software Foundation, Inc.
    License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
    This is free software: you are free to change and redistribute it.
    There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
    and "show warranty" for details.
    This GDB was configured as "x86_64-linux-gnu".
    For bug reporting instructions, please see:
    <http://bugs.launchpad.net/gdb-linaro/>...
    Reading symbols from /home/sc/Documents/a.out...done.
    [New LWP 4073]
    
    warning: Can't read pathname for load map: Input/output error.
    Core was generated by `./a.out'.
    Program terminated with signal 11, Segmentation fault.
    #0  0x0000000000400533 in bar () at foo.c:7
    7	    *c = 0;
    (gdb) where
    #0  0x0000000000400533 in bar () at foo.c:7
    #1  0x0000000000400574 in foo () at foo.c:13
    #2  0x0000000000400584 in main () at foo.c:19
    (gdb) print c
    $1 = (int *) 0x0
    (gdb)
    It's not as good as running in the debugger and single-stepping, but you do have a chance to have a good look around if you compile with -g
    At least it'll give you a place to look.

    In bash, type 'ulimit -a' to see what your process limits are.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Segmentation fault 11
    By Chanakya in forum C++ Programming
    Replies: 7
    Last Post: 06-30-2012, 03:01 PM
  2. Segmentation Fault Please Help
    By cdineshan in forum C Programming
    Replies: 3
    Last Post: 11-08-2011, 07:11 PM
  3. segmentation fault
    By bazzano in forum C Programming
    Replies: 9
    Last Post: 04-10-2006, 10:25 AM
  4. Segmentation Fault Again
    By mrbump2004 in forum C Programming
    Replies: 6
    Last Post: 12-05-2004, 02:31 PM
  5. segmentation fault and memory fault
    By Unregistered in forum C Programming
    Replies: 12
    Last Post: 04-02-2002, 11:09 PM