Kvass
Kvass

Reputation: 8434

Mallocing an Array in C

I have the following piece of code which I would expect to fail but seems to be working correctly. I'm confused by why this is not causing some sort of segmentation fault.

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

struct entry {
    int foo;
};

struct table {
    int size;
    struct entry* entries;
};

typedef struct table *Table;
typedef struct entry Entry;

int main() {
    Table table = malloc(sizeof(struct table));
    table->entries = malloc(sizeof(struct entry) * 1);
    (table->entries)[5].foo = 5;
    for (int i = 0; i < 10; i++) {
        printf("Entry #%d: %d\n",i,(table->entries)[i].foo);
    }
}

I would have expected that since I only malloced enough space for one entry in table->entries, accessing any index other than 0 would be out of bounds. But when I run this program it prints out 5 for as the foo value of the entry at index 5, and the rest as 0, which is the correct behavior. Why is this not failing?

Upvotes: 0

Views: 674

Answers (5)

YaleCheung
YaleCheung

Reputation: 620

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

struct entry {
    int foo;
};

struct table {
    int size;
    struct entry* entries;
};

typedef struct table *Table;
typedef struct entry Entry;

int main() {
    Table table =(table)malloc(sizeof(struct table));
    table->entries =(entry*)malloc(sizeof(struct entry) * 10);
    (table->entries)[5].foo = 5;
    for (int i = 0; i < 10; i++) {
        printf("Entry #%d: %d\n",i,(table->entries)[i].foo);
    }
}

First, you need to convert the (void*) type into the pointer type you want when using malloc. Second, you only allocate entries pointers, which means, when you use (table->entries)[5].foo, you might access memory illegal, so it's a dangerous behavior. Finally, you need to initialize foo before you print it. You need to obey the rules, do not write codes like that.

Upvotes: 0

Jonathan Leffler
Jonathan Leffler

Reputation: 753725

You are accessing out of bounds, but that merely invokes 'undefined behaviour'. Anything may happen when you invoke 'undefined behaviour'. One possibility is that the program crashes; another is that the program does not crash and appears to be OK. Either is possible; it is even possible for it sometimes to crash and sometimes not crash.

If you tried more memory allocation, or tried freeing memory, you'd be more likely to see that things have gone wrong. However, even that's not guaranteed; you may have missed all the sensitive information (the bytes that are used by malloc() et al to determine which memory is allocated and which is not).

You can write:

table->entries[i].foo

You don't need the parentheses around (table->entries)[i].foo, though they're harmless except that they suggest a neophyte was coding.

Upvotes: 1

Vallabh Patade
Vallabh Patade

Reputation: 5110

This is undefined behavior that you are accessing memory location which is not 'yours'. You have writern some thing in memory which is not allocated by you, corrupting that memory location.

Upvotes: 0

Havenard
Havenard

Reputation: 27864

Its not failing because despite you are writing to unallocated memory, this memory is perfectly inside the legal HEAP space. But sinse you didn't declare to the memory manager that you are using that memory space, a future malloc() may try to alloc to the same area, and you will get overlapping buffers and undefined behaviour.

Upvotes: 0

Charlie Burns
Charlie Burns

Reputation: 7044

Someone else will say it better, but Undefined Behavior is undefined.

It's not defined. It might work. It might not.

It all depends what is in those memory locations.

You wrote one bad location. You read some others. You happened to not hit anything too important.

You wrote one word well past your malloc'ed area. Perhaps if you did more computations that would cause trouble because you wrote into malloc's data structures. Maybe not.

Upvotes: 2

Related Questions