0

I currently learning c and then ran into free() and malloc(). So there is this small program to toy aroung with malloc and free.

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

int main(int argc, char *argv[]) {
    char *char_ptr; // A char pointer
    int *int_ptr; // An integer pointer
    char *char_ptr1;
    int mem_size;

    if (argc < 2)// If there aren't command-line arguments,
        mem_size = 50; // use 50 as the default value.
    else
        mem_size = atoi(argv[1]);

    printf("\t[+] allocating %d bytes of memory on the heap for char_ptr\n", mem_size);
    char_ptr = (char *) malloc(mem_size); // Allocating heap memory

    if(char_ptr == NULL) { // Error checking, in case malloc() fails
        fprintf(stderr, "Error: could not allocate heap memory.\n");
    exit(-1);
    }

    strcpy(char_ptr, "This is memory is located on the heap.");
    printf("char_ptr (%p) --> '%s'\n", char_ptr, char_ptr);

    printf("\t[+] allocating 12 bytes of memory on the heap for int_ptr\n");
    int_ptr = (int *) malloc(12); // Allocated heap memory again

    if(int_ptr == NULL) { // Error checking, in case malloc() fails
        fprintf(stderr, "Error: could not allocate heap memory.\n");
        exit(-1);
    }

    *int_ptr = 31337; // Put the value of 31337 where int_ptr is pointing.
    printf("int_ptr (%p) --> %d\n", int_ptr, *int_ptr);


    printf("\t[-] freeing char_ptr's heap memory...\n");
    free(char_ptr); // Freeing heap memory

    printf("\t[+] allocating another 15 bytes for char_ptr\n");
    char_ptr1 = (char *) malloc(15); // Allocating more heap memory

    if(char_ptr == NULL) { // Error checking, in case malloc() fails
        fprintf(stderr, "Error: could not allocate heap memory.\n");
        exit(-1);
    }
    else printf("succeded in allocation, [pointer] %p\n", char_ptr);


    strcpy(char_ptr1, "new memory");
    printf("char_ptr (%p) --> '%s'\n", char_ptr1, char_ptr1);

    printf("\t[-] freeing int_ptr's heap memory...\n");
    free(int_ptr); // Freeing heap memory
    printf("\t[-] freeing char_ptr's heap memory...\n");
    free(char_ptr1); // Freeing the other block of heap memory
}

So, if I allocate a rather large memoryspace for the char_ptr it works well.

But what confuses me, is that for small values it doesn't work. I get the value: error: "free() invalid next size(fast)".

From what I've read in other posts, this occures when one wants to free memory that has not been allocated, which is not the case in my example.

So in what way is the allocation of char_ptr related to char_ptr1's freeing ?

nemo
  • 25
  • 1
  • 10
  • 5
    after freeing `char_ptr`, you are mixing `char_ptr` and `char_ptr1`, but `char_ptr` points to invalid memory because of the free before – mch Jun 18 '14 at 11:56
  • when you malloc for the int_ptr, you probably want to malloc 12 * sizeof(int). – Vicky Jun 18 '14 at 11:59
  • Run your program using a debugger to learn where it crashes. – alk Jun 18 '14 at 11:59
  • Manül: in what way to you mean mixing them up? I saw that I mixed them up in the printf() but that shouldnt be an issue, right? – nemo Jun 18 '14 at 12:15
  • Possible duplicate of [Error: free(): invalid next size (fast):](https://stackoverflow.com/questions/4729395/error-free-invalid-next-size-fast) – Raedwald Nov 22 '18 at 09:06
  • The problem for both questions was a different one. Also this question is already solved. Why mark it as duplicate now after that many years?? for real though – nemo Nov 23 '18 at 12:59

3 Answers3

3

If you allocate only a small buffer, code like

strcpy(char_ptr, "This is memory is located on the heap.");

may overflow the allocated area (you need to allocate a buffer of at least size 39 bytes for this string). In particular, you might by overwriting parts of the internal data structures used by malloc itself to keep track of the allocations. Make sure, that the malloc'ed space is large enough to accomodate all the data you put into it.

Similar problems may occur with the int_ptr. Your size of 12 is odd but should be safe (on "common" machines). Better, though, would be:

int_ptr = malloc(sizeof(int));
Dirk
  • 30,623
  • 8
  • 82
  • 102
  • 1
    "*only small*" here exactly means with less then `strlen("This is memory is located on the heap.") + 1` characters. – alk Jun 18 '14 at 12:02
  • Yeah true, haven't thought about it^^'. But it works even if I only allcoate 25 bytes instead of at least 39. It crashes when i allocate less than 25 – nemo Jun 18 '14 at 12:14
  • @nemo since it's undefined behaviour what happens when you overflow a buffer, anything could happen. It could appear to work, but cause severe errors elsewhere, it could crash, etc. – nos Jun 18 '14 at 13:01
0

If you write more data than you allocated room for, you get undefined behavior.

unwind
  • 391,730
  • 64
  • 469
  • 606
0

A bit of background.

In general malloc receives an argument that tells him how many space you wish to allocate and returns you the pointer to this memory block.

type * var = malloc(sizeof(type) * length);

type can be any type that you wish to be allocated on the heap, int, char etc.

Let's look at your code. This line for example:

char_ptr = (char *) malloc(mem_size); // Allocating heap memory

Here you want to allocate an array of characters with lenght = mem_size. This code is valid because sizeof(char) is 1. It requires 1 byte to store a character.

However, a better way of writting this would be:

char_ptr = malloc(sizeof(char) * mem_size); // Allocating heap memory

This feels better and you stick to the same format eventhough the sizeof(char) is redundant in a way. Also, do not cast the outcome of a malloc operation. Leave this to be promoted to you specified type. See this post here.

Back to your question:

So in what way is the allocation of char_ptr related to char_ptr1's freeing ?

It is not in this case. I feel you mixed up the guard pointer, being char_ptr instead of the just allocated char_ptr1.

     |
     v

if(char_ptr1 == NULL) { // Error checking, in case malloc() fails
    fprintf(stderr, "Error: could not allocate heap memory.\n");
    exit(-1);
}
Community
  • 1
  • 1
Montaldo
  • 863
  • 8
  • 16