Segfault on accessing pointers
I'm developing simple GTK3 C app (using WSL2 and VSCode), but when I try to deserialize structs from file I'm getting Segfault (I'm not really familiar with gdb, so when I tried to debug I couldn't really find the line which causes error).
My Code
Struct definition
typedef struct whatev {
size_t id;
char* name;
int amount;
float value;
signed char state;
} SomeStruct;
Struct is defined in separate, included header, which doesen't cause any problems during compilation (just for clarification)
Function causing segfault
SomeStruct* checkLine(char* str) {
char* readString;
int d1;
float f1;
sscanf(str, "0[^;];%d;%f", readString, &d1, &f1);
// printf("Checking line: Read name: \"%s\", amount=%d, value=%f\n", readString, d1, f1);
if (readString[0] != '\0') {
SomeStruct* newLine = malloc(sizeof(SomeStruct));
// strcpy(newLine->name, readString);
newLine->name = readString;
newLine->amount = d1;
newLine->value = f1;
return newLine;
}
return NULL;
}
SomeStruct* createStructsFromFile(FILE* filestream, size_t fileLength) {
printf("Create struct from file: start\n");
SomeStruct* js = malloc(fileLength * sizeof(js));
SomeStruct* currentItem = malloc(sizeof(js));
size_t failed = 0;
size_t j = 0;
unsigned int buffer_size = 500;
// ERROR: Segfault somewhere here
for (size_t i = 0; i < fileLength; i ) {
char buffer[buffer_size];
fgets(buffer, buffer_size, filestream);
if ((currentItem = checkLine(buffer)) != NULL) {
currentItem->id = j;
currentItem->state = 0;
js[j] = *currentItem;
currentItem = (SomeStruct*)malloc(sizeof(js));
j ;
}
else
failed ; // TODO
}
printf("Create struct from file: Finished creating, failed reading %zd / %zd lines\n", failed, fileLength);
return js;
}
My debugging attempt
Breakpoint 5 at 0x80031a6: file FileOperations/fileOperations.c, line 125.
(gdb) step
[LWP 22523 exited]
createStructsFromFile: before assignment currentItem[0] (KsiążkaZPolskimiZnakami) to js[0]
123 js[j] = *currentItem;
(gdb) display js
13: js = (SomeStruct *) 0x85663e0
(gdb) display js[0]
14: js[0] = {id = 139820112, name = 0x0, amount = 137883733, value = 2.80259693e-44, state = 0 '\000'}
(gdb) display js[1]
15: js[1] = {id = 90194313216, name = 0xfffffff <error: Cannot access memory at address 0xfffffff>,
amount = 0, value = 0, state = 21 '\025'}
(gdb) display js[19]
16: js[19] = {id = 67174657, name = 0x0, amount = 0, value = -8.99305959e 35, state = 54 '6'}
(gdb) display currentItem
17: currentItem = (SomeStruct *) 0x83f34b0
(gdb) display currentItem->name
18: currentItem->name = 0x7ffffffecf30 "KsiążkaZPolskimiZnakami"
(gdb) step
Thread 1 "main" hit Breakpoint 5, createStructsFromFile (filestream=0x696b736c6f505a61,
fileLength=7763297035996459851) at FileOperations/fileOperations.c:125
125 printf("createStructsFromFile: inserted %zdth struct\n\n", j);
13: js = (SomeStruct *) 0x85663e0
14: js[0] = {id = 0, name = 0x7ffffffecf30 "KsiążkaZPolskimiZnakami", amount = 12,
value = 3.99000001, state = 0 '\000'}
15: js[1] = {id = 90194313216, name = 0xfffffff <error: Cannot access memory at address 0xfffffff>,
amount = 0, value = 0, state = 21 '\025'}
16: js[19] = {id = 67174657, name = 0x0, amount = 0, value = -8.99305959e 35, state = 54 '6'}
17: currentItem = (SomeStruct *) 0x83f34b0
18: currentItem->name = 0x7ffffffecf30 "KsiążkaZPolskimiZnakami"
(gdb) step
createStructsFromFile: inserted 0th struct
126 currentItem = malloc(sizeof(js));
13: js = (SomeStruct *) 0x85663e0
14: js[0] = {id = 0, name = 0x7ffffffecf30 "KsiążkaZPolskimiZnakami", amount = 12,
value = 3.99000001, state = 0 '\000'}
15: js[1] = {id = 90194313216, name = 0xfffffff <error: Cannot access memory at address 0xfffffff>,
amount = 0, value = 0, state = 21 '\025'}
16: js[19] = {id = 67174657, name = 0x0, amount = 0, value = -8.99305959e 35, state = 54 '6'}
17: currentItem = (SomeStruct *) 0x83f34b0
18: currentItem->name = 0x7ffffffecf30 "KsiążkaZPolskimiZnakami"
(gdb) step
start pętli 1
Thread 1 "main" received signal SIGSEGV, Segmentation fault.
0x00007ffffeae2657 in ?? ()
Sample database
KsiążkaZPolskimiZnakami;12;3.99
Book with a lot of spaces;44;2.99
OutOfStock;0;1.00
LiterallyFreeNotebook;99;0.00
NextLineTriesToMakeScanfError;1;255.12
;;
HopeThatReadingWillWork;12;66.72
ThisBookHas7Parts;3;12.50
لكن لا بد أن أوضح لك أن كل هذه الأفكار;6;12.5
ArabicAndNeat;8;11
NegativeQuantity;-12;5.00
NegativeValue;7;-2.22
!LL3G4L_$|gNS;10;7.5
AboveWasJustSpace;2;0.1
TooManyArguments;1;15.55;12
UnexpectedType;3232.1;55
71830;80085;AndOtherFunnyThings
\0;\0;\0
EscapeSequence\n\"exit(1);11;255.1
YesILoveDebugging,Why?;-0;-99999999999999.9999
Expectations
I want to use createStructsFromFile
's output to populate GTK TreeView. I also tried using double pointers, but for debugging sake I simplified returns (size_t createStructsFromFile(FILE* filestream, size_t fileLength, JakasStruktura** js)
What's wrong and how can I improve it?
If needed, code can be found on my GitHub
(commit)[https://github.com/ikarmus2001/ProjektC/commit/761a1f2000ee8ab1c32efd8449c1b95f8f11a2c1]
Thanks in advance
CodePudding user response:
Code passes an uninitialized object readString
to sscanf()
leading to undefined behavior (UB). @Johnny Mopp
char* readString;
...
sscanf(str, "0[^;];%d;%f", readString, &d1, &f1); // bad
Instead
char readString[100 1];
Check return value
Test if scan was successful**
// sscanf(str, "0[^;];%d;%f", readString, &d1, &f1);
if (sscanf(str, "0[^;];%d;%f", readString, &d1, &f1) != 3) {
Handle_bad_input();
}
Needs a copy of the string
Instead of coping a point, allocate data.
// newLine->name = readString;
newLine->name = malloc(strlen(readString) 1);
if (newLine->name == NULL) {
TBD_eror_handling();
}
strcpy(newLine->name, readString);
The earlier SomeStruct* newLine = malloc(sizeof(SomeStruct));
allocated memory for the struct, including the pointer: .name
member. Yet the pointer still does not point to any allocated string.
Later code needs to free this allocation when done with the structure.
CodePudding user response:
Doesen't mallocking struct already reserve memory for that pointer? SomeStruct* newLine = malloc(sizeof(SomeStruct)); newLine->name = readString;
no that allocates space for the struct itself. So you get one of these
typedef struct whatev {
size_t id;
char* name;
int amount;
float value;
signed char state;
} SomeStruct;
but name
is not pointing anywhere (malloc doesnt even know there is a pointer there, it just gives you raw memory for the whole struct). You now need to make name
point somewhere too