Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

How to overcome Segfault on accessing pointer to array

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, "%100[^;];%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)

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

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

>Solution :

Code passes an uninitialized object readString to sscanf() leading to undefined behavior (UB). @Johnny Mopp

char* readString;
...
sscanf(str, "%100[^;];%d;%f", readString, &d1, &f1);  // bad

Instead

char readString[100+1];

Check return value

Test if scan was successful**

// sscanf(str, "%100[^;];%d;%f", readString, &d1, &f1);
if (sscanf(str, "%100[^;];%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.

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading