堆是以下定义的结构的链接列表:
struct block
{
/*header + block*/
bool freeSpace;
block * prev;
block * next;
size_t size;
char block_part[];
};
我正在研究以下案例:
如果我找到的第一个内存块太大,以至于它可以容纳新分配的内存 另外,块和另一个块,然后块被分成两部分;一个块来举行新的 已分配的块和剩余空闲块。
(请注意,如果它比我需要的大一点,但不大 足够一个新的块(即它不足以容纳新块的元数据),我将在块的末尾有未使用的空间。)
我的代码如下。当我特意测试这个案例时,我的程序崩溃了一个段错误。有人能看出问题是什么吗?感谢。
do{
if (ptr -> freeSpace && ptr -> size >= size){
/*first suffient free block is found*/
ptr -> freeSpace = false;
if (ptr -> size > size + sizeof(struct block)){
/*if big enought for 'size' AND metadata of a new block, split the block*/
struct block * returnPtr = memset((ptr -> block_part), 0, size);
struct block * added = returnPtr + size;
added -> size = ptr -> size - size - sizeof(struct block);
added -> freeSpace = true;
added -> prev = ptr;
added -> next = ptr -> next;
(ptr -> next) -> prev = added;
ptr -> next = added;
ptr -> size = size;
return returnPtr;
}
ptr -> size = size;
return memset((ptr -> block_part), 0, size);
}
prevPtr = ptr;
ptr = ptr -> next;
}while (ptr);
答案 0 :(得分:2)
Memset返回void *
。它没有发出警告,因为编译器会自动生成void指针(例如malloc
(非)强制转换。
struct block *returnPtr = memset((ptr->block_part), 0, size);
为什么你会为一个包含多个成员的整个结构浪费内存来存储指向字符的void指针?
之后,您使用 now void指针的地址并将其移动size
- 向前移动数字。然后将其视为已分配的结构。这导致added
根本没有被分配(如果size
大于strlen(ptr->block_part)+1
你已经在其他人的记忆中)或者至少违反了记忆。访问这样的存储器会产生错误的程序。
因此,您观察到分段错误并编程崩溃。
注意:到目前为止,我还没有看到有人以这种方式使用memset
返回值。