简体   繁体   中英

Freeing a pointer to a 'double' value

All of the stuff I could find referring to freeing 'double' pointers refers to freeing pointers to pointers, which is not what I am talking about. I already figured out how to do that.

It might not even be a big thing at all, but I noticed that when I free() an int , char , or float pointer, the value is removed or replaced with a garbage value, but when I free() a double pointer, the value remains the same.

Here's the code I tested this with:

int main()
{
  int *p_a = malloc(sizeof(int));
  *p_a = 1;

  char *p_b = malloc(sizeof(char));
  *p_b = 'b';

  float *p_c = malloc(sizeof(float));
  *p_c = 3.565;

  double *p_d = malloc(sizeof(double));
  *p_d = 7.77;

  printf("Before 'free()':\n");
  printf("A: %p\t%d\n", p_a, *p_a);
  printf("B: %p\t%c\n", p_b, *p_b);
  printf("C: %p\t%g\n", p_c, *p_c);
  printf("D: %p\t%g\n", p_d, *p_d);

  free(p_a);
  free(p_b);
  free(p_c);
  free(p_d);

  printf("\nAfter 'free()':\n");
  printf("A: %p\t%d\n", p_a, *p_a);
  printf("B: %p\t%c\n", p_b, *p_b);
  printf("C: %p\t%g\n", p_c, *p_c);
  printf("D: %p\t%g\n", p_d, *p_d);

  return 0;
}

This produced the following output:

Before 'free()':
A: 0x8f2e008    1
B: 0x8f2e018    b
C: 0x8f2e028    3.565
D: 0x8f2e038    7.77

After 'free()':
A: 0x8f2e008    0
B: 0x8f2e018
C: 0x8f2e028    1.46175e-33
D: 0x8f2e038    7.77

Is that normal? My understanding of how malloc() and free() work is that when you malloc() a pointer, you set aside some bytes of memory for the pointer to point to. This is put on the heap , where it cannot be accessed, and it will not come off the heap until it is free() d or a memory clean-up is triggered on the computer, which is not controlled by the user. So, when you free() a pointer, you basically get rid of the association between the pointer and the address it points to, allowing that memory to be used later on.

Given all that, why is the double pointer still pointing to the same value?

Now that I think about it, why do the pointers have an address at all after the free() s?

As I am a beginner to C , any and all wisdom and knowledge is much appreciated. Thank you for your time.

EDIT: After further testing and meddling, I found that if you enter a number that has more than 6 digits and rounds up on the last one (eg. 777.7777) for the double , after it is free() d it loses its rounding.

To illustrate:

Before 'free()':
D: 0x8f2e038    777.778

After 'free()':
D: 0x8f2e038    777.777

This supports @rodrigo's hypothesis (in the comments) that, because the double is 8 bytes - as opposed to int , char and float 's 4 bytes - free() only modifies the first 4 bytes, so it does not lose all of its data.

Thanks everyone for your help!

My understanding of how malloc() and free() work is that when you malloc() a pointer, you set aside some bytes of memory for the pointer to point to.

You don't malloc a pointer. You malloc a block of memory. The value returned by malloc is a pointer to that memory. So let's rephrase that.

My understanding of how malloc() and free() work is that when you malloc() a block of memory, you set aside some bytes of memory; the pointer returned points to the start of that block of memory.

Correct.

This [the memory block] is put on the heap

Correct; think of the heap as long-term random-access storage.

where it cannot be accessed

This is either wrong or nonsensical. Where what cannot be accessed, and by whom?

it [the block of memory] will not come off the heap until it is free()d

The memory block allocated by malloc is reserved for the use of your program until free is called. To free the block, you call free and pass the pointer that was originally returned from malloc , yes.

or a memory clean-up is triggered on the computer, which is not controlled by the user

This is again incoherent. Modern operating systems use virtual memory. When a process is destroyed the entire virtual address space vanishes.

when you free() a pointer, you basically get rid of the association between the pointer and the address it points to, allowing that memory to be used later on.

No no no no no. This is the crux of your misunderstanding.

You free a block of memory by passing the pointer that was originally returned by malloc to free. That frees the block of memory, and malloc is then allowed to hand it out again, should other code in your process ask for memory.

But free does NOT change what address the pointer points to! The pointer continues to point to an address; that address is now invalid! Dereferencing a pointer to invalid memory is called "undefined behaviour" in C, and literally anything can happen. Your program can crash. You can get the value that used to be there back. Your password can be emailed to hackers in a secret lair at the north pole. Anything can happen, so don't do that .

(Coincidentally I have earlier today written a blog article about this subject which will go up on Wednesday, so watch my blog for details.)

Given all that, why is the double pointer still pointing to the same value?

Undefined behaviour means that anything can happen. The pointer still pointing to the same value is something happening, and something happening is a subset of anything happening.

Now that I think about it, why do the pointers have an address at all after the free()s?

The pointer is stored in a variable. You didn't change the value of the variable. Variables keep their values until you change them.

Where can I read more?

This highly related question might be of interest to you.

Can a local variable's memory be accessed outside its scope?

That question is the same as yours, except in the given question the pointer is to the stack, not to the heap. But the logic is the same: dereferencing a pointer to a popped stack frame is undefined behaviour, just as dereferencing a pointer to a free'd block is undefined behaviour. Anything can happen.

Basically, once you free a pointer, you should not use the data it points to anymore.

malloc allocates for you some chunk of memory that you are responsible to write and read. That chunk 'belongs' to you, but it's only a rent!

After you free that chunk, it's back to the system. As said above, using that data is undefined behavior: expected result (as if no free), wrong result, crash...

As per the double issue , try to invert the freeing (D to A) and see what happens... (and anyway, malloc doesn't know you intend to put a double in that space).

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