I'm making a program to split a file into lexemes but I'm unfamiliar with C and I'm getting a weird segmentation error. The following code runs and prints:
1
2
Segmentation Fault: 11
I've looked up other causes to segmentation faults and I'm not doing anything to an array after 2. What am I doing wrong? How can a simple assignment cause a segmentation fault?
#include <stdio.h>
#define CHAR_CODE 1
#define NUM_CODE 2
#define RESERVED_CHAR_CODE 3
#define SPACE_CODE 4
#define ERR_CODE 5
char token[16];
char line[128];
int lineLen = 0;
int counter = 0;
FILE *file;
void cleanToken(){
for(int i = 0 ; i < 16; i++){
token[i] = 0;
}
}
void cleanLine(){
for(int i = 0 ; i < 128; i++){
line[i] = 0;
}
}
void next(){
cleanToken();
printf("1\n");
char c;
if(counter == lineLen){
printf("2\n");
lineLen = 0;
printf("3");
cleanLine();
printf("4");
counter = 0;
while((c=getc(file)) != 10 && c != EOF){
if(c!=32){
line[lineLen] = c;
lineLen++;
}
printf("%d\n", lineLen);
}
printf("%s\n", line);
}
c = line[counter];
int type = getType(c);
while(getType(c)==type){
token[counter] = c;
counter = counter + 1;
c = line[counter];
if(c == EOF | c == 4 | type == RESERVED_CHAR_CODE){
break;
}
}
}
int getType(int c){
if((c > 96 & c < 123) | (c>64 & c < 91)){
return CHAR_CODE;
} else if(c < 58 & c > 46){
return NUM_CODE;
} else if(c == 32){
return SPACE_CODE;
} else if(c == 33 | c == 34 | (c > 36 & c < 44) | c == 45 | c == 47 | (c > 58 & c < 63)){
return RESERVED_CHAR_CODE;
} else {
return ERR_CODE;
}
}
int main(){
int c;
FILE* file;
file = fopen("test.txt", "r");
for(int i = 0; i < 10 ;i++){
next();
printf("%s\n", token);
}
return 0;
}
There are a number of problems in your code, most of which will be shown by using -Wall when you compile, but specifically, the crash is being caused by attempting to access the global variable file, which has not been initialized.
You shadowed it in main() with another variable with the same name. You initialized that one, but not the global one being accessed by next().
Also, your printf statements are insufficient for debugging, as there is no guarantee that the output buffer will be flushed to your console before the program crashes. If you add \n to the printf("3") and printf("4") lines, you will see that they get printed before the crash. Alternatively, you could call fflush(stdout) after the printf() calls to ensure that they are printed. By doing this, you will see that the crash is not happening as a result of the assignment as it appears.
A debugger such as gdb would be very helpful in debugging your code.
EDIT
Derp. Just saw eddiem's answer, and he's right - that's the real problem in your code.
However, you should still add the lineLen check in your loop.
ORIGINAL
Gonna bet real money the problem is here:
while((c=getc(file)) != 10 && c != EOF){
if(c!=32){
line[lineLen] = c;
lineLen++;
}
What happens if the file contains more than 128 characters on a single line? You wind up writing past the end of your array, which can cause all kinds of mayhem.
You need to add a check to make sure you're not exceeding your array bounds:
while ( lineLen < 128 && ( c = getc( file ) ) != 10 && c != EOF ) { ... }
You're not seeing 3 and 4 print out because you don't have a newline in those printf statements. stdout is usually line-buffered, which means output won't appear on the terminal unless the buffer is full or a newline character is sent.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With