Search code examples
cmallocoverflow

Why is there no error when you input letters more than malloc size?


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

int main() {

  char * chr = (char*)malloc(sizeof(char));
  
  chr = "apple";
  printf("%s", chr);
  
  return 0;

}

Hello. I have a question about malloc. I made only int sized byte (1byte) with malloc. And I input oversized letter "apple" (6byte) I thought the ouput would be like "A" or Null. But the output was "apple". How could this possible?


Solution

  • The memory malloc assign is not assigned the same way as the memory assigned when declaring a variable or an array.

    Malloc (and its derrivates) assign memory in the Heap while declaring a string or an int assign memory in the stack.

    char *ptr = malloc(sizeof(char) * (elem + 1)); // Here malloc is called, memory is assined in the heap
    
    ptr = "hello world"; // allocates a new space in the stach where the string hello world is stored 
    

    Basicaly here you are not filling the allocated space of memory with apple. You are delacring a new one that contain apple.

    If you're new to C programming i advise you to learn how to use pointer and arrays before using malloc (try to reproduce strlen, puts or other simple functions like these)

    The next part is only here if you want to roughly understand how it works

    What's the difference ?

    The difference is, your stack memory change while your program process When your main function is load, it load it variables in the stack. Then when you call an other function such as f1, f1 and it variable will also be load in the stack

    Let's take the following code :

    int f1() {
        int var4 = 0;
        // step 2 and 5
        return (0);
    }
    
    char *f2() {
        int var5 = 0;
        int var6 = 0;
        char *f2_ptr = malloc(sizeof(char) * 10); // we will ignore this for the first part
        // step 4
        f1()
        // step 6
        return (ptr);
    }
    
    int main(void) {
        int var1 = 0;
        int var2 = 0;
        int var3 = 0;
        // step 1
        f1();
        // step 3
        char *main_ptr = f2()
        // step 7
        free(ptr)
        // step 8 (only for Stack + Heap part)    
        return (0);
    }
    

    There is the shema of your memory step by step

    Stack Only

    step 1 main and our variables has been load

    main
       var1
       var2
       var3
    

    step 2 we've entered in f1, main and our main's variables are still here but now we also have f1 and f1 variable

    main
        var1
        var2
        var3
        f1
            var4
    

    step 3 we've left f1 so it has been unloaded. main and our main variables are still loaded

    main
       var1
       var2
       var3
       
    

    step 4 just like in step 2 we've entered in a function (f2), main and our main's variables remains and we load f2 and f2 variables

    main
        var1
        var2
        var3
        f2
            var5
            var6
    

    step 5 Once again we've entered in f1. f1 and its variable are loaded at the bottom of your stack

    main
        var1
        var2
        var3
        f2
            var5
            var6
            f1
                var4
    

    step 6 we leave f1, f1 and its variable are unload

    main
        var1
        var2
        var3
        f2
            var5
            var6
    

    step 7 we leave f2, f2 and its variable are unload

    main
        var1
        var2
        var3
    

    As you can see, the more we progress in the program the lower in the stack we go. when we hit a return statement, we go back up in the stack.

    Stack + Heap

    When you use malloc, the allocated space of memory return is not stored in the stack. This allow you to have a memory segment which is not unloaded when you leave the function. This allow you to make dynamic memory allocation and a lot of other stuffs.

    Here is the same step by step example with malloc :

    steps 1, 2 and 3 are basicly the same as the first part

    main
       var1
       var2
       var3
       
    

    step 4 this time we use malloc and a new memory segment is allocated away from the stack. its adress is store in f2_ptr

    main
        var1
        var2
        var3
        main_ptr
        f2
            var5
            var6
            f2_ptr
    
    
    malloc_memory_segment
    

    step 5 as you can see the memory segment created by malloc remain at the bottom of the memory

    main
        var1
        var2
        var3
        main_ptr
        f2
            var5
            var6
            f2_ptr
            f1
                var4
    
    malloc_memory_segment
    

    step 6 we leave f1, f1 and its variable are unload

    main
        var1
        var2
        var3
        main_ptr
        f2
            var5
            var6
            f2_ptr
    
    
    malloc_memory_segment
    

    step 7 we leave f2, f2 and its variables are unload but not the malloc allocated segment

    main
        var1
        var2
        var3
        main_ptr
    
    malloc_memory_segment
    

    step 8 we free main_ptr which delete the malloc_memory_segment

    main
        var1
        var2
        var3
        main_ptr
    

    Hope this was clear enough and it helps you understand how your program works

    Good luck and keep learning