1

I have found a piece of code online that purposely has errors in the code as part of a debugging exercise. I have gotten the simple errors fixed, but there is one line which I'm not sure whether it is valid.

#include <stdlib.h>
#include <stdio.h>

struct foo {
    int size;
    int *array;
};

typedef struct foo bar;

bar* readArray(){
    bar *fbar = (bar *)malloc(sizeof(bar));
    fbar->array = (int *)malloc(sizeof(int)*2); //ADDED THIS LINE FOR TESTING
    int i = 0;
    int temp;
    while(scanf("%d", &temp) == 1){
        *(fbar->array + (i-1)) = temp; //THIS LINE HERE
        i++;
    }
    if(i == 0){
        printf("No numbers were entered!");
    }
    fbar->size = i;
    return fbar;

}

int main(){
    bar *p = readArray();
    return 0;
}

I tried running it which of course causes a segfault because the example didn't malloc space for *array. I tried testing the line by mallocing space for 2 int's to test if the first 2 loops worked. I assumed the program would get a segfault after the first 2 int's are read, which did not occur (the program keeps running). Now I don't understand what that line of code does and why I am not segfaulting.

I can't exactly figure out what is the error, or if there even is an error besides the lack of malloc() for int *array.

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
Johan14th
  • 117
  • 1
  • 12
  • You won't always get a seg-fault if you write out of bounds. If your array is size 2 and you write 3 elements to it, depending on where in memory the array is, you just corrupt the next address after the array. This may or may not cause a seg-fault. – Kon Oct 09 '18 at 16:12
  • 2
    [why you're not segfaulting](https://stackoverflow.com/questions/12410016/why-dont-i-get-a-segmentation-fault-when-i-write-beyond-the-end-of-an-array) – Barmar Oct 09 '18 at 16:12
  • @ODYN-Kon oh wow thanks, I usually get a segfault when I don't malloc enough memory, I assumed this would always be the case. – Johan14th Oct 09 '18 at 16:17
  • Seg fault is usually some sort of memory access violation. If you write far enough past the boundary you'll usually run into that. It all depends where in memory original array was allocated. If it's placed right against the boundary of the memory you have access to, even a single byte overflow would cause seg fault. – Kon Oct 09 '18 at 16:23

1 Answers1

6

For any pointer (or array) p and index i the expression *(p + i) is exactly equal to p[i].

Now if we take your expression *(fbar->array + (i-1)), with the above it's equal to fbar->array[i - 1].

The problem should be clear what happens when i == 0 and you have fbar->array[-1]. It is out of bounds and will lead to undefined behavior.

As for why it doesn't crash, that's part of the undefined behavior. It could crash, it could seem to work (like it does for you), or it could bring forth nasal demons.

Some programmer dude
  • 400,186
  • 35
  • 402
  • 621
  • ok that makes sense I would then instead use `*(fbar->array + i) = test` if I understood this. But would you have any idea, why the program wouldn't crash even after the second loop if I only malloced enough for 2 int's? – Johan14th Oct 09 '18 at 16:14
  • 3
    @Johan14th: That's the thing about undefined behavior - your code *may* crash immediately, or it may put the program in a bad state where it crashes in a later operation, or it may result in bad output, or it may appear to work with no issues. – John Bode Oct 09 '18 at 17:09