Thread: How can this possibly make sense?

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

    Question How can this possibly make sense?

    I've had segmentation fault issues for about 2 1/2 hours now and I think I'm getting closer to the problem. Now I'm finding the weirdest thing.

    The following bit of code is at the top of my main function:
    Code:
    int main(int argc, char *argv[]){
    	
    	FILE *fp;
    	if( argc != 2){ // check for argument
    		printf("Error: Please use at least one file argument. Program Exit...\n");
    		exit(0);
    	}
    	
    	if( (fp = fopen(argv[1], "r")) == NULL ){ // try to open file
    		printf("Error: Unable to open file %s. Program Exit...\n", *argv);
    		exit(0);
    	}
    	
    ...etc etc
    When I compile and run with this I get a segmentation fault. However, for some reason when I insert this into the code:

    Code:
    int main(int argc, char *argv[]){
    	
            printf("no segfault -2");
    
    	FILE *fp;
    	if( argc != 2){ // check for argument
    		printf("Error: Please use at least one file argument. Program Exit...\n");
    		exit(0);
    	}
    	
    	if( (fp = fopen(argv[1], "r")) == NULL ){ // try to open file
    		printf("Error: Unable to open file %s. Program Exit...\n", *argv);
    		exit(0);
    	}
    This works perfectly fine! Well, besides other, more fixable errors with the rest of my code...

    HOW??????

  2. #2
    Registered User
    Join Date
    Apr 2011
    Posts
    8
    By the way, when I run gdb without the segmentation checkpoint, I get this:

    Code:
    Program received signal SIGSEGV, Segmentation fault.
    0x0000003c4320cd22 in _dl_fixup () from /lib64/ld-linux-x86-64.so.2

  3. #3
    Officially An Architect brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,396
    Calling a function causes changes to stack memory. These changes are making the difference between crashing and not crashing. It means your bug is somehow stack-related. Most likely, usage of an uninitialized variable somewhere.
    Code:
    //try
    //{
    	if (a) do { f( b); } while(1);
    	else   do { f(!b); } while(1);
    //}

  4. #4
    Registered User
    Join Date
    Apr 2011
    Posts
    8
    Quote Originally Posted by brewbuck View Post
    Calling a function causes changes to stack memory. These changes are making the difference between crashing and not crashing. It means your bug is somehow stack-related. Most likely, usage of an uninitialized variable somewhere.
    Okay, I think I understand that. But wouldn't I get an error or at least a warning if I tried to use an uninitialized variable somewhere?

    EDIT: I just realized that would be if it weren't declared, not if it weren't initialized.
    Last edited by stlbhoy; 04-26-2011 at 08:36 PM.

  5. #5
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by stlbhoy
    But wouldn't I get an error or at least a warning if I tried to use an uninitialized variable somewhere?
    You might, especially if you turn on your compiler's warning levels to a sufficiently high level.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  6. #6
    Registered User
    Join Date
    Apr 2011
    Posts
    8
    Quote Originally Posted by laserlight View Post
    You might, especially if you turn on your compiler's warning levels to a sufficiently high level.
    How would I do this, and would it tell me what variables weren't initialized?

  7. #7
    Banned
    Join Date
    Aug 2010
    Location
    Ontario Canada
    Posts
    9,547
    I had a similar problem with Windows...
    Check your settings for calling conventions... C on x86 uses CDECL as a default... I noticed you are compiling x64 code which may not use the same conventions... On Windows (at least) x64 code uses FASTCALL which treats the stack differently. You will need to check your Linux docs to find out for sure... the required setting will be a compiler setting either in your IDE or command line... For me the fix was a simple project setting... I don't know what the linux fix would be.

    Another possibility is that without including stddio.h the library isn't being loaded until the first call, which happens after your FILE* definition but when you inlcude the printf() statement (which may be used by the runtime library) it initializes the library at the right time... It may be as simple as adding #include <sdtlib.h> and #include <stdio.h> to the top of your files.
    Last edited by CommonTater; 04-26-2011 at 08:48 PM.

  8. #8
    Registered User
    Join Date
    Apr 2011
    Posts
    8
    Quote Originally Posted by CommonTater View Post
    I had a similar problem with Windows...
    Check your settings for calling conventions... C on x86 uses CDECL as a default... I noticed you are compiling x64 code which may not use the same conventions... On Windows (at least) x64 code uses FASTCALL which treats the stack differently. You will need to check your Linux docs to find out for sure... the required setting will be a compiler setting either in your IDE or command line... For me the fix was a simple project setting... I don't know what the linux fix would be.

    Another possibility is that without including dtdio.h the library isn't being loaded until the first call, which happens after your FILE* definition but when you inlcude the printf() statement (which may be used by the runtime library) it initializes the library at the right time... It may be as simple as adding #include <sdtlib.h> and #include <stdio.h> to the top of your files.
    Yeah I got a warning when I first didn't include <stdlib.h> (which I assume you meant by "dtdio.h" and "<sdtlib.h>" unless these are libraries I don't know about) but it's included now and the same thing is happening. I'm currently running it on my school's servers so I can't change any of that.

    As an update, and to explain a little bit about what I'm trying to do:

    I'm terrible with pointers (and C in general, but that's what this project has to be done in), so I've been trying to use character arrays. My program is meant to take a "Tuple" file, and here is test1.tup that I've been reading in:

    Code:
    (ASSIGN,BP,0)
    (ASSIGN,SP,0)
    (ASSIGN,FP,SP)
    (ADDI,SP,FP,2)
    (ASSIGN,M[FP],3)
    (JUMP,2)
    (LABEL,0)
    (ADDI,SP,SP,1)
    (ADDI,SP,SP,1)
    (ASSIGN,R0,M[FP+4])
    (READI,M[FP+4])
    (ASSIGN,R1,M[FP+5])
    (ASSIGN,R2,4)
    (ASSIGN,M[FP+5],R2)
    (ASSIGN,M[SP],4)
    (ADDI,SP,SP,1)
    (ASSIGN,M[SP],FP)
    (ADDI,SP,SP,1)
    (SUBI,M[SP],SP,2)
    (ADDI,SP,SP,1)
    (ASSIGN,R3,M[FP+4])
    (ASSIGN,R4,R3)
    (ASSIGN,M[SP],R4)
    (ADDI,SP,SP,1)
    (ASSIGN,R5,M[FP+5])
    (ASSIGN,R6,R5)
    (ASSIGN,M[SP],R6)
    (ADDI,SP,SP,1)
    (SUBI,FP,SP,5)
    (JUMP,1)
    (LABEL,4)
    (ASSIGN,SP,M[FP+2])
    (ASSIGN,FP,M[FP+1])
    (JUMP,M[FP])
    (LABEL,1)
    (ASSIGN,R7,M[FP+3])
    (ASSIGN,R8,R7)
    (ASSIGN,R9,M[FP+4])
    (ASSIGN,R10,R9)
    (ADDI,R11,R8,R10)
    (WRITEI,R11)
    (JUMP,M[FP])
    (LABEL,2)
    (ADDI,SP,SP,1)
    (ADDI,SP,SP,1)
    (ADDI,SP,SP,1)
    (ADDI,SP,SP,1)
    (ADDI,SP,SP,1)
    (ASSIGN,R12,M[FP+5])
    (READI,M[FP+5])
    (ASSIGN,R13,M[FP+5])
    (ASSIGN,R14,R13)
    (WRITEI,R14)
    (ASSIGN,R15,M[FP+6])
    (ASSIGN,R16,R15)
    (WRITEI,R16)
    (ASSIGN,M[SP],5)
    (ADDI,SP,SP,1)
    (ASSIGN,M[SP],FP)
    (ADDI,SP,SP,1)
    (SUBI,M[SP],SP,2)
    (ADDI,SP,SP,1)
    (ASSIGN,R17,M[FP+5])
    (ASSIGN,R18,R17)
    (ASSIGN,M[SP],R18)
    (ADDI,SP,SP,1)
    (SUBI,FP,SP,4)
    (JUMP,0)
    (LABEL,5)
    (ASSIGN,SP,M[FP+2])
    (ASSIGN,FP,M[FP+1])
    (JUMP,M[FP])
    (LABEL,3)
    The program should then make an array of basic blocks from the above code (basic block meaning anything that starts with LABEL and may or may not end with JUMP). Therefore I'm using an array of these structures:

    This is types.c
    Code:
    #define MAXDATA 1000
    
    struct BB{
    	int BBid;
    	char code[MAXDATA];
    };
    Where the "char code[MAXDATA]" is just the concatenation of all the lines of code between a LABEL and JUMP (inclusive) or between a LABEL and another LABEL.

    The file with my main function currently looks like this:

    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <ctype.h>
    #include "buffer.c"
    #include "types.c"
    
    #define MAXLINE 50
    #define MAXBB 20
    
    int main(int argc, char *argv[]){
    	
    	//printf("no segfault -2");
    	
    	FILE *fp;
    	if( argc != 2){ // check for argument
    		printf("Error: Please use at least one file argument. Program Exit...\n");
    		exit(0);
    	}
    	
    	if( (fp = fopen(argv[1], "r")) == NULL ){ // try to open file
    		printf("Error: Unable to open file %s. Program Exit...\n", *argv);
    		exit(0);
    	}
    	
    	struct BB * BBarray[MAXBB]; // initialize array of basic blocks
    	int currBBid = 0; // begin with basic block 0
    	int codePt = 0;
    	
    	// initialize EVERYTHING!!!
    	int i, j;
    	for (i = 0; i < MAXBB; i++){
    		for (j = 0; j < MAXDATA; j++){
    			BBarray[i]->code[j] = '\0';
    		}
    		BBarray[i]->BBid = -1;
    	}
    	
    	char line[MAXLINE];
    	int linePt;
    	
    	int count;
    	int length; // initialize variables for getting the line
    	
    	char flag = 'N';
    	char c;
    	
    	while( (c=getch(fp)) != EOF ){
    	
    			for(count = 0; count < MAXLINE; count++){
    				line[count] = '\0';
    			}
    	
    			// get line
    			line[0] = c;
    			for(count = 1; (count < MAXLINE) && (((c=getch(fp)) != '\n') && (c != '\r')); count++){
    				
    				line[count] = c;
    				
    			}
    			ungetch(c);
    			line[count++] = '\n';
    			line[count] = '\0';
    			length = strlen(line);
    						
    			/*
    				put line in basic block code
    				if JUMP, put line in code and increment to next BB
    				if LABEL, increment (if fall through to label, not jump to label) then put line in code (unless already incremented because of jump shown by flag)
    				else put line in code
    			*/
    			if(strncmp(line, "(JUMP", 5) == 0){
    				
    				BBarray[currBBid]->BBid = currBBid; // redundant, oh well
    				
    				linePt = 0;
    				while(linePt < length){
    					BBarray[currBBid]->code[codePt++] = line[linePt++];
    				}
    
    				BBarray[currBBid]->code[codePt++] = '\n';
    				
    				currBBid++; // new basic block
    				codePt = 0; // initialize new basic block
    				
    				flag = 'J'; // flag to show currBBid has already been incremented because a JUMP has been reached
    				
    			}else if(strncmp(line, "(LABEL", 5) == 0){
    				
    				if(flag != 'J'){ // fall through to label, new basic block
    					currBBid++;
    					codePt = 0;
    				}
    				
    				BBarray[currBBid]->BBid = currBBid;
    				
    				linePt = 0;
    				while(linePt < length){
    					BBarray[currBBid]->code[codePt++] = line[linePt++];
    				}
    				
    				BBarray[currBBid]->code[codePt++] = '\n';
    				
    				flag = 'N'; // no flag after this change
    			
    			}else{
    				
    				BBarray[currBBid]->BBid = currBBid;
    				
    				linePt = 0;
    				while(linePt < length){
    					BBarray[currBBid]->code[codePt++] = line[linePt++];
    				}
    			
    			}
    				
    	}
    	
    	printf("BBid\t\tCode");
    	for(count=0; count <= currBBid; count++){
    		printf("%d\t\t%s", BBarray[count]->BBid, BBarray[count]->code);
    	}
    	
    	return 0;
    }
    "buffer.c" just contains getch and ungetch

    Any help would be greatly appreciated!

  9. #9
    Banned
    Join Date
    Aug 2010
    Location
    Ontario Canada
    Posts
    9,547
    Code:
    #include "buffer.c"
    #include "types.c"
    AHA! Including C files is mucho bad ju-ju ... You need to make header files to protoype the functions and relate the variables etc. in those files to your other souce files. I'm betting the segfault is actually in one of those files or perhaps from the way they "fit" (or more accurately "don't fit") into the correct program structure of your main program.

  10. #10
    Registered User
    Join Date
    Apr 2011
    Posts
    8
    Quote Originally Posted by CommonTater View Post
    Code:
    #include "buffer.c"
    #include "types.c"
    AHA! Including C files is mucho bad ju-ju ... You need to make header files to protoype the functions and relate the variables etc. in those files to your other souce files. I'm betting the segfault is actually in one of those files or perhaps from the way they "fit" (or more accurately "don't fit") into the correct program structure of your main program.
    Thanks for the tip, I just copied and pasted the code from those files (it wasn't much anyway) to the main file and it actually got rid of the unexplainable segfault that gdb was giving me. However I still get one when I run it and gdb says it has to do with these lines, which I wrote to initialize all the memory used by my structure as was suggested by brewbuck

    Calling a function causes changes to stack memory. These changes are making the difference between crashing and not crashing. It means your bug is somehow stack-related. Most likely, usage of an uninitialized variable somewhere.
    These are the lines gdb tells me have a segfault:

    Code:
    	// initialize EVERYTHING!!!
    	int i, j;
    	for (i = 0; i < MAXBB; i++){
    		for (j = 0; j < MAXDATA; j++){
    			BBarray[i]->code[j] = '\0';
    		}
    		BBarray[i]->BBid = -1;
    	}
    I've gone through it but I can't figure out why this would be a segerror...
    This is the structure again:

    Code:
    struct BB{
    	int BBid;
    	char code[1000];
    };

    EDIT:
    Actually it is this line specifically it says is the problem:
    Code:
    BBarray[i]->code[j] = '\0';
    Last edited by stlbhoy; 04-26-2011 at 09:31 PM.

  11. #11
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    Code:
    	struct BB * BBarray[MAXBB]; // initialize array of basic blocks
    	int currBBid = 0; // begin with basic block 0
    	int codePt = 0;
    	
    	// initialize EVERYTHING!!!
    	int i, j;
    	for (i = 0; i < MAXBB; i++){
    		for (j = 0; j < MAXDATA; j++){
    			BBarray[i]->code[j] = '\0';
    		}
    		BBarray[i]->BBid = -1;
    	}
    So what is BBarray[i] pointing at when you get around to dereferencing the pointer?

    Perhaps you should consider writing a smaller case which uses fixed sized arrays before messing with pointers.
    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. Does this make any sense?
    By xniinja in forum C Programming
    Replies: 20
    Last Post: 08-05-2010, 11:07 AM
  2. does it make any sense
    By ExDHaos in forum C++ Programming
    Replies: 0
    Last Post: 05-23-2009, 08:06 AM
  3. does this make sense ??
    By agarwaga in forum C++ Programming
    Replies: 14
    Last Post: 03-08-2006, 07:10 PM
  4. Can anyone help me make sense from this?
    By correlcj in forum C Programming
    Replies: 1
    Last Post: 07-23-2002, 07:31 PM
  5. anyone make any sense of this
    By Unregistered in forum C++ Programming
    Replies: 6
    Last Post: 10-03-2001, 10:29 PM