1

I know that malloc(size_t size) allocates size bytes and returns a pointer to the allocated memory. .

So how come when I allocate zero bytes to the integer pointer p, I am still able to initialize it?

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

int main()
{

        int *p = malloc(0);
        *p = 10;

        printf("Pointer address is: %p\n", p);
        printf("The value of the pointer: %d\n", *p);

        return 0;
}

Here is my program output, I was expecting a segmentation fault.

Pointer address is: 0x1ebd260
The value of the pointer: 10
aboria
  • 123
  • 6

5 Answers5

3

The behavior of malloc(0) is implementation defined, it will either return a pointer or NULL. As per C Standard, you should not use the pointer returned by malloc when requested zero size space1).

Dereferencing the pointer returned by malloc(0) is undefined behavior which includes the program may execute incorrectly (either crashing or silently generating incorrect results), or it may fortuitously do exactly what the programmer intended.


1) From C Standard#7.22.3p1 [emphasis added]:

1 The order and contiguity of storage allocated by successive calls to the aligned_alloc, calloc, malloc, and realloc functions is unspecified. The pointer returned if the allocation succeeds is suitably aligned so that it may be assigned to a pointer to any type of object with a fundamental alignment requirement and then used to access such an object or an array of such objects in the space allocated (until the space is explicitly deallocated). The lifetime of an allocated object extends from the allocation until the deallocation. Each such allocation shall yield a pointer to an object disjoint from any other object. The pointer returned points to the start (lowest byte address) of the allocated space. If the space cannot be allocated, a null pointer is returned. 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.

H.S.
  • 11,654
  • 2
  • 15
  • 32
1

When you call malloc(0) and write to the returned buffer, you invoke undefined behavior. That means you can't predict how the program will behave. It might crash, it might output strange results, or (as in this case) it may appear to work properly.

Just because the program could crash doesn't mean it will.

dbush
  • 205,898
  • 23
  • 218
  • 273
0

In general, C does not prevent you from doing incorrect things.

After int *p = malloc(0);, p has some value. It might be a null pointer, or it might point to one or more bytes of memory. In either case, you should not use it.1 But the C language does not stop you from doing so.

When you execute *p = 10;, the compiler may have generated code to write 10 to the place where p points. p may be pointing at actual writable memory, so the store instruction may execute without failing. And then you have written 10 to a place in memory where you should not. At this point, the C standard no longer specifies what the behavior of your program is—by writing to an inappropriate place, you have broken the model of how C works.

It is also possible your compiler recognizes that *p = 10; is incorrect code in this situation and generates something other than the write to memory described above. A good compiler might give you a warning message for this code, but the compiler is not obligated to do this by the C standard, and it can allow your program to break in other ways.

Footnote

1 If malloc returns a null pointer, you should not write to *p because it is not pointing to an object. If it returns something else, you should not write to *p because C 2018 7.22.3.1 says, for this of malloc(0), “the returned pointer shall not be used to access an object.”

Eric Postpischil
  • 195,579
  • 13
  • 168
  • 312
0

I think it is good idea to look at segmentation fault definition https://en.wikipedia.org/wiki/Segmentation_fault

The following are some typical causes of a segmentation fault:

  • Attempting to access a nonexistent memory address (outside process's address space)
  • Attempting to access memory the program does not have rights to (such as kernel structures in process context)
  • Attempting to write read-only memory (such as code segment)

So in general, access to any address in program's data segment will not lead to seg fault. This approach makes sence as C doesn't have any framework with memory management in it (like C# or Java). So as malloc in this example returns some address (not NULL) it returns it from program's data segment which can be accessed by program.

However if program is complex, such action (*p = 10) may overwrite data belonging to some other variable or object (or even pointer!) and lead to undefined behaviour (including seg fault).

But please take in account, that as described in other answers such program is not best practice and you shouldn't use such approach in production.

Fyodor Yemelyanenko
  • 11,264
  • 1
  • 30
  • 38
-1
This is a source code of malloc() (maybe have a litter difference between kernel versions but concept still like this), It can answer your question:

static void *malloc(int size)
{
void *p;

         if (size < 0)
        error("Malloc error");
         if (!malloc_ptr)
        malloc_ptr = free_mem_ptr;

         malloc_ptr = (malloc_ptr + 3) & ~3;     /* Align */

         p = (void *)malloc_ptr;
         malloc_ptr += size;

         if (free_mem_end_ptr && malloc_ptr >= free_mem_end_ptr)
        error("Out of memory");

         malloc_count++;
         return p;
  }

When you assigned size is 0, it already gave you a pointer to first address of memory

Hai
  • 73
  • 1
  • 10