int main() {
char** k;
k = new char*;
char* k1 = "abc";
char* k2 = "def";
*k = k1;
*(k + 1) = k2;
delete [] (k + 1);
}
Error: segmentation fault
Could someone explain why I get segmentation fault when freeing (k + 1)? I was able to free k with no problems.
ADD: In the answers it has been said that I can’t delete [] (k + 1) since I haven’t used new on it; But how do you explain the fact that cout<<*(k + 1)<<endl; printed correctly?
This allocated storage for only a single
char*.This tries to pretend there are two
char*s allocated. This may not be the site of the segfault, but it is the error.Here you’re trying to
delete[]something you did notnew[], another error.EDIT: Deep down, memory is allocated in large chunks, such as pages. So when you allocate a small bit of storage, it’s very likely that the memory around it is also valid. It’s still very invalid to access it, though.
More to the point, when you say something like
new char*, this turns into a call tooperator new(sizeof(char*)). Let’s say the OS allocates a new 4K page of physical RAM for that at address0x12340000. The memory manager needs a small structure in there to keep track of the block, something like:So it puts this structure at
0x12340000. Immediately after that, it puts the storage you requested, so (assuming this is a 32-bit machine) it returns a pointer of0x12340008, sincesizeof(void*) == sizeof(size_t) == 4. Then it needs to put a header after your storage to track the unused part of that 4K page, so it doesn’t waste memory by allocating another 4K page when you want anotherchar*. That header goes at the address right past the end of your allocated block,0x1234000C. Once the dust settles, thatnew char*has put this in memory:The null pointers indicate the end of the allocated and free block linked lists.
So when you do:
k + 1 == 0x1234000Cis thenext_blockpointer for the free block, and you just overwrote it with an invalid value (the address of a string in read-only memory, most likely). This does not immediately cause a segmentation fault, but when the memory manager tries to traverse the free block list, it will wind up looking at that string and misinterpreting it as a block header, then going to thenext_blockfrom there which is an invalid address, and boom, segfault.