k = new char*;
This allocated storage for only a single char*
.
*(k + 1) = k2;
This tries to pretend there are two char*
s allocated. This may not be the site of the segfault, but it is the error.
delete [] (k + 1);
Here you're trying to delete[]
something you did not new[]
, 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 to operator new(sizeof(char*))
. Let's say the OS allocates a new 4K page of physical RAM for that at address 0x12340000
. The memory manager needs a small structure in there to keep track of the block, something like:
struct mem_block_info {
void* next_block;
size_t block_size;
};
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 of 0x12340008
, since sizeof(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 another char*
. That header goes at the address right past the end of your allocated block, 0x1234000C
. Once the dust settles, that new char*
has put this in memory:
Address Data
0x12340000 0x00000000
0x12340004 0x00000001
0x12340008 uninitialized; could be anything
0x1234000C 0x00000000
0x12340010 0x00000FF4
The null pointers indicate the end of the allocated and free block linked lists.
So when you do:
*(k + 1) = k2;
k + 1 == 0x1234000C
is the next_block
pointer 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 the next_block
from there which is an invalid address, and boom, segfault.