1

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.

congusbongus
  • 13,359
  • 7
  • 71
  • 99
  • 1
    "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? –  Mar 01 '13 at 05:46
  • 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 Mar 01 '13 at 06:17
  • Delete the executable and try again. – congusbongus Mar 01 '13 at 06:57
  • @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 Mar 01 '13 at 08:11
  • 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 Mar 01 '13 at 08:17
  • According to C99 standard If the size of the space requested is zero, the behavior is implementation defined: either a null pointer is returned, or the behavior is as if the size were some nonzero value, except that the returned pointer shall not be used to access an object.but when i use it to access the stored at the location the pointer holds,it displays the answer.why? – THE PARADOX Mar 01 '13 at 09:09
  • undefined behaviour, or implementation-defined behaviour, means it may some times work but you shouldn't depend on it. – congusbongus Mar 01 '13 at 12:10
  • Thanks @cong xu and everyone for trying to help. – THE PARADOX Mar 01 '13 at 12:29

5 Answers5

3

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.

  • I agree with you.but when i do something like int *p=malloc(),here i give malloc no arguments,i dont specify no of bytes i need.so the compiler should print memory not assigned.is it?or the compiler tackles this problem some other way. – THE PARADOX Mar 01 '13 at 06:05
  • Some compilers may substitute default arguments -- it would be `int malloc();` and when this would be linked to the implementation of malloc, the behaviour would be undefined. Malloc would expect there to be an integer, which would probably be zero, but could be almost anything else too. Some compilers, such as gcc 4.6.1. would give an error `"too few arguments to function malloc"` – Aki Suihkonen Mar 01 '13 at 07:29
2

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.

Aki Suihkonen
  • 19,144
  • 1
  • 36
  • 57
  • Isn't that wastage of precious space.and what do you think will happen if i did not ask for any space like if i did int * p=malloc() – THE PARADOX Mar 01 '13 at 07:11
  • That's a carefully calculated tradeoff in between execution speed and ability to reclaim / free and later reallocate blocks. If you OTOH know you need a bunches of '1' char entries, why not use a custom structure such as `uint8_t pool[121];` ? `malloc();` should not compile. – Aki Suihkonen Mar 01 '13 at 07:16
  • 1
    @THEPARADOX - Wouldn't the big waste be to allocate 1 byte using `malloc` and then use 4 or 8 bytes for the pointer `p`? So most implementations assume you don't do that very often, and optimize for other cases. – Bo Persson Mar 01 '13 at 08:37
0

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))

Aniket Inge
  • 25,375
  • 5
  • 50
  • 78
  • Yes i understand that gcc should complain.but what i want to say why does it allow the code to run inspite of the problem it has. – THE PARADOX Mar 01 '13 at 05:53
  • @THEPARADOX because it is not mentioned in C standard that such code should not be allowed. It all boils down to the C standards. And a compiler must obey it - no matter what, without breaking code in the past – Aniket Inge Mar 01 '13 at 05:55
  • If i write int *p=malloc(),here i give malloc no arguments,i dont specify no of bytes i need.so the compiler should print memory not assigned.is it? – THE PARADOX Mar 01 '13 at 06:13
0

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..

Krishnabhadra
  • 34,169
  • 30
  • 118
  • 167
0

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.

ldav1s
  • 15,885
  • 2
  • 53
  • 56