First, a word about memory protection. Modern operating systems provide the means to control access to the memory system. A user process should not be allowed to modify its read-only text section. It should not be allowed to read or modify any of the code and data structures in the kernel. It should not be allowed to read or write the private memory of other processes. And it should not be allowed to modify any virtual pages that are shared with other processes unless all parties explicitly allow it (via calls to explicit interprocess communication system calls). Each process usually has its own private virtual memory space, which translates to disjoint or safely shareable physical memory pages.
Remember that in virtual memory systems, we have a Page Table, which contains Page Table Entries (PTEs). A page table entry contains the base address of a physical page in DRAM, or an allocated page on the desk.
Enough of Virtual Memory. The operating system adds three permission bits to PTE entries, called SUP (supervisor), Read, Write bits, and they correspond to root, read, and write privliges respectively. If during the address translation the calling process violates any of those priviliges, it'll generate a protection fault (i.e., segmentation fault)....
Take this example
p = (char*) 0;
c = *p; //generates seg fault
The line at (1) generates a seg fault because it is trying to read location zero, and when the OS checks, it can't find a page allocated at location 0, and generates a segmentation fault.
p.s. This was a really crude descrition, so don't rely on it completely.... Should allow you to google it better, at the very least.
2- How do you detect if an overflow happened in adding two unsigned integers?
If the result is less than any of the operands, an overflow has occured in the case of unsigned addition. If both x and y less than 2^w (where w is the number of bits, we have no overflow). But s = x + y ==> s >= x (or y). So if s is less than x, or s is less than y, then we have an overflow. This is because in case of an overflow, s = x + y - 2^w (wraps around). THis is because we had a carry on of one, which we can't store, so we decrement the sum by 2^w. And since y < 2^w, y - 2^w < 0, which means s < x, hence overflow occured.
3- I get a stack overflow error at run time, but I can't spot any large stack allocations?
C++ allows you to delcare variables anywhere in the code (almost), unlike C which only allows you to delcare variables at the beginning of a block of instructions. So check large array allocations in the middle of your function/block. For example:
//after tens of lines of code
What the compiler did was to inspect your code first, push all local variables on the stack, regardless of where they were declared, then start the executing the first instruction in the function. If you're stepping through a debugger, you won't be able to spot the problem because it'll crash at the opening brace.