Reputation: 239
I'm currently taking an introductory CS course that uses C. My textbook seems to imply that a pointer variable still holds the address for memory previously allocated to it, even after free() was called on it -- assume I previously used malloc(). Does this mean that portions of memory become "locked" when malloc() is called so the data of my pointer remains constant? What prevents other processes -- say google chrome or some app -- from messing with my variable? I could easily assign a value to an array at an invalid index, causing things to break. I could also access memory improperly, again using an array at an invalid index, giving me garbage or, if I'm really really lucky, a value that is meaningful to me. What is preventing a computer from spiraling into chaos!
Upvotes: 4
Views: 265
Reputation: 47962
Here's one way of thinking about it. Let's think of computer memory as being divided up into "pages". Let's imagine that each "page" is an actual sheet of paper, that we write numbers on in pencil. Let's imagine that all the pages that our program uses are stored in a filing cabinet, from page 0 up to page N. Let's imagine that we have some easy way of keeping track of which pages in the filing cabinet are in use -- perhaps we fold over the top corner, or something. Finally, let's imagine that paper is somewhat precious: we never actually throw a piece of it away. When we need some new memory, it's worth it to find an existing page that's not in use, and erase whatever's on it, and use it again.
With that analogy in mind, we can answer your questions.
My textbook seems to imply that a pointer variable still holds the address for memory previously allocated to it.
Right. When we "free" a page of memory, we just fold the upper corner (or whatever). But we don't erase the page yet, because there's no need to (that would be inefficient). We wait until someone else allocates the page later to erase it and write new numbers on it.
What prevents other processes -- say google chrome or some app -- from messing with my variable?
Based on the analogy I've developed so far, nothing does. If, in fact, all the programs on your computer accessed memory directly, there would be nothing keeping them from messing with each other's memory, and badly. So that's why most computers do not in fact rig things up so that ordinary programs access memory directly.
Instead, just about all general-purpose computers today incorporate a memory management unit (typically implementing virtual memory). The upshot is that each program gets its own filing cabinet. A program can mess around with all the pages in its filing cabinet, it can use them correctly or incorrectly and confuse itself and crash if it really wants to, but there is simply no way for a program to do anything with the pages in any other program's filing cabinet. It can't even peek at them, let alone write to them.
Upvotes: 1
Reputation: 133929
What is preventing a computer from spiraling into chaos!
The modern processors have a mode of operation called protected mode with virtual memory - a normal program (process) runs in so-called user-mode, and sees a memory space distinct from other currently running processes. The operating system then makes sure that all such misbehaviour is contained within one such process - while it is probable that such access would cause a crash, it would be contained into just this one process.
This wasn't true in older versions of Windows - while the Windows 3 could use the x86 protected mode, it ran all programs under the same privilege level - there the dreaded Blue Screen of Death might have taken the whole system down:
As for the part that
My textbook seems to imply that a pointer variable still holds the address for memory previously allocated to it, even after free() was called on it -- assume I previously used malloc().
This isn't actually strictly true. The C standard specifically says that after free
is called on a pointer, the value of the pointer itself becomes indeterminate. It might still point to the same address on your implementation, but all bets are off. The following program might even crash on some platform:
void *ptr = malloc(42);
free(ptr);
// some other code that is between here...
if (ptr) {
...
}
As the C standard says at 6.2.4p2
The value of a pointer becomes indeterminate when the object it points to (or just past) reaches the end of its lifetime.
And Appendix J.2. Undefined behavior:
The value of a pointer to an object whose lifetime has ended is used (6.2.4).
One possible behaviour could be caused by the compiler knowing that the value is not needed after free
. Thus if ptr
in the above code was stored in a register, the compiler is free to overwrite the value for some code in between there, and subsequently the variable ptr
could behave as it was an uninitialized value by the time it was used in the if
.
Using a pointer whose value is indeterminate will result in all sorts of funny behaviour, such as evidenced by this question here. The compiler need not produce the value that you'd expect, it just needs to conform to the standard.
In any case, the book is correct in that you're not to use the ptr
after free(ptr)
until you've set a new value to it, it is just that the specific example in the book is misleading as it is just one of the many possible outcomes, as is common for undefined behaviour in C.
Upvotes: 4
Reputation: 8414
What prevents other processes -- say google chrome or some app -- from messing with my variable?
All modern desktop / server OSes ensure that the memory space of one program cannot be accessed by any other program. This comes about largely from the configuration (managed by the OS) of the memory management unit in the CPU.
However, not all OSes do this. DOS didn't, largely because it was intended as a single process OS; TSR programs could access anything in the whole machine, including the foreground programs.
Some real time OSes such as VxWorks (particularly older variants) are multitasking, preemptive OSes, but do not provide any inter-process memory separation. The designers chose to do this to reduce the context switch times, something that's handy in a real time OS.
Upvotes: 1
Reputation: 54325
Way back in the 1970s there were computers used by more than one person. The other users hated it when one of them crashed the system. So they invented the virtual machine. Not like when you hear it now, or well, yeah kind of.
Virtual memory so that programs can all use address 0x4000000 at the same time. Virtual CPUs so that many programs can run on one CPU with time slicing. Virtual input and output devices.
All of that was invented 50 years ago in Multics, VMS, Unix, IBM OS/360, etc.
Upvotes: 4
Reputation: 726699
pointer variable still holds the address for memory previously allocated to it, even after
free()
was called on it
This is true. The situation is called "dangling pointer". Your program is not allowed to use these pointers; otherwise, its behavior is undefined.
Does this mean that portions of memory become "locked" when malloc() is called so the data of my pointer remains constant?
They are locked only in the sense that malloc
would not return the allocated range to your program again, until you free
it. There is no built-in protection, though: if your program accidentally writes to a freed pointer, it may overwrite data in a legitimate variable, leading to errors that are extremely hard to catch without proper tools.
What prevents other processes -- say google chrome or some app -- from messing with my variable?
The fact that other apps run in separate memory space. Hardware and OS ensure that other processes are locked out from the memory space of your program.
Upvotes: 6