Question about memory management and pointer owernship

Hello everyone,
I am trying to comprehend the concept of how pointers know who they are pointing at. For an example let's choose the stop and copy method used by Java. This method splits main memory into 2. Then copies memory from the active half and places it in the new half neatly so there is limited fragmentation, clearing up memory for future use. My question is this:

Why can't we do this in C++? I am under the impression that moving memory like this in C++ would leave the pointers we initially used, pointing at nothing. The reason for this is unknown to me. I don't understand why copying and moving this memory wouldn't create new pointers to go along with the copied memory and delete the old ones pointing at the old, fragmented memory we wanted to clean up.

Well, C/C++ isn't Java, so whatever Java can do isn't necessarily how C/C++ does things.

https://www.learncpp.com/cpp-tutorial/introduction-to-pointers/
In Java there are no pointers. In Java you have references to objects. And these Java objects live in the Java heap space and are "managed" by the JVM. In fact the JVM may move around the objects in the memory (heap space), but that is completely "transparent" to the Java application. If an object is "moved" by the JVM, it transparently updates all references to that object. The JVM also keeps track of how many references there are to a certain object. If no references are left to an object, the object is "dead" and will be removed from the heap space; not necessarily immediately, but the next time when the garbage collector runs.

In C/C++ you can allocate objects either on the stack or on the heap. If you allocate an object on the heap, by using the new operator or by using the malloc() function, then you get a pointer to that object. That pointer really is nothing but a "raw" memory address! Consequently, the object must not be moved around in memory, because that would obviously invalidate all pointers to that object! Again, pointers are just memory addresses. So, if the object was moved, the pointer would "know" nothing about that and still would be pointing to the "old" (now invalid) address it was pointing to before. Also, C/C++ has no garbage collector. You need to manually delete or free() memory that is no longer needed; otherwise you get memory leaks!

C/C++ objects allocated on the stack have "automatic storage duration". Such objects will be destroyed automatically/implicitly as soon as they go out of scope. AFAIK, Java has nothing like that.
Last edited on
I take the opposite view -- in Java, everything is a pointer :) (except primitive types)
I take the opposite view -- in Java, everything is a pointer :) (except primitive types)

In Java, everything that isn't a primitive type is an object. Java objects always live in the Java heap space. Variables do not "contain" objects; instead they store references to the actual objects (on the heap).

Whether these "references" are implemented as pointers (memory addresses), or as something else, that is an implementation detail of the specific JVM; and it is totally "transparent" to the application code. The way how "references" are implemented in Java can differ between different JVM implementations. It is very well possible that the JVM keeps the actual memory addresses of the Java objects in a global hash table and the references in your Java program are not "pointers" (memory addresses) but are indices into that hash table.

Anyhow, when the JVM moves an object around in the heap space, it has to make sure that all references to the object still work correctly and the program won't break. If references were implemented as pointers, the JVM would have to find all pointers pointing to the "moved" object and update them. If references are indices into a hash table, then the object's new address only needs to be updated at one place (the hash table).

In C/C++ memory management is way more "simple" – for the better or for the worse – so pointers are really just "raw" memory addresses, and objects (blocks of memory) allocated on the heap never move around – unless you explicitly realloc() them – because that obviously would break all existing pointers...
Last edited on
I am trying to comprehend the concept of how pointers know who they are pointing at


hardware. ram is like a giant array of bytes, and each byte has a location.
eg ram[number] is what was put there. When you get a pointer, the OS assures you that its usable (clean, not in use by others) and you stuff your data there. The pointer itself is just an integer, sorta kinda the index into ram. (this is a simplification; but its more or less conceptually correct; I am not sure all machines can address by bytes or if they do it by pages & offsets or some funky low level thing, but from your code/ c++ viewpoint, what I said is good enough here).


Why can't we do this in C++?

You can. You just need to do that manually, with the tools provided; its not automated probably for two reasons 1) raw pointer memory manipulation is avoided in all but the most performance critical code in modern c++ (we use c++ object containers like vector to do the bulk of this in most programs now) and 2) its pretty simple to do it yourself, we don't need more clutter to do things that are rarely done and when they are, are usually better hand-tuned than cookie cutter.


I don't understand why copying and moving this memory wouldn't create new pointers to go along with the copied memory and delete the old ones pointing at the old, fragmented memory we wanted to clean up.


well, you do it yourself.
1) create a new pointer variable destination and ask for memory for it. //your new pointers
2) copy the memory, probably with memcpy //the copy operation
3) delete the old pointers

C++ memory does not fragment 'naturally'. That is, a NEW statement gives you a block of memory and you can't fragment that. You can only fragment memory if you build a data structure that has multiple pointers, one for each chunk of memory, and that is a self inflicted problem that you chose in your design phase knowing that it would fragment.

linked lists, trees, and graphs can be written in a CLASSICAL style that fragments memory where each "NODE" has pointers to more nodes and they all get 'new' memory independent of each other. But you CAN write these data structures in a way to NOT do that; its just the classical school design that does this. Its very easy, using a vector, to avoid the fragmentation entirely. As a bonus, the vectorized list is going to serialize better because the "pointers" are no longer pointers but array index into a persistent offset so you can directly load and save without having extra code to reconstruct it. NOTHING IS FREE. If you used a vector to make a linked list object, it would have fewer page faults but it will still do the copy and move when it needs to grow in size and that is an expensive operation. It can be minimized, but it can't be totally avoided unless your data is static or has a maximum size etc.

arrays, vectors, pointer-blocks (new type[size]) are all non fragmented.

Memory fragmentation is a giant slowdown in high performance code and is a good thing to understand. C++ provides you the tools to deal with it for your program however you want, but that is hands-on unless you are satisfied with the way a container does it for you. Java ... I don't know what java does, but its sluggish when you get down and dirty with the memory management, it simply can't seem to keep up for that specific area. Its gotten to be a decently well performing language, but, ... not a lot of high end games are written in java. For a reason.
Last edited on
Topic archived. No new replies allowed.