简体   繁体   中英

about malloc() and free() in C

I have the following C-code:

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

typedef struct node
{
    int a;
}node;

int main()
{
    node * n;

    printf("\n%d\n",n->a);

    n  = (node *) malloc ( sizeof( node ));

    printf("\n%d\n",n->a);
    n->a = 6;
    printf("\n%d\n",n->a);
    free(n);
    printf("\n%d\n",n->a);
    n->a = 4;
    printf("\n%d\n",n->a);
    return 0;
}

Output obtained is :

1314172

0

6

0

4

My question is even after free(n) , why does n->a = 0 and how can we also reassign it to any value like n->a = 4 ?

Doesn't free make the memory block pointed to by n invalid ??

free(n);
n->a = 4; // is not guaranteed to work, might crash on some implementations

Invokes Undefined Behaviour.

why does n->a = 0 and how can we also reassign it to any value like n->a = 4 ?

Thats because Undefined Behaviour means anything can happen. You can't rely on that.

PS : Don't write such code.

EDIT :

As Jonathan noticed your code invokes Undefined Behavior long before you free() and then dereference n .

node * n; //n is not initialized
printf("\n%d\n",n->a);  //dereferencing a wild pointer invokes UB.

Reusing a freed pointer is similar to making a copy of a key for a car you rented, returning the car, and then trying to use that key to get in the car after you have returned the car to the rental place. You might be able to get away with it, but you shouldn't be doing it and very often it will get you in trouble.

No, free may or may not do anything to the associated memory. Referencing it is invalid though. Other processes/your process may have overwritten the memory, or if you're unlucky, the data might be just as you'd left it.

It's up to you to make sure you don't reference free'd memory.

When you dereference a pointer to unallocated memory, the behaviour is undefined. This means that it could do anything. It might trigger an error, or it might do something else.

In most cases, if you free some memory, that memory is not immediately re-used, and is not immediately reclaimed by the Operating System. This means that the memory is still accessible to your application and will still contain its previous values. You can often read or write to it without errors, but you must not rely on this behaviour .

If you ran this code in a number of different environments, you would find that in some environments it always works, in some it always triggers an error, but that in many others it works 'most of the time'. This makes C quite difficult to debug! :)

the memory block is released. That doesnt mean that you cannot write to it; it means that you must not write to it. The machine will not stop you doing it (usually, there are some tools like electric fence that will prevent it)

As you will find in the future ; you will end up doing this accidentally a lot; and usually Bad Things (tm) will happen

On most operating systems targeted at hardware with an MMU (such as x86), the only way to actually get an error for a memory read is if the application address is unmapped. Since the MMU doesn't have an entry that tells it where to find in physical memory the data associated with the logical address the application asked for, it causes an interrupt and the operating system takes over, to do something about it.

But most operating systems don't do much to manage memory on behalf of the application, except to give it a contiguous chunk of memory of the desired size. The operating system doesn't allow the applications to muck about in the MMU, either, since most MMU's aren't quite smart enough to let applications do things safely without affecting other programs negatively (either by accident or malice).

So when you malloc() something, if your app doesn't already have a place to put that in its existing address space, it asks the operating system for more, but when you later free() it, unless that happens to be at the very end of the address space for your app, you can't give it back to the operating system to make that memory area cause an error when you try to read it.

There are some ways to get that, for instance, with mmap() , but that's not really the right reason to use that function.

Most of the OS will allocate a certain minimum space that will be equal to or greater than the space you requested. Once you call free, this space will not go back to the OS, instead kept with you for future reuse. Hence, you can get away with something like what you have written above.

But on a strict note, this is categorized as "Undefined" behavior. But you can get away with it most of the times. Just don't make a habit off it ;)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM