1

there is a Invalid read of size 4 shows up, but i don't know how to avoid it: this is where the valgrind tells me have the invalid read

Queue* recordQueue = newQueue(NULL, NULL);
    
    FILE* file = fopen(fileName, "r");
    char* processName = malloc(8 * sizeof(char));
    assert(processName != NULL);
    unsigned int arriveTime;
    unsigned int serviceTime;
    short memoryRequirement;
    while (fscanf(file, "%d %s %d %hd", &arriveTime, processName, 
        &serviceTime, &memoryRequirement) != EOF) {
        ProcessStatus status = NOT_READY;
        ProcessInfo* processInfo = newProcessInfo(processName, arriveTime, 
            serviceTime, memoryRequirement, status);
        
        processName = malloc(8 * sizeof(char));
        assert(processName != NULL);
        inQueue(recordQueue, newNode(processInfo, NULL, NULL));
    }
    return recordQueue;

and the valgrind shows that:

==237688== Invalid read of size 4
==237688==    at 0x48C3AF2: __vfscanf_internal (vfscanf-internal.c:345)
==237688==    by 0x48C329C: __isoc99_fscanf (isoc99_fscanf.c:30)
==237688==    by 0x10A3AE: readProcessesFronFile (in /home/haozhec/project1/comp30023-2023-project-1/allocate)
==237688==    by 0x10A91D: main (in /home/haozhec/project1/comp30023-2023-project-1/allocate)
==237688==  Address 0xc0 is not stack'd, malloc'd or (recently) free'd
==237688== 
==237688== 
==237688== Process terminating with default action of signal 11 (SIGSEGV)
==237688==  Access not within mapped region at address 0xC0
==237688==    at 0x48C3AF2: __vfscanf_internal (vfscanf-internal.c:345)
==237688==    by 0x48C329C: __isoc99_fscanf (isoc99_fscanf.c:30)
==237688==    by 0x10A3AE: readProcessesFronFile (in /home/haozhec/project1/comp30023-2023-project-1/allocate)
==237688==    by 0x10A91D: main (in /home/haozhec/project1/comp30023-2023-project-1/allocate)

anybody know how to fix it? can anybody tells me how to avoid such problem when using fscanf?

Howard Cui
  • 21
  • 2
  • 1
    Edit the code to provide a [mre]. In particular, show the input string that is scanned for `processName`. – Eric Postpischil Apr 09 '23 at 23:33
  • 1
    `processName` can only hold strings of max. length of 7. Are you sure that all your strings in the second column of your file are shorter than 8 characters long? – Pablo Apr 09 '23 at 23:35
  • Try with width modifier in `%8s`. – fukanchik Apr 10 '23 at 00:10
  • 1
    My guess: You have a newline at the end of the input file, so the the `fscanf` will not return an EOF on the last record and thus try next a read on an empty/partial record then "over" reading file buffer . (if your process names are all less than 8 chars) – Zilog80 Apr 10 '23 at 00:12
  • 1
    You're reading an unbound string (`%s`) into an 8 char array. There's probably some padding, but you should put a size parameter on the string to make sure. Also remember to count the '\0'. Also, you're reading signed integers (`%d`) into unsigned integers, use `%u` instead. – John Bayko Apr 10 '23 at 00:19
  • @Howard Cui, try `while (fscanf(file, "%d %s %d %hd", &arriveTime, processName, &serviceTime, &memoryRequirement) != EOF)` --> `while (fscanf(file, "%u %7s %u %hd", &arriveTime, processName, &serviceTime, &memoryRequirement) == 4)` – chux - Reinstate Monica Apr 10 '23 at 00:34

1 Answers1

4

If the file doesn't exist for example, fopen will return a null pointer - fscanf will then try to read from the memory pointed to by file, but since it's a null pointer there's no memory there - that's an invalid read. And this is the cause for the SIGSEGV (actually the name of the signal emitted when a segmentation fault occurs).

To prevent such crashes (and give the user feedback as to why your program isn't doing what the user expects), you should check for a null pointer first before doing anything with the file pointer - so, after the fopen line add

if (!file) {
    fprintf(stderr, "Failed opening file '%s': %s\n",
            fileName, strerror(errno));
    return 0;
}

Since file is a pointer (an unsigned integer), it will evaluate to true in a boolean operator if the pointer address is non-zero. Inversely, if the pointer equals 0 (thus is a null pointer) it evaluates to false - ! inverts the boolean result and thus whenever the pointer file equals 0, the if statement will be executed, alerting the user of the situation.

TheEagle
  • 5,808
  • 3
  • 11
  • 39
  • Does this actually fix the problem? This reads as more a comment than an answer as currently written. – Chris Apr 10 '23 at 01:01
  • 1
    @Chris: If `fopen` returns a null pointer and `fscanf` attempts to access offset 0xc0 in the `FILE` structure, that would explain Valgrind complaining about the access to address 0xc0. – Eric Postpischil Apr 10 '23 at 01:24
  • 1
    @EricPostpischil, yes. I felt elaboration would make this a better answer. – Chris Apr 10 '23 at 05:27