1
votes

When i wrote the following code i got weird answers.

#include<stdio.h>
#include<stdlib.h>
main()
{
int *p=malloc(1);
if(p==0)
printf("memory not assigned\n");
else
{
printf("memory assigned\n");
printf("enter an int\t");
scanf("%d",p);
printf("\n You entered number %d",*p);
printf("\nIt has been stored at-%p",p);
}
}

I think malloc takes argument as number of byte.so here i entered 1 byte and i know that on my machine int requires 4 bytes for storage(through sizeof()) but still the code shows no error and i can enter an int value.even if i enter 3333333 it does not complain.if i use malloc() instead of malloc(1) gcc complains of too few argument for malloc but still gives the same result.I cant understand this behaviour.will someone please clarify it.

I am running it on gcc through virtual box.

5
"gcc complains of too few argument for malloc but still gives the same result" - since the compilation failed, your executable hasn't been overwritten, why would it do anything else? - user529758
When i ran it again and entered new value it took it happily and did not complain.so i dont think that the previous executable has not been overwritten. - THE PARADOX
Delete the executable and try again. - congusbongus
@cong xu yes correct,once i deleted the executable and tried to run i gave error :).Thank you.i think its proved that malloc requires one argument. - THE PARADOX
And what if that argument is 0.when i use malloc(0) the compilor does not complain and prints that memory has been assigned. - THE PARADOX

5 Answers

3
votes

As you said, if you do this:

int *p=malloc(1);

Only 1 byte will be allocated. Since an int is larger than 1 byte, it will overrun the allocated memory and give you undefined behavior. If you do this:

int *p=malloc(sizeof(int));

Then there will be enough space for the integer.

C does not warn you when you run outside the bounds allocated memory, so you need to carefully manage what size you malloc.

2
votes

Malloc in "modern" environments use different kind of allocation strategies for different lengths. The common thing is that in 32-bit environments the de facto standard was to align everything by 8 bytes and nowadays in x64 era in 16-byte granularity.

This in effect means there are 7 or 15 characters of extra space after the 1 byte you asked. Should you use it? Only with consenting adults within closed doors.

Among the methods, btw, there are reverting to system call, that allocates pages at physical boundaries -- try e.g. malloc(1<<28); (256 Mb); some implementation of malloc allocate 1-8 or 1-16 bytes from a special buffer and in turn for larger chunks reserve internally N+8 or N+16 (again rounded up to next boundary) for bookkeeping data too.

This is the data that will be trashed, if you overwrite your reserved area. It leads to ASSERT in some malloc / free later on and it leads to a duplicate and soon to be closed very vague question on SO.

Malloc on embedded systems can be programmed not to be able to reclaim; it can be implemented simply by

void *malloc_embedded(size_t a) {
    static uint8_t *heap=_heap;
    uint8_t *old=heap; heap+=a;
    return old;
}

This behaves as you probably expected, but the use cases are much more limited -- this method could be modified to be able to free the last allocated element but no more.

0
votes

Undefined behavior ?? malloc(1) returns a free block or size 1 byte, there might be more blocks besides the one returned, where your integer gets written.(that rhymed!)

Obviously, malloc() requires 1 argument. If you supply none, gcc will complain, and so will all other compilers that obey C's standard.

If you want sizeof(int) bytes then: malloc(sizeof(int))

0
votes

It is your responsibility to alloc enough memory for your needs. Compiler won't check whether you are accessing memory which is outside what you alloc'ed.

If you alloc x amount of memory, to store values of size grater than x, your app may(may not) crash at run time. It is undefined behaviour.

If you call malloc(1) ,there is no need for the compiler to complain since, malloc requires one argument (size of memory), and you are passing it..

But when you call malloc(), the case is different, and compiler complains..

0
votes

The implementation of malloc is unlikely to give you exactly one byte. It'll likely be sized up to the nearest word size, which means that something that is the sizeof(int) will fit into that space. Much like:

struct foo {
    char a;
};

The sizeof(struct foo) will likely be the word size. Needless to say, you should be allocating more space (e.g. malloc(sizeof(int))) since you want to read an int. It'll be less confusing for software maintenance later on, despite the fact it "happens" to work. It's likely undefined behavior.