Thread: sscanf segmentation fault

  1. #1
    Registered User
    Join Date
    Mar 2010
    Posts
    40

    sscanf segmentation fault

    Hi all,

    I'm having a segmentation fault that I don't understand. The program compiles and runs just fine on any number of different Macs I've tried it on (OSX 10.5, and 10.6), but when I tried moving it to a linux cluster, I'm getting a segmentation error right here.

    Code:
            float fprime= 0;
            char * pch;
            .... intervening code ....
    
            while (fgets(buf, sizeof(buf), fp)!=NULL)
            {
                    pch = strtok(buf, ",");
                    while (pch != NULL)
                    {
                            printf("before sscanf\n");
                            sscanf(pch, "%f", &fprime);
                            printf("after sscanf\n");
                            f[k]= fprime;
                            printf("is it here\n");
                            pch= strtok(NULL, ",");
                            printf("checking\n");
                            k++;
                    }
            }
    You can see from the code where I've put in printf statements to try and figure out exactly when the segmentation fault is occuring, and it happens right at the sscanf. strtok returns a pointer of type char to the last token found in the string, so I don't think it's because there's a problem with pch, but maybe I'm wrong?

    I'd appreciate any help and/or suggestions.

    Brad

  2. #2
    Registered User
    Join Date
    Dec 2007
    Posts
    2,675
    You know the best way to figure out not only WHERE a seg fault is occurring, but WHY? Compile the code in debug mode and run it in a debugger. The debugger will stop when -- and where in the code -- the fault occurs and you can evaluate the state of the variables to figure out what's going wrong.

  3. #3
    Registered User
    Join Date
    Mar 2010
    Posts
    40
    I'm unfamiliar with gdb, but I'm trying it anyway. Usually I just use the built in debugger in xcode, which is really helpful, but I'm unfamiliar with gdb.

  4. #4
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,661
    What is buf - an array, or just a pointer?

    What is f - an array or a pointer?

    What limits k to be in range of the array f ?
    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.

  5. #5
    Registered User
    Join Date
    Mar 2010
    Posts
    40
    Here is the code for the whole routine
    Code:
    float *f_retrieve_vector(char filename[], int n)
    // in most cases n= 1000;
    {
    	FILE* fp;
    	
    	int k= 0;
    	float *f;
    	float fprime= 0;
    
    	char * pch;
    	
    	
    	char buf[1024];
    	if ((fp= fopen(filename, "rt"))==NULL) 
    	{
    		printf("could not open %s in f_retrieve_vector() in structures.c\nexiting to system\n", filename);
    		exit(-1);
    	}
    	
    	f= calloc(n, sizeof(float));
    	
    	if (f== NULL)
    	{
    		printf("could not allocate memory for vector f in f_retrieve_vector()\nexiting..\n");
    		exit(-1);
    		
    	}
    	k= 0;
    	// read a line into the buffer
    	while (fgets(buf, sizeof(buf), fp)!=NULL)
    	{
    		pch = strtok(buf, ",");
    		while (pch != NULL)
    		{
    			sscanf(pch, "%g", &fprime);
                            f[k]= fprime;
    			pch= strtok(NULL, ",");
    			k++;
    		}
    	}
    	
    	if (k!=n) 
    		printf("fewer than %d (read %d) entries read in from file %s in f_retrieve_vector()\nremaining values will be ZEROED\n", n, k, filename);
    	
    	fclose(fp);
    	return f;
    	
    }
    f is a pointer to a chunk of memory allocated by calloc of type float.

    The while loop scans over the input buffer, which has n items in a comma delimited list. k is just incremented everytime an item is read from the list, and k <= n.

    The problem though doesn't exist with the assignment of f[k]= frpime, it exists with the sscanf, because I get exactly the same problem if I remove the f[k]= fprime line.

  6. #6
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,661
    Starting from this simple test,
    Code:
    int main ( ) {
      float *f = f_retrieve_vector("data.txt", 1000);
      free(f);
      return 0;
    }
    does it crash?

    If not, then you have a cause and effect situation going on. What you're seeing is the side effect of a bug in one part of the program causing an effect in another part.

    Endless staring at the place where it shows up won't help much.

    But I'd be happier if you had some "&& k < n" tests in your loops as well, to make sure there is no overrun.
    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.

  7. #7
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,661
    Starting from this simple test,
    Code:
    int main ( ) {
      float *f = f_retrieve_vector("data.txt", 1000);
      free(f);
      return 0;
    }
    does it crash?

    If not, then you have a cause and effect situation going on. What you're seeing is the side effect of a bug in one part of the program causing an effect in another part.

    Endless staring at the place where it shows up won't help much.

    But I'd be happier if you had some "&& k < n" tests in your loops as well, to make sure there is no overrun.
    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.

  8. #8
    Registered User
    Join Date
    Mar 2010
    Posts
    40
    Quote Originally Posted by Salem View Post
    If not, then you have a cause and effect situation going on. What you're seeing is the side effect of a bug in one part of the program causing an effect in another part.

    Endless staring at the place where it shows up won't help much.

    But I'd be happier if you had some "&& k < n" tests in your loops as well, to make sure there is no overrun.
    Yes, it did crash at exactly the same place. I will definitely put some && k < n tests in there, that's a very good suggestion.

    I'm confused why a cause and effect situation would be implied if it didn't crash. In the situation you suggested, there is only a single routine being executed, so if it does crash, it must be related to something in that specific function, doesn't it?

  9. #9
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,661
    Yes, the more you can narrow it down to a complete example that shows the problem, the better.

    Particularly when you start dealing with memory allocation, then any mistake with say buffer overrun, or mistakes in allocation/free (say freeing twice, or use after free) can (and often do) result in a problem in some other routine later on when it tries to use dynamic memory.

    But if all you've posted "is it" (plus the simple main to test it), then it does look pretty weird.

    Which OS/Compiler are you using?
    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.

  10. #10
    Registered User
    Join Date
    Mar 2010
    Posts
    40
    Quote Originally Posted by Salem View Post
    Yes, the more you can narrow it down to a complete example that shows the problem, the better.

    Particularly when you start dealing with memory allocation, then any mistake with say buffer overrun, or mistakes in allocation/free (say freeing twice, or use after free) can (and often do) result in a problem in some other routine later on when it tries to use dynamic memory.

    But if all you've posted "is it" (plus the simple main to test it), then it does look pretty weird.

    Which OS/Compiler are you using?
    I completely agree with you regarding debugging. Normally when I write new routines I debug them exactly that way- one call at a time, directly from main to make sure they're working, for exactly the reasons you outlined.

    uname-a reported the follow

    Linux infoserv 2.6.31.13-server-1mnb #1 SMP Tue Apr 27 21:14:30 EDT 2010 x86_64 AMD Opteron(tm) Processor 250 GNU/Linux

    I've tried compiling with cc and gcc, without any command line options except for -lm with the same result. Maybe I should try it with -O0 to turn off any default optimizations.

    I also just noticed this error file in the directory, when I tried to submit the job to the queue (I'm running this on a small linux cluster).

    ./a.out: /lib64/tls/libc.so.6: version `GLIBC_2.7' not found (required by ./a.out)

  11. #11
    Registered User
    Join Date
    Mar 2010
    Posts
    40
    It seems like the problem actually might be replaced to pch, rather than to sscanf. I modified the following line

    Code:
    pch = strtok(buf, ","); 
    printf("after strtok\n");
    printf("pch contains %s\n", pch);
    And now it prints out "after strtok", but i fails on the printf statement- again, a segmentation fault- that suggests to me that strtok is returning something funny.

  12. #12
    ... kermit's Avatar
    Join Date
    Jan 2003
    Posts
    1,534
    Not knowing how much you know about gdb, or have tried, have a look at this example. It might help you to understand how you can narrow down what is causing the segfault. The only thing that I would change is this:

    Code:
    gcc -g seg.c -o seg
    Using dwks example, I would change the switches to the following:

    Code:
    gcc -Wall -Wextra -ggdb3 -o progname progname.c
    -Wall is a little misleading, as it does not not really give "all" warnings. -Wextra adds a few more warnings that -Wall does not get (-Wextra used to be just -W). -ggdb3 produces debugging info particular for use by gdb, and in its most verbose form.

    Edit: I forgot to mention that you will want to turn off optimisations (for debugging purposes). You would use the -O0 switch:

    Code:
    gcc -Wall -Wextra -ggdb3 -O0 -o progname progname.c
    Last edited by kermit; 09-28-2010 at 03:40 PM.

  13. #13
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,661
    > ./a.out: /lib64/tls/libc.so.6: version `GLIBC_2.7' not found (required by ./a.out)
    This is worrying.
    What ARE you linking against for your standard C library?

    Assuming you are dynamically linking with some version of the library, it would seem to be the incorrect version.
    If you have a mis-aligned entry table for example, you might not even be calling strtok(). Some functions like printf may still match up, leading you to think early success is a good thing.
    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.

  14. #14
    Registered User
    Join Date
    Mar 2010
    Posts
    40
    So I solved that problem by doing two things- linking against c99 library (which got rid of the GLIBC_2.7 not found error) and by swapping out the sscanf statement for an atof. I considered re-writing the whole function to use a for loop (since I do specify the number of entries I want read in) and/or using strtof instead of strtok and sscanf, but this was easier and it works.

    Now I've got another problem, but I am going to start a new thread about it, because it's not an sscanf segmentation fault, it's this:

    *** glibc detected *** double free or corruption (!prev)

    Which occurs during execution, and there's no way that a double free occurred. Anyway, new thread.

  15. #15
    Registered User
    Join Date
    Mar 2010
    Posts
    40
    The glibc error was due to a really severe buffer overrun. Now I've solved the problem in the interim by making my buffers many times larger than I expect will be needed (40960 bytes), but I think I may just decide to go back and implement some boundary detection.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Odd Segmentation Fault
    By JohnnyAppleseed in forum C Programming
    Replies: 7
    Last Post: 08-24-2010, 12:01 PM
  2. Segmentation fault
    By bennyandthejets in forum C++ Programming
    Replies: 7
    Last Post: 09-07-2005, 05:04 PM
  3. Segmentation fault
    By NoUse in forum C Programming
    Replies: 4
    Last Post: 03-26-2005, 03:29 PM
  4. Locating A Segmentation Fault
    By Stack Overflow in forum C Programming
    Replies: 12
    Last Post: 12-14-2004, 01:33 PM
  5. Segmentation fault...
    By alvifarooq in forum C++ Programming
    Replies: 14
    Last Post: 09-26-2004, 12:53 PM