Beginning C Student - How does free() affect the memory address on the heap?

The name of the pictureThe name of the pictureThe name of the pictureClash Royale CLAN TAG#URR8PPP











up vote
6
down vote

favorite












This assignment asks us to allocate two int-type variables using malloc() (named var1 and var2), print the addresses of each variable (the address of the pointer on the stack and the address on the heap), then use free() to deallocate var1, print the addresses again, then allocate another space in the heap for var1 and print the addresses a third time. I believe that the instructor is trying to show us that the heap address for var1 is supposed to change, but it always stays the same... unless I remove free(var1) from the code. The instructor did a similar demonstration, but did not use free() to deallocate any variables, so we never saw how this was supposed to work.



Here is my code:



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

void main()


int *var1 = (int*)malloc(sizeof(int));
*var1 = 1000;
int *var2 = (int*)malloc(sizeof(int));
*var2 = 2000;

printf("Addresses of var1n");
printf("Pointer on stack: %p / Heap: %pnn", &var1, var1);
printf("Addresses of var2n");
printf("Pointer on stack: %p / Heap: %pnn", &var2, var2);

free(var1);

printf("AFTER DEALLOCATING var1 FROM THE HEAPn");
printf("Addresses of var1n");
printf("Pointer on stack: %p / Heap: %pnn", &var1, var1);
printf("Addresses of var2n");
printf("Pointer on stack: %p / Heap: %pnn", &var2, var2);

var1 = (int*) malloc(sizeof(int));
*var1 = 1500;

printf("NEW MEMORY ADDRESS ALLOCATED FOR var1n");
printf("Addresses of var1n");
printf("Pointer on stack: %p / Heap: %pnn", &var1, var1);
printf("Addresses of var2n");
printf("Pointer on stack: %p / Heap: %pnn", &var2, var2);




This code results in this output:



Addresses of var1
Pointer on stack: 0xffffcbf8 / Heap: 0x600000390

Addresses of var2
Pointer on stack: 0xffffcbf0 / Heap: 0x6000003b0

AFTER DEALLOCATING var1 FROM THE HEAP
Addresses of var1
Pointer on stack: 0xffffcbf8 / Heap: 0x600000390

Addresses of var2
Pointer on stack: 0xffffcbf0 / Heap: 0x6000003b0

NEW MEMORY ADDRESS ALLOCATED FOR var1
Addresses of var1
Pointer on stack: 0xffffcbf8 / Heap: 0x600000390

Addresses of var2
Pointer on stack: 0xffffcbf0 / Heap: 0x6000003b0


As you can see, the heap address does not change for var1 when I deallocate it, and it doesn't change when I allocate memory space for var1 again. However, if I simply remove the free(var1) line from the program, it simply assigns a second memory space for var1 and points to that on the heap, which DOES have a different memory address:



Addresses of var1 
Pointer on stack: 0xffffcbf8 / Heap: 0x600000390

Addresses of var2
Pointer on stack: 0xffffcbf0 / Heap: 0x6000003b0

AFTER DEALLOCATING var1 FROM THE HEAP
Addresses of var1
Pointer on stack: 0xffffcbf8 / Heap: 0x600000390

Addresses of var2
Pointer on stack: 0xffffcbf0 / Heap: 0x6000003b0

NEW MEMORY ADDRESS ALLOCATED FOR var1
Addresses of var1
Pointer on stack: 0xffffcbf8 / Heap: 0x600000420

Addresses of var2
Pointer on stack: 0xffffcbf0 / Heap: 0x6000003b0


(Just to be clear, all I did was remove free(var1) from the previous code, so the "AFTER DEALLOCATING var1" section now shows the exact same heap address as the previous set, but it DOES change the heap address of var1 in the third section.)



Can anybody tell me what is happening here? The only logical explanation I can come up with is that when I'm using free() to deallocate var1 and then printing the address, it's simply printing the LAST address that it pointed to, and then when I'm allocating memory for var1 the second time, it's simply "backfilling" the previous address with the new value of var1. Does this make sense? Do I have errors in my code, or is this just how C behaves when deallocating memory for a variable and then reallocating it?










share|improve this question









New contributor




Firelion is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.















  • 1




    1. free() takes a pointer which you might provide with a variable. However, it doesn't change the contents of that variable. (Pointer is given by value to free().) 2. If you free() N bytes and later (rather immediately) malloc() N bytes again, why shouldn't you get the same address? Sounds, like heap management does a good job - it is re-using the free space of sufficient size. ;-)
    – Scheff
    6 hours ago






  • 2




    It makes perfect sense for a malloc implementation to reuse space for a new object of the same size.
    – John Bode
    6 hours ago










  • Hey there. Not what you asking, but you don't need to cast the return value of malloc anymore. Also, I find useful to use int *var = malloc(sizeof *var) instead of int *var = malloc(sizeof(int)). That way I can change the type of var without the risk of forgetting to change it inside the malloc call (e.g. float *var = malloc(sizeof(int))).
    – ddz
    6 hours ago











  • You're basically right. The lesson here is that, even after freeing memory, you may still have variables pointing to that memory, despite the fact that you don't own it. These "dangling pointers" can cause lots of misery, and that's why it's considered good practice to clear such pointers, e.g. free(p);p=NULL;
    – Tim Randall
    4 hours ago














up vote
6
down vote

favorite












This assignment asks us to allocate two int-type variables using malloc() (named var1 and var2), print the addresses of each variable (the address of the pointer on the stack and the address on the heap), then use free() to deallocate var1, print the addresses again, then allocate another space in the heap for var1 and print the addresses a third time. I believe that the instructor is trying to show us that the heap address for var1 is supposed to change, but it always stays the same... unless I remove free(var1) from the code. The instructor did a similar demonstration, but did not use free() to deallocate any variables, so we never saw how this was supposed to work.



Here is my code:



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

void main()


int *var1 = (int*)malloc(sizeof(int));
*var1 = 1000;
int *var2 = (int*)malloc(sizeof(int));
*var2 = 2000;

printf("Addresses of var1n");
printf("Pointer on stack: %p / Heap: %pnn", &var1, var1);
printf("Addresses of var2n");
printf("Pointer on stack: %p / Heap: %pnn", &var2, var2);

free(var1);

printf("AFTER DEALLOCATING var1 FROM THE HEAPn");
printf("Addresses of var1n");
printf("Pointer on stack: %p / Heap: %pnn", &var1, var1);
printf("Addresses of var2n");
printf("Pointer on stack: %p / Heap: %pnn", &var2, var2);

var1 = (int*) malloc(sizeof(int));
*var1 = 1500;

printf("NEW MEMORY ADDRESS ALLOCATED FOR var1n");
printf("Addresses of var1n");
printf("Pointer on stack: %p / Heap: %pnn", &var1, var1);
printf("Addresses of var2n");
printf("Pointer on stack: %p / Heap: %pnn", &var2, var2);




This code results in this output:



Addresses of var1
Pointer on stack: 0xffffcbf8 / Heap: 0x600000390

Addresses of var2
Pointer on stack: 0xffffcbf0 / Heap: 0x6000003b0

AFTER DEALLOCATING var1 FROM THE HEAP
Addresses of var1
Pointer on stack: 0xffffcbf8 / Heap: 0x600000390

Addresses of var2
Pointer on stack: 0xffffcbf0 / Heap: 0x6000003b0

NEW MEMORY ADDRESS ALLOCATED FOR var1
Addresses of var1
Pointer on stack: 0xffffcbf8 / Heap: 0x600000390

Addresses of var2
Pointer on stack: 0xffffcbf0 / Heap: 0x6000003b0


As you can see, the heap address does not change for var1 when I deallocate it, and it doesn't change when I allocate memory space for var1 again. However, if I simply remove the free(var1) line from the program, it simply assigns a second memory space for var1 and points to that on the heap, which DOES have a different memory address:



Addresses of var1 
Pointer on stack: 0xffffcbf8 / Heap: 0x600000390

Addresses of var2
Pointer on stack: 0xffffcbf0 / Heap: 0x6000003b0

AFTER DEALLOCATING var1 FROM THE HEAP
Addresses of var1
Pointer on stack: 0xffffcbf8 / Heap: 0x600000390

Addresses of var2
Pointer on stack: 0xffffcbf0 / Heap: 0x6000003b0

NEW MEMORY ADDRESS ALLOCATED FOR var1
Addresses of var1
Pointer on stack: 0xffffcbf8 / Heap: 0x600000420

Addresses of var2
Pointer on stack: 0xffffcbf0 / Heap: 0x6000003b0


(Just to be clear, all I did was remove free(var1) from the previous code, so the "AFTER DEALLOCATING var1" section now shows the exact same heap address as the previous set, but it DOES change the heap address of var1 in the third section.)



Can anybody tell me what is happening here? The only logical explanation I can come up with is that when I'm using free() to deallocate var1 and then printing the address, it's simply printing the LAST address that it pointed to, and then when I'm allocating memory for var1 the second time, it's simply "backfilling" the previous address with the new value of var1. Does this make sense? Do I have errors in my code, or is this just how C behaves when deallocating memory for a variable and then reallocating it?










share|improve this question









New contributor




Firelion is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.















  • 1




    1. free() takes a pointer which you might provide with a variable. However, it doesn't change the contents of that variable. (Pointer is given by value to free().) 2. If you free() N bytes and later (rather immediately) malloc() N bytes again, why shouldn't you get the same address? Sounds, like heap management does a good job - it is re-using the free space of sufficient size. ;-)
    – Scheff
    6 hours ago






  • 2




    It makes perfect sense for a malloc implementation to reuse space for a new object of the same size.
    – John Bode
    6 hours ago










  • Hey there. Not what you asking, but you don't need to cast the return value of malloc anymore. Also, I find useful to use int *var = malloc(sizeof *var) instead of int *var = malloc(sizeof(int)). That way I can change the type of var without the risk of forgetting to change it inside the malloc call (e.g. float *var = malloc(sizeof(int))).
    – ddz
    6 hours ago











  • You're basically right. The lesson here is that, even after freeing memory, you may still have variables pointing to that memory, despite the fact that you don't own it. These "dangling pointers" can cause lots of misery, and that's why it's considered good practice to clear such pointers, e.g. free(p);p=NULL;
    – Tim Randall
    4 hours ago












up vote
6
down vote

favorite









up vote
6
down vote

favorite











This assignment asks us to allocate two int-type variables using malloc() (named var1 and var2), print the addresses of each variable (the address of the pointer on the stack and the address on the heap), then use free() to deallocate var1, print the addresses again, then allocate another space in the heap for var1 and print the addresses a third time. I believe that the instructor is trying to show us that the heap address for var1 is supposed to change, but it always stays the same... unless I remove free(var1) from the code. The instructor did a similar demonstration, but did not use free() to deallocate any variables, so we never saw how this was supposed to work.



Here is my code:



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

void main()


int *var1 = (int*)malloc(sizeof(int));
*var1 = 1000;
int *var2 = (int*)malloc(sizeof(int));
*var2 = 2000;

printf("Addresses of var1n");
printf("Pointer on stack: %p / Heap: %pnn", &var1, var1);
printf("Addresses of var2n");
printf("Pointer on stack: %p / Heap: %pnn", &var2, var2);

free(var1);

printf("AFTER DEALLOCATING var1 FROM THE HEAPn");
printf("Addresses of var1n");
printf("Pointer on stack: %p / Heap: %pnn", &var1, var1);
printf("Addresses of var2n");
printf("Pointer on stack: %p / Heap: %pnn", &var2, var2);

var1 = (int*) malloc(sizeof(int));
*var1 = 1500;

printf("NEW MEMORY ADDRESS ALLOCATED FOR var1n");
printf("Addresses of var1n");
printf("Pointer on stack: %p / Heap: %pnn", &var1, var1);
printf("Addresses of var2n");
printf("Pointer on stack: %p / Heap: %pnn", &var2, var2);




This code results in this output:



Addresses of var1
Pointer on stack: 0xffffcbf8 / Heap: 0x600000390

Addresses of var2
Pointer on stack: 0xffffcbf0 / Heap: 0x6000003b0

AFTER DEALLOCATING var1 FROM THE HEAP
Addresses of var1
Pointer on stack: 0xffffcbf8 / Heap: 0x600000390

Addresses of var2
Pointer on stack: 0xffffcbf0 / Heap: 0x6000003b0

NEW MEMORY ADDRESS ALLOCATED FOR var1
Addresses of var1
Pointer on stack: 0xffffcbf8 / Heap: 0x600000390

Addresses of var2
Pointer on stack: 0xffffcbf0 / Heap: 0x6000003b0


As you can see, the heap address does not change for var1 when I deallocate it, and it doesn't change when I allocate memory space for var1 again. However, if I simply remove the free(var1) line from the program, it simply assigns a second memory space for var1 and points to that on the heap, which DOES have a different memory address:



Addresses of var1 
Pointer on stack: 0xffffcbf8 / Heap: 0x600000390

Addresses of var2
Pointer on stack: 0xffffcbf0 / Heap: 0x6000003b0

AFTER DEALLOCATING var1 FROM THE HEAP
Addresses of var1
Pointer on stack: 0xffffcbf8 / Heap: 0x600000390

Addresses of var2
Pointer on stack: 0xffffcbf0 / Heap: 0x6000003b0

NEW MEMORY ADDRESS ALLOCATED FOR var1
Addresses of var1
Pointer on stack: 0xffffcbf8 / Heap: 0x600000420

Addresses of var2
Pointer on stack: 0xffffcbf0 / Heap: 0x6000003b0


(Just to be clear, all I did was remove free(var1) from the previous code, so the "AFTER DEALLOCATING var1" section now shows the exact same heap address as the previous set, but it DOES change the heap address of var1 in the third section.)



Can anybody tell me what is happening here? The only logical explanation I can come up with is that when I'm using free() to deallocate var1 and then printing the address, it's simply printing the LAST address that it pointed to, and then when I'm allocating memory for var1 the second time, it's simply "backfilling" the previous address with the new value of var1. Does this make sense? Do I have errors in my code, or is this just how C behaves when deallocating memory for a variable and then reallocating it?










share|improve this question









New contributor




Firelion is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.











This assignment asks us to allocate two int-type variables using malloc() (named var1 and var2), print the addresses of each variable (the address of the pointer on the stack and the address on the heap), then use free() to deallocate var1, print the addresses again, then allocate another space in the heap for var1 and print the addresses a third time. I believe that the instructor is trying to show us that the heap address for var1 is supposed to change, but it always stays the same... unless I remove free(var1) from the code. The instructor did a similar demonstration, but did not use free() to deallocate any variables, so we never saw how this was supposed to work.



Here is my code:



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

void main()


int *var1 = (int*)malloc(sizeof(int));
*var1 = 1000;
int *var2 = (int*)malloc(sizeof(int));
*var2 = 2000;

printf("Addresses of var1n");
printf("Pointer on stack: %p / Heap: %pnn", &var1, var1);
printf("Addresses of var2n");
printf("Pointer on stack: %p / Heap: %pnn", &var2, var2);

free(var1);

printf("AFTER DEALLOCATING var1 FROM THE HEAPn");
printf("Addresses of var1n");
printf("Pointer on stack: %p / Heap: %pnn", &var1, var1);
printf("Addresses of var2n");
printf("Pointer on stack: %p / Heap: %pnn", &var2, var2);

var1 = (int*) malloc(sizeof(int));
*var1 = 1500;

printf("NEW MEMORY ADDRESS ALLOCATED FOR var1n");
printf("Addresses of var1n");
printf("Pointer on stack: %p / Heap: %pnn", &var1, var1);
printf("Addresses of var2n");
printf("Pointer on stack: %p / Heap: %pnn", &var2, var2);




This code results in this output:



Addresses of var1
Pointer on stack: 0xffffcbf8 / Heap: 0x600000390

Addresses of var2
Pointer on stack: 0xffffcbf0 / Heap: 0x6000003b0

AFTER DEALLOCATING var1 FROM THE HEAP
Addresses of var1
Pointer on stack: 0xffffcbf8 / Heap: 0x600000390

Addresses of var2
Pointer on stack: 0xffffcbf0 / Heap: 0x6000003b0

NEW MEMORY ADDRESS ALLOCATED FOR var1
Addresses of var1
Pointer on stack: 0xffffcbf8 / Heap: 0x600000390

Addresses of var2
Pointer on stack: 0xffffcbf0 / Heap: 0x6000003b0


As you can see, the heap address does not change for var1 when I deallocate it, and it doesn't change when I allocate memory space for var1 again. However, if I simply remove the free(var1) line from the program, it simply assigns a second memory space for var1 and points to that on the heap, which DOES have a different memory address:



Addresses of var1 
Pointer on stack: 0xffffcbf8 / Heap: 0x600000390

Addresses of var2
Pointer on stack: 0xffffcbf0 / Heap: 0x6000003b0

AFTER DEALLOCATING var1 FROM THE HEAP
Addresses of var1
Pointer on stack: 0xffffcbf8 / Heap: 0x600000390

Addresses of var2
Pointer on stack: 0xffffcbf0 / Heap: 0x6000003b0

NEW MEMORY ADDRESS ALLOCATED FOR var1
Addresses of var1
Pointer on stack: 0xffffcbf8 / Heap: 0x600000420

Addresses of var2
Pointer on stack: 0xffffcbf0 / Heap: 0x6000003b0


(Just to be clear, all I did was remove free(var1) from the previous code, so the "AFTER DEALLOCATING var1" section now shows the exact same heap address as the previous set, but it DOES change the heap address of var1 in the third section.)



Can anybody tell me what is happening here? The only logical explanation I can come up with is that when I'm using free() to deallocate var1 and then printing the address, it's simply printing the LAST address that it pointed to, and then when I'm allocating memory for var1 the second time, it's simply "backfilling" the previous address with the new value of var1. Does this make sense? Do I have errors in my code, or is this just how C behaves when deallocating memory for a variable and then reallocating it?







c malloc heap-memory free memory-address






share|improve this question









New contributor




Firelion is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.











share|improve this question









New contributor




Firelion is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.









share|improve this question




share|improve this question








edited 6 hours ago









Broman

5,68892241




5,68892241






New contributor




Firelion is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.









asked 6 hours ago









Firelion

311




311




New contributor




Firelion is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.





New contributor





Firelion is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.






Firelion is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.







  • 1




    1. free() takes a pointer which you might provide with a variable. However, it doesn't change the contents of that variable. (Pointer is given by value to free().) 2. If you free() N bytes and later (rather immediately) malloc() N bytes again, why shouldn't you get the same address? Sounds, like heap management does a good job - it is re-using the free space of sufficient size. ;-)
    – Scheff
    6 hours ago






  • 2




    It makes perfect sense for a malloc implementation to reuse space for a new object of the same size.
    – John Bode
    6 hours ago










  • Hey there. Not what you asking, but you don't need to cast the return value of malloc anymore. Also, I find useful to use int *var = malloc(sizeof *var) instead of int *var = malloc(sizeof(int)). That way I can change the type of var without the risk of forgetting to change it inside the malloc call (e.g. float *var = malloc(sizeof(int))).
    – ddz
    6 hours ago











  • You're basically right. The lesson here is that, even after freeing memory, you may still have variables pointing to that memory, despite the fact that you don't own it. These "dangling pointers" can cause lots of misery, and that's why it's considered good practice to clear such pointers, e.g. free(p);p=NULL;
    – Tim Randall
    4 hours ago












  • 1




    1. free() takes a pointer which you might provide with a variable. However, it doesn't change the contents of that variable. (Pointer is given by value to free().) 2. If you free() N bytes and later (rather immediately) malloc() N bytes again, why shouldn't you get the same address? Sounds, like heap management does a good job - it is re-using the free space of sufficient size. ;-)
    – Scheff
    6 hours ago






  • 2




    It makes perfect sense for a malloc implementation to reuse space for a new object of the same size.
    – John Bode
    6 hours ago










  • Hey there. Not what you asking, but you don't need to cast the return value of malloc anymore. Also, I find useful to use int *var = malloc(sizeof *var) instead of int *var = malloc(sizeof(int)). That way I can change the type of var without the risk of forgetting to change it inside the malloc call (e.g. float *var = malloc(sizeof(int))).
    – ddz
    6 hours ago











  • You're basically right. The lesson here is that, even after freeing memory, you may still have variables pointing to that memory, despite the fact that you don't own it. These "dangling pointers" can cause lots of misery, and that's why it's considered good practice to clear such pointers, e.g. free(p);p=NULL;
    – Tim Randall
    4 hours ago







1




1




1. free() takes a pointer which you might provide with a variable. However, it doesn't change the contents of that variable. (Pointer is given by value to free().) 2. If you free() N bytes and later (rather immediately) malloc() N bytes again, why shouldn't you get the same address? Sounds, like heap management does a good job - it is re-using the free space of sufficient size. ;-)
– Scheff
6 hours ago




1. free() takes a pointer which you might provide with a variable. However, it doesn't change the contents of that variable. (Pointer is given by value to free().) 2. If you free() N bytes and later (rather immediately) malloc() N bytes again, why shouldn't you get the same address? Sounds, like heap management does a good job - it is re-using the free space of sufficient size. ;-)
– Scheff
6 hours ago




2




2




It makes perfect sense for a malloc implementation to reuse space for a new object of the same size.
– John Bode
6 hours ago




It makes perfect sense for a malloc implementation to reuse space for a new object of the same size.
– John Bode
6 hours ago












Hey there. Not what you asking, but you don't need to cast the return value of malloc anymore. Also, I find useful to use int *var = malloc(sizeof *var) instead of int *var = malloc(sizeof(int)). That way I can change the type of var without the risk of forgetting to change it inside the malloc call (e.g. float *var = malloc(sizeof(int))).
– ddz
6 hours ago





Hey there. Not what you asking, but you don't need to cast the return value of malloc anymore. Also, I find useful to use int *var = malloc(sizeof *var) instead of int *var = malloc(sizeof(int)). That way I can change the type of var without the risk of forgetting to change it inside the malloc call (e.g. float *var = malloc(sizeof(int))).
– ddz
6 hours ago













You're basically right. The lesson here is that, even after freeing memory, you may still have variables pointing to that memory, despite the fact that you don't own it. These "dangling pointers" can cause lots of misery, and that's why it's considered good practice to clear such pointers, e.g. free(p);p=NULL;
– Tim Randall
4 hours ago




You're basically right. The lesson here is that, even after freeing memory, you may still have variables pointing to that memory, despite the fact that you don't own it. These "dangling pointers" can cause lots of misery, and that's why it's considered good practice to clear such pointers, e.g. free(p);p=NULL;
– Tim Randall
4 hours ago












3 Answers
3






active

oldest

votes

















up vote
9
down vote













It is perfectly normal that malloc might return the same addresses when memory is freed and then reallocated. It would also be normal for it to return different addresses.



If you change the malloc calls to request different sizes than the original allocations, you might get different addresses, since the old blocks malloc had prepared might not be enough for the new requests. But they might be enough, so the addresses might not change.



Incidentally:




  • void main() is incorrect. It should be int main(void).

  • Printing an address after the space it points to has been freed is not supported by the C standard. It is not uncommon for it to “work,” but it is not proper. C 2018 6.2.4 2 tells us “The value of a pointer becomes indeterminate when the object it points to (or just past) reaches the end of its lifetime.” When an object allocated with malloc is freed with free, its lifetime ends.





share|improve this answer






















  • Printing an address after the space it points to has been freed... Can't you print any address (as long as you don't access contents if it's not a valid address)?
    – Scheff
    6 hours ago










  • @Scheff: No. The C standard does not require pointers to be simply numeric addresses in a flat address space. Some C implementations use complicated addressing schemes (e.g,, segment and offset, and there are others), and these might require part of a pointer to be “active” in that it refers to some other address or register or structure that is dynamically set up. When space is freed, that other information may be deconstructed. Then, when printf attempts to format the pointer for %p, its attempt to use that information may fail.
    – Eric Postpischil
    6 hours ago










  • Thanks. I find this is an interesting point worth to be mentioned in your answer. It's a bit beyond "it's just a value that can be printed" and interesting for whom which are used to flat addresses without harm. (Segment/offset addressing reminds me to the ancient DOS on 8086 but even in that case, I cannot remember that printing an invalid address was anyhow dangerous.)
    – Scheff
    6 hours ago

















up vote
4
down vote













In the first example, the value of where the pointer used to point at the heap remains untouched at the stack after free(). But you can no longer access that address.



When they allocate the variable yet again, it is not strange that you get the same address, as there should be an available segment of the right size at that address. You are however not guaranteed to get the same one - which address that's the best pick from what's available is handled by the library code.






share|improve this answer



























    up vote
    3
    down vote














    The only logical explanation I can come up with is that when I'm using free() to deallocate var1 and then printing the address, it's simply printing the LAST address that it pointed to




    Kind of right. Freeing a pointer does not affect the content of the pointer at all. Or to be more precise, it's value is indeterminate after being freed. In fact, according to the standard you cannot even trust the pointer to contain the address it did before invoking free. As far as I know, it will in most cases, but you cannot trust it.



    The standard says:




    C 2018 6.2.4 2: “The value of a pointer becomes indeterminate when the object it points to (or just past) reaches the end of its lifetime.”




    A common mistake is to use the test if(ptr == NULL) as a check if you have properly freed the pointer. This will not work.






    share|improve this answer


















    • 3




      The C standard does not guarantee that “Freeing a pointer does not affect the content of the pointer at all.” After a pointer is passed to free, using its value has unspecified behavior.
      – Eric Postpischil
      6 hours ago











    • @EricPostpischil but how can free(pointer) change the value of pointer? Sure after freeing, that value is meaningless, but the bit pattern of pointer will remain. After all free is just a function call. But, yes, I can't think of a use case where that meaningless value could be used for anything useful.
      – Jabberwocky
      6 hours ago











    • @EricPostpischil free can't change the value of the pointer passed to it though. So it will remain the same value as it was before, previously valid and with no trap representations. The contents of that address can of course no longer be accessed, but that's another story. This appears to be yet another error in informative Annex J of the standard. There is no normative text saying that the pointer takes an indeterminate value or some such.
      – Lundin
      6 hours ago










    • @Jabberwocky: free cannot change the bytes that represent pointer, but it can change data structures that are used to organize memory and addressing. See my comment on my answer.
      – Eric Postpischil
      6 hours ago










    • @EricPostpischil Ah yeah you are correct, I read that wrong. You should add the quote to your answer.
      – Lundin
      6 hours ago










    Your Answer





    StackExchange.ifUsing("editor", function ()
    StackExchange.using("externalEditor", function ()
    StackExchange.using("snippets", function ()
    StackExchange.snippets.init();
    );
    );
    , "code-snippets");

    StackExchange.ready(function()
    var channelOptions =
    tags: "".split(" "),
    id: "1"
    ;
    initTagRenderer("".split(" "), "".split(" "), channelOptions);

    StackExchange.using("externalEditor", function()
    // Have to fire editor after snippets, if snippets enabled
    if (StackExchange.settings.snippets.snippetsEnabled)
    StackExchange.using("snippets", function()
    createEditor();
    );

    else
    createEditor();

    );

    function createEditor()
    StackExchange.prepareEditor(
    heartbeatType: 'answer',
    convertImagesToLinks: true,
    noModals: false,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: 10,
    bindNavPrevention: true,
    postfix: "",
    onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    );



    );






    Firelion is a new contributor. Be nice, and check out our Code of Conduct.









     

    draft saved


    draft discarded


















    StackExchange.ready(
    function ()
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f52951210%2fbeginning-c-student-how-does-free-affect-the-memory-address-on-the-heap%23new-answer', 'question_page');

    );

    Post as a guest






























    3 Answers
    3






    active

    oldest

    votes








    3 Answers
    3






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes








    up vote
    9
    down vote













    It is perfectly normal that malloc might return the same addresses when memory is freed and then reallocated. It would also be normal for it to return different addresses.



    If you change the malloc calls to request different sizes than the original allocations, you might get different addresses, since the old blocks malloc had prepared might not be enough for the new requests. But they might be enough, so the addresses might not change.



    Incidentally:




    • void main() is incorrect. It should be int main(void).

    • Printing an address after the space it points to has been freed is not supported by the C standard. It is not uncommon for it to “work,” but it is not proper. C 2018 6.2.4 2 tells us “The value of a pointer becomes indeterminate when the object it points to (or just past) reaches the end of its lifetime.” When an object allocated with malloc is freed with free, its lifetime ends.





    share|improve this answer






















    • Printing an address after the space it points to has been freed... Can't you print any address (as long as you don't access contents if it's not a valid address)?
      – Scheff
      6 hours ago










    • @Scheff: No. The C standard does not require pointers to be simply numeric addresses in a flat address space. Some C implementations use complicated addressing schemes (e.g,, segment and offset, and there are others), and these might require part of a pointer to be “active” in that it refers to some other address or register or structure that is dynamically set up. When space is freed, that other information may be deconstructed. Then, when printf attempts to format the pointer for %p, its attempt to use that information may fail.
      – Eric Postpischil
      6 hours ago










    • Thanks. I find this is an interesting point worth to be mentioned in your answer. It's a bit beyond "it's just a value that can be printed" and interesting for whom which are used to flat addresses without harm. (Segment/offset addressing reminds me to the ancient DOS on 8086 but even in that case, I cannot remember that printing an invalid address was anyhow dangerous.)
      – Scheff
      6 hours ago














    up vote
    9
    down vote













    It is perfectly normal that malloc might return the same addresses when memory is freed and then reallocated. It would also be normal for it to return different addresses.



    If you change the malloc calls to request different sizes than the original allocations, you might get different addresses, since the old blocks malloc had prepared might not be enough for the new requests. But they might be enough, so the addresses might not change.



    Incidentally:




    • void main() is incorrect. It should be int main(void).

    • Printing an address after the space it points to has been freed is not supported by the C standard. It is not uncommon for it to “work,” but it is not proper. C 2018 6.2.4 2 tells us “The value of a pointer becomes indeterminate when the object it points to (or just past) reaches the end of its lifetime.” When an object allocated with malloc is freed with free, its lifetime ends.





    share|improve this answer






















    • Printing an address after the space it points to has been freed... Can't you print any address (as long as you don't access contents if it's not a valid address)?
      – Scheff
      6 hours ago










    • @Scheff: No. The C standard does not require pointers to be simply numeric addresses in a flat address space. Some C implementations use complicated addressing schemes (e.g,, segment and offset, and there are others), and these might require part of a pointer to be “active” in that it refers to some other address or register or structure that is dynamically set up. When space is freed, that other information may be deconstructed. Then, when printf attempts to format the pointer for %p, its attempt to use that information may fail.
      – Eric Postpischil
      6 hours ago










    • Thanks. I find this is an interesting point worth to be mentioned in your answer. It's a bit beyond "it's just a value that can be printed" and interesting for whom which are used to flat addresses without harm. (Segment/offset addressing reminds me to the ancient DOS on 8086 but even in that case, I cannot remember that printing an invalid address was anyhow dangerous.)
      – Scheff
      6 hours ago












    up vote
    9
    down vote










    up vote
    9
    down vote









    It is perfectly normal that malloc might return the same addresses when memory is freed and then reallocated. It would also be normal for it to return different addresses.



    If you change the malloc calls to request different sizes than the original allocations, you might get different addresses, since the old blocks malloc had prepared might not be enough for the new requests. But they might be enough, so the addresses might not change.



    Incidentally:




    • void main() is incorrect. It should be int main(void).

    • Printing an address after the space it points to has been freed is not supported by the C standard. It is not uncommon for it to “work,” but it is not proper. C 2018 6.2.4 2 tells us “The value of a pointer becomes indeterminate when the object it points to (or just past) reaches the end of its lifetime.” When an object allocated with malloc is freed with free, its lifetime ends.





    share|improve this answer














    It is perfectly normal that malloc might return the same addresses when memory is freed and then reallocated. It would also be normal for it to return different addresses.



    If you change the malloc calls to request different sizes than the original allocations, you might get different addresses, since the old blocks malloc had prepared might not be enough for the new requests. But they might be enough, so the addresses might not change.



    Incidentally:




    • void main() is incorrect. It should be int main(void).

    • Printing an address after the space it points to has been freed is not supported by the C standard. It is not uncommon for it to “work,” but it is not proper. C 2018 6.2.4 2 tells us “The value of a pointer becomes indeterminate when the object it points to (or just past) reaches the end of its lifetime.” When an object allocated with malloc is freed with free, its lifetime ends.






    share|improve this answer














    share|improve this answer



    share|improve this answer








    edited 6 hours ago

























    answered 6 hours ago









    Eric Postpischil

    67.3k873146




    67.3k873146











    • Printing an address after the space it points to has been freed... Can't you print any address (as long as you don't access contents if it's not a valid address)?
      – Scheff
      6 hours ago










    • @Scheff: No. The C standard does not require pointers to be simply numeric addresses in a flat address space. Some C implementations use complicated addressing schemes (e.g,, segment and offset, and there are others), and these might require part of a pointer to be “active” in that it refers to some other address or register or structure that is dynamically set up. When space is freed, that other information may be deconstructed. Then, when printf attempts to format the pointer for %p, its attempt to use that information may fail.
      – Eric Postpischil
      6 hours ago










    • Thanks. I find this is an interesting point worth to be mentioned in your answer. It's a bit beyond "it's just a value that can be printed" and interesting for whom which are used to flat addresses without harm. (Segment/offset addressing reminds me to the ancient DOS on 8086 but even in that case, I cannot remember that printing an invalid address was anyhow dangerous.)
      – Scheff
      6 hours ago
















    • Printing an address after the space it points to has been freed... Can't you print any address (as long as you don't access contents if it's not a valid address)?
      – Scheff
      6 hours ago










    • @Scheff: No. The C standard does not require pointers to be simply numeric addresses in a flat address space. Some C implementations use complicated addressing schemes (e.g,, segment and offset, and there are others), and these might require part of a pointer to be “active” in that it refers to some other address or register or structure that is dynamically set up. When space is freed, that other information may be deconstructed. Then, when printf attempts to format the pointer for %p, its attempt to use that information may fail.
      – Eric Postpischil
      6 hours ago










    • Thanks. I find this is an interesting point worth to be mentioned in your answer. It's a bit beyond "it's just a value that can be printed" and interesting for whom which are used to flat addresses without harm. (Segment/offset addressing reminds me to the ancient DOS on 8086 but even in that case, I cannot remember that printing an invalid address was anyhow dangerous.)
      – Scheff
      6 hours ago















    Printing an address after the space it points to has been freed... Can't you print any address (as long as you don't access contents if it's not a valid address)?
    – Scheff
    6 hours ago




    Printing an address after the space it points to has been freed... Can't you print any address (as long as you don't access contents if it's not a valid address)?
    – Scheff
    6 hours ago












    @Scheff: No. The C standard does not require pointers to be simply numeric addresses in a flat address space. Some C implementations use complicated addressing schemes (e.g,, segment and offset, and there are others), and these might require part of a pointer to be “active” in that it refers to some other address or register or structure that is dynamically set up. When space is freed, that other information may be deconstructed. Then, when printf attempts to format the pointer for %p, its attempt to use that information may fail.
    – Eric Postpischil
    6 hours ago




    @Scheff: No. The C standard does not require pointers to be simply numeric addresses in a flat address space. Some C implementations use complicated addressing schemes (e.g,, segment and offset, and there are others), and these might require part of a pointer to be “active” in that it refers to some other address or register or structure that is dynamically set up. When space is freed, that other information may be deconstructed. Then, when printf attempts to format the pointer for %p, its attempt to use that information may fail.
    – Eric Postpischil
    6 hours ago












    Thanks. I find this is an interesting point worth to be mentioned in your answer. It's a bit beyond "it's just a value that can be printed" and interesting for whom which are used to flat addresses without harm. (Segment/offset addressing reminds me to the ancient DOS on 8086 but even in that case, I cannot remember that printing an invalid address was anyhow dangerous.)
    – Scheff
    6 hours ago




    Thanks. I find this is an interesting point worth to be mentioned in your answer. It's a bit beyond "it's just a value that can be printed" and interesting for whom which are used to flat addresses without harm. (Segment/offset addressing reminds me to the ancient DOS on 8086 but even in that case, I cannot remember that printing an invalid address was anyhow dangerous.)
    – Scheff
    6 hours ago












    up vote
    4
    down vote













    In the first example, the value of where the pointer used to point at the heap remains untouched at the stack after free(). But you can no longer access that address.



    When they allocate the variable yet again, it is not strange that you get the same address, as there should be an available segment of the right size at that address. You are however not guaranteed to get the same one - which address that's the best pick from what's available is handled by the library code.






    share|improve this answer
























      up vote
      4
      down vote













      In the first example, the value of where the pointer used to point at the heap remains untouched at the stack after free(). But you can no longer access that address.



      When they allocate the variable yet again, it is not strange that you get the same address, as there should be an available segment of the right size at that address. You are however not guaranteed to get the same one - which address that's the best pick from what's available is handled by the library code.






      share|improve this answer






















        up vote
        4
        down vote










        up vote
        4
        down vote









        In the first example, the value of where the pointer used to point at the heap remains untouched at the stack after free(). But you can no longer access that address.



        When they allocate the variable yet again, it is not strange that you get the same address, as there should be an available segment of the right size at that address. You are however not guaranteed to get the same one - which address that's the best pick from what's available is handled by the library code.






        share|improve this answer












        In the first example, the value of where the pointer used to point at the heap remains untouched at the stack after free(). But you can no longer access that address.



        When they allocate the variable yet again, it is not strange that you get the same address, as there should be an available segment of the right size at that address. You are however not guaranteed to get the same one - which address that's the best pick from what's available is handled by the library code.







        share|improve this answer












        share|improve this answer



        share|improve this answer










        answered 6 hours ago









        Lundin

        103k16151255




        103k16151255




















            up vote
            3
            down vote














            The only logical explanation I can come up with is that when I'm using free() to deallocate var1 and then printing the address, it's simply printing the LAST address that it pointed to




            Kind of right. Freeing a pointer does not affect the content of the pointer at all. Or to be more precise, it's value is indeterminate after being freed. In fact, according to the standard you cannot even trust the pointer to contain the address it did before invoking free. As far as I know, it will in most cases, but you cannot trust it.



            The standard says:




            C 2018 6.2.4 2: “The value of a pointer becomes indeterminate when the object it points to (or just past) reaches the end of its lifetime.”




            A common mistake is to use the test if(ptr == NULL) as a check if you have properly freed the pointer. This will not work.






            share|improve this answer


















            • 3




              The C standard does not guarantee that “Freeing a pointer does not affect the content of the pointer at all.” After a pointer is passed to free, using its value has unspecified behavior.
              – Eric Postpischil
              6 hours ago











            • @EricPostpischil but how can free(pointer) change the value of pointer? Sure after freeing, that value is meaningless, but the bit pattern of pointer will remain. After all free is just a function call. But, yes, I can't think of a use case where that meaningless value could be used for anything useful.
              – Jabberwocky
              6 hours ago











            • @EricPostpischil free can't change the value of the pointer passed to it though. So it will remain the same value as it was before, previously valid and with no trap representations. The contents of that address can of course no longer be accessed, but that's another story. This appears to be yet another error in informative Annex J of the standard. There is no normative text saying that the pointer takes an indeterminate value or some such.
              – Lundin
              6 hours ago










            • @Jabberwocky: free cannot change the bytes that represent pointer, but it can change data structures that are used to organize memory and addressing. See my comment on my answer.
              – Eric Postpischil
              6 hours ago










            • @EricPostpischil Ah yeah you are correct, I read that wrong. You should add the quote to your answer.
              – Lundin
              6 hours ago














            up vote
            3
            down vote














            The only logical explanation I can come up with is that when I'm using free() to deallocate var1 and then printing the address, it's simply printing the LAST address that it pointed to




            Kind of right. Freeing a pointer does not affect the content of the pointer at all. Or to be more precise, it's value is indeterminate after being freed. In fact, according to the standard you cannot even trust the pointer to contain the address it did before invoking free. As far as I know, it will in most cases, but you cannot trust it.



            The standard says:




            C 2018 6.2.4 2: “The value of a pointer becomes indeterminate when the object it points to (or just past) reaches the end of its lifetime.”




            A common mistake is to use the test if(ptr == NULL) as a check if you have properly freed the pointer. This will not work.






            share|improve this answer


















            • 3




              The C standard does not guarantee that “Freeing a pointer does not affect the content of the pointer at all.” After a pointer is passed to free, using its value has unspecified behavior.
              – Eric Postpischil
              6 hours ago











            • @EricPostpischil but how can free(pointer) change the value of pointer? Sure after freeing, that value is meaningless, but the bit pattern of pointer will remain. After all free is just a function call. But, yes, I can't think of a use case where that meaningless value could be used for anything useful.
              – Jabberwocky
              6 hours ago











            • @EricPostpischil free can't change the value of the pointer passed to it though. So it will remain the same value as it was before, previously valid and with no trap representations. The contents of that address can of course no longer be accessed, but that's another story. This appears to be yet another error in informative Annex J of the standard. There is no normative text saying that the pointer takes an indeterminate value or some such.
              – Lundin
              6 hours ago










            • @Jabberwocky: free cannot change the bytes that represent pointer, but it can change data structures that are used to organize memory and addressing. See my comment on my answer.
              – Eric Postpischil
              6 hours ago










            • @EricPostpischil Ah yeah you are correct, I read that wrong. You should add the quote to your answer.
              – Lundin
              6 hours ago












            up vote
            3
            down vote










            up vote
            3
            down vote










            The only logical explanation I can come up with is that when I'm using free() to deallocate var1 and then printing the address, it's simply printing the LAST address that it pointed to




            Kind of right. Freeing a pointer does not affect the content of the pointer at all. Or to be more precise, it's value is indeterminate after being freed. In fact, according to the standard you cannot even trust the pointer to contain the address it did before invoking free. As far as I know, it will in most cases, but you cannot trust it.



            The standard says:




            C 2018 6.2.4 2: “The value of a pointer becomes indeterminate when the object it points to (or just past) reaches the end of its lifetime.”




            A common mistake is to use the test if(ptr == NULL) as a check if you have properly freed the pointer. This will not work.






            share|improve this answer















            The only logical explanation I can come up with is that when I'm using free() to deallocate var1 and then printing the address, it's simply printing the LAST address that it pointed to




            Kind of right. Freeing a pointer does not affect the content of the pointer at all. Or to be more precise, it's value is indeterminate after being freed. In fact, according to the standard you cannot even trust the pointer to contain the address it did before invoking free. As far as I know, it will in most cases, but you cannot trust it.



            The standard says:




            C 2018 6.2.4 2: “The value of a pointer becomes indeterminate when the object it points to (or just past) reaches the end of its lifetime.”




            A common mistake is to use the test if(ptr == NULL) as a check if you have properly freed the pointer. This will not work.







            share|improve this answer














            share|improve this answer



            share|improve this answer








            edited 6 hours ago

























            answered 6 hours ago









            Broman

            5,68892241




            5,68892241







            • 3




              The C standard does not guarantee that “Freeing a pointer does not affect the content of the pointer at all.” After a pointer is passed to free, using its value has unspecified behavior.
              – Eric Postpischil
              6 hours ago











            • @EricPostpischil but how can free(pointer) change the value of pointer? Sure after freeing, that value is meaningless, but the bit pattern of pointer will remain. After all free is just a function call. But, yes, I can't think of a use case where that meaningless value could be used for anything useful.
              – Jabberwocky
              6 hours ago











            • @EricPostpischil free can't change the value of the pointer passed to it though. So it will remain the same value as it was before, previously valid and with no trap representations. The contents of that address can of course no longer be accessed, but that's another story. This appears to be yet another error in informative Annex J of the standard. There is no normative text saying that the pointer takes an indeterminate value or some such.
              – Lundin
              6 hours ago










            • @Jabberwocky: free cannot change the bytes that represent pointer, but it can change data structures that are used to organize memory and addressing. See my comment on my answer.
              – Eric Postpischil
              6 hours ago










            • @EricPostpischil Ah yeah you are correct, I read that wrong. You should add the quote to your answer.
              – Lundin
              6 hours ago












            • 3




              The C standard does not guarantee that “Freeing a pointer does not affect the content of the pointer at all.” After a pointer is passed to free, using its value has unspecified behavior.
              – Eric Postpischil
              6 hours ago











            • @EricPostpischil but how can free(pointer) change the value of pointer? Sure after freeing, that value is meaningless, but the bit pattern of pointer will remain. After all free is just a function call. But, yes, I can't think of a use case where that meaningless value could be used for anything useful.
              – Jabberwocky
              6 hours ago











            • @EricPostpischil free can't change the value of the pointer passed to it though. So it will remain the same value as it was before, previously valid and with no trap representations. The contents of that address can of course no longer be accessed, but that's another story. This appears to be yet another error in informative Annex J of the standard. There is no normative text saying that the pointer takes an indeterminate value or some such.
              – Lundin
              6 hours ago










            • @Jabberwocky: free cannot change the bytes that represent pointer, but it can change data structures that are used to organize memory and addressing. See my comment on my answer.
              – Eric Postpischil
              6 hours ago










            • @EricPostpischil Ah yeah you are correct, I read that wrong. You should add the quote to your answer.
              – Lundin
              6 hours ago







            3




            3




            The C standard does not guarantee that “Freeing a pointer does not affect the content of the pointer at all.” After a pointer is passed to free, using its value has unspecified behavior.
            – Eric Postpischil
            6 hours ago





            The C standard does not guarantee that “Freeing a pointer does not affect the content of the pointer at all.” After a pointer is passed to free, using its value has unspecified behavior.
            – Eric Postpischil
            6 hours ago













            @EricPostpischil but how can free(pointer) change the value of pointer? Sure after freeing, that value is meaningless, but the bit pattern of pointer will remain. After all free is just a function call. But, yes, I can't think of a use case where that meaningless value could be used for anything useful.
            – Jabberwocky
            6 hours ago





            @EricPostpischil but how can free(pointer) change the value of pointer? Sure after freeing, that value is meaningless, but the bit pattern of pointer will remain. After all free is just a function call. But, yes, I can't think of a use case where that meaningless value could be used for anything useful.
            – Jabberwocky
            6 hours ago













            @EricPostpischil free can't change the value of the pointer passed to it though. So it will remain the same value as it was before, previously valid and with no trap representations. The contents of that address can of course no longer be accessed, but that's another story. This appears to be yet another error in informative Annex J of the standard. There is no normative text saying that the pointer takes an indeterminate value or some such.
            – Lundin
            6 hours ago




            @EricPostpischil free can't change the value of the pointer passed to it though. So it will remain the same value as it was before, previously valid and with no trap representations. The contents of that address can of course no longer be accessed, but that's another story. This appears to be yet another error in informative Annex J of the standard. There is no normative text saying that the pointer takes an indeterminate value or some such.
            – Lundin
            6 hours ago












            @Jabberwocky: free cannot change the bytes that represent pointer, but it can change data structures that are used to organize memory and addressing. See my comment on my answer.
            – Eric Postpischil
            6 hours ago




            @Jabberwocky: free cannot change the bytes that represent pointer, but it can change data structures that are used to organize memory and addressing. See my comment on my answer.
            – Eric Postpischil
            6 hours ago












            @EricPostpischil Ah yeah you are correct, I read that wrong. You should add the quote to your answer.
            – Lundin
            6 hours ago




            @EricPostpischil Ah yeah you are correct, I read that wrong. You should add the quote to your answer.
            – Lundin
            6 hours ago










            Firelion is a new contributor. Be nice, and check out our Code of Conduct.









             

            draft saved


            draft discarded


















            Firelion is a new contributor. Be nice, and check out our Code of Conduct.












            Firelion is a new contributor. Be nice, and check out our Code of Conduct.











            Firelion is a new contributor. Be nice, and check out our Code of Conduct.













             


            draft saved


            draft discarded














            StackExchange.ready(
            function ()
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f52951210%2fbeginning-c-student-how-does-free-affect-the-memory-address-on-the-heap%23new-answer', 'question_page');

            );

            Post as a guest













































































            Popular posts from this blog

            How to check contact read email or not when send email to Individual?

            Displaying single band from multi-band raster using QGIS

            How many registers does an x86_64 CPU actually have?