Attempt to debug program c segmentation error using valgrind output

The CLI compiler compiles and works fine on windows. Compilation works fine on Linux, but a segmentation error occurs during operation.

I turned to stackoverflow for help and found some questions similar to what I was going to ask what the valgrind I just installed (woo!) Suggested.

So, I ran my program through valgrind and received a depressingly large amount of output, but I will start with the first error message:

==11951== Command: ./vt ==11951== Loading... Load default database? (y/n)y Opened input file vtdb.~sv, reading contents... ==11951== Invalid write of size 1 ==11951== at 0x400FA9: readnumberfromfile (in /home/rob/Documents/programming/c/vocabtest/vt) ==11951== by 0x400C21: getrecordsfromfile (in /home/rob/Documents/programming/c/vocabtest/vt) ==11951== by 0x401FFD: main (in /home/rob/Documents/programming/c/vocabtest/vt) ==11951== Address 0x53b05bb is 0 bytes after a block of size 11 alloc'd ==11951== at 0x4C28FAC: malloc (vg_replace_malloc.c:236) ==11951== by 0x400EAC: readnumberfromfile (in /home/rob/Documents/programming/c/vocabtest/vt) ==11951== by 0x400C21: getrecordsfromfile (in /home/rob/Documents/programming/c/vocabtest/vt) ==11951== by 0x401FFD: main (in /home/rob/Documents/programming/c/vocabtest/vt) ==11951== ...finished. 1180 entries read from vtdb.~sv. 

The problem seems to be in readnumberfromfile , and I looked through it and I can’t find what is wrong with it!

Can anyone shed some light?

 int readnumberfromfile (int maxvalue,char separator) { int number, i=0; char ch; char * buff = (char *)malloc(11);//allocate enough space for an 10-digit number and a terminating null if (!buff) {printf("Memory allocation failed!\n");return 0;}//return 0 and print error if alloc failed if (!maxvalue) maxvalue=MAXINTVALUE; ch=getc(inputfile); while (!isdigit(ch)) { if (ch == separator||ch=='\n'||ch==EOF) {fprintf(stderr,"Format error in file\n");return 0;}//if no number found(reached separator before digit), print error and return 0 ch = getc(inputfile);//cycle forward until you reach a digit } while (i<11 && ch!=separator && ch!='\n')//stop when you reach '~', end of line, or when number too long { buff[i++]=ch; ch = getc(inputfile); //copy number from file to buff, one char at a time } buff[i] = '\0';//terminate string number = atoi(buff)<=maxvalue ? atoi(buff) : maxvalue;//convert string to number and make sure it in range free(buff); return number; } 

This is called from getrecordsfromfile , if used:

 void getrecordsfromfile(char * inputfilename,char separator) { int counter = 0; struct vocab * newvocab; struct listinfo * newvocablist; if (!(inputfile = fopen(inputfilename, "r"))) { printf("Unable to read input file. File does not exist or is in use.\n"); } else { printf("Opened input file %s, reading contents...\n",inputfilename); while (!feof(inputfile)) { newvocab = (struct vocab *)malloc(sizeof(struct vocab)); if (!newvocab) { printf("Memory allocation failed!\n"); return; } else { newvocab->question=readtextfromfile(MAXTEXTLENGTH,separator); newvocab->answer=readtextfromfile(MAXTEXTLENGTH,separator); newvocab->info=readtextfromfile(MAXTEXTLENGTH,separator); newvocab->hint=readtextfromfile(MAXTEXTLENGTH,separator); newvocab->right=readnumberfromfile(1,separator); newvocab->counter=readnumberfromfile(0,separator); newvocab->known=readnumberfromfile(3,separator); switch (newvocab->known) { case 0: newvocablist = &n2l;break; case 1: newvocablist = &norm;break; case 2: newvocablist = &known;break; case 3: newvocablist = &old;break; } addtolist(newvocab,newvocablist); if (newvocab->question==NULL||newvocab->answer==NULL) { printf("Removing empty vocab record created from faulty input file...\n"); removefromlist(newvocab,newvocablist,1); } else counter++; } } fclose(inputfile); printf("...finished.\n%i entries read from %s.\n\n",counter,inputfilename); } return; } 

The full source can be created from https://github.com/megamasha/Vocab-Tester

A few notes: I'm trying to help myself, I did my research, looked at similar questions and myself learned about valgrind.

I am still a relative novice, and although I appreciate the solutions (WHAT to do to fix this), knowledge (HOW to fix or avoid it next time) is even more useful. I am here (and very passionate) to learn.

+4
source share
4 answers
 int number, i=0; ... while (i<11 ... 

You read up to eleven digits for i = 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, and 10. And then try to insert \0 into the twelfth slot of buff[11] .

He caused " one mistake ."

So, the fix depends on what you want to change. If you want to accept 11 characters, change malloc buff. If you want to accept only 10, change the while condition.

+3
source

buff[i] = '\0';//terminate string

here i == 11, since you allocated only 11 characters, and while the condition ends when i = 11. So, you get access to memory that you did not allocate.

behavior for this situation is not defined.

you can solve this by highlighting one extra character on malloc .

+7
source

Invalid size 1 record

You are probably writing char

The address 0x53b05bb is 0 bytes after a block of size 11 alloc'd

You just overflowed something in size 11

Both in readnumberfromfile

This is suspiciously related (in size):

 char * buff = (char *)malloc(11); 

This will be done using i = 11 after the loop that ends after the allocation:

 buff[i] = '\0' 

As wormsparty reports, you can get valgrind to be more useful by getting debugging characters in your binary format.

+2
source

In the future, if you compile with -g, valgrind will show you exactly which line segfault occurred on.

+1
source

All Articles