Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
524 views
in Technique[技术] by (71.8m points)

c - What happens if I use malloc with the wrong size?

I'm trying to learn more about memory allocation, and so I wrote some test code below to see what would happen if I tried to allocate memory of a less size than what I needed.

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

typedef struct {
    char *message;
    int number;
} Object;

int main(int argc, char *argv[]) {
    Object *obj = malloc(sizeof(Object) - 8);   
    printf("The size of the struct is: %ld
", sizeof(Object));
    printf("The size of what was allocated is: %ld
", sizeof(*obj));

    obj->message = "Hello there! My name is Chris!";
    obj->number = 435543;

    puts(obj->message);
    printf("%d
", obj->number);

    free(obj);

    return 0;
}

First of all, is sizeof(*obj) the correct way to see how much memory was actually allocated in this case? Second, why am I still able to assign values to struct objects even if I didn't allocate enough space?

My OS is Ubuntu 12.10 64bit, compiler is gcc 4.7.2

Here is the valgrind output:

==14257== Memcheck, a memory error detector
==14257== Copyright (C) 2002-2011, and GNU GPL'd, by Julian Seward et al.
==14257== Using Valgrind-3.7.0 and LibVEX; rerun with -h for copyright info
==14257== Command: ./ex
==14257== 
The size of the struct is: 16
The size of what was allocated is: 16
==14257== Invalid write of size 4
==14257==    at 0x400640: main (ex.c:15)
==14257==  Address 0x51f1048 is 0 bytes after a block of size 8 alloc'd
==14257==    at 0x4C2B3F8: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==14257==    by 0x400604: main (ex.c:10)
==14257== 
Hello there! My name is Chris!
==14257== Invalid read of size 4
==14257==    at 0x40065A: main (ex.c:18)
==14257==  Address 0x51f1048 is 0 bytes after a block of size 8 alloc'd
==14257==    at 0x4C2B3F8: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==14257==    by 0x400604: main (ex.c:10)
==14257== 
435543
==14257== 
==14257== HEAP SUMMARY:
==14257==     in use at exit: 0 bytes in 0 blocks
==14257==   total heap usage: 1 allocs, 1 frees, 8 bytes allocated
==14257== 
==14257== All heap blocks were freed -- no leaks are possible
==14257== 
==14257== For counts of detected and suppressed errors, rerun with: -v
==14257== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 2 from 2)
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

In this specific case, you are potentially trying to allocate 0 bytes, because sizeof(Object) is 8 in most 32-bit compilers. malloc(0) will return NULL as its an invalid size to be allocated, and trying to write to address NULL will certainly crash your application.

But lets suppose you successfully allocate 4 bytes, and try to write 8 bytes within it. In a single thread application it should probably work without issues, because despite you will be writing to unallocated memory space, it will not be exactly writing to some crazy address lost in the virtual memory.

Howover, if you do this:

Object* a = (Object*)malloc(4);
Object* b = (Object*)malloc(4);

It is potentially true that a and b were allocated in serie. It means that, in most 32-bit compilers, writing to a->number will overwrite b->message with the same value and vice versa, because both will be trying to store information to the same space in memory.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...