不使用memcpy实现realloc报无效指针错误,求代码排查及拷贝方案
故障原因
- 头部指针计算错误:内存块头部存储在返回给用户的指针
ptr的低地址方向(即ptr - WORD_SIZE位置),你在计算新块头部时用了UNSCALED_POINTER_ADD(newPtr, WORD_SIZE),相当于跑到了新块payload区域的高地址,操作的根本不是合法的头部结构,后续对newBlockInfo->next的访问直接越界。 - 拷贝长度逻辑错误:你重新将
ptrSize赋值为新块的大小,正确逻辑应该是取旧块有效大小、新申请size的较小值作为拷贝长度,否则旧块小于新块时会读到旧块以外的非法内存。 - 拷贝逻辑完全错位:你循环中一直在拷贝块管理结构体的
sizeAndTags字段,还不断修改新旧块的next指针,完全没有拷贝用户实际的payload数据;且next是内存池管理用的链表指针,直接拷贝会彻底破坏新块的管理结构,必然触发指针异常。 - 缺malloc返回值校验:调用
malloc(size)后没有判断返回值是否为NULL,内存分配失败时后续操作全是空指针访问。
无原生拷贝函数的payload传输实现
不需要调用memcpy等原生函数,直接将两个payload指针转换为unsigned char *类型,逐字节循环拷贝即可,逻辑和memcpy底层实现一致。
修正后的完整实现代码
void* realloc(void* ptr, size_t size) { BlockInfo * oldBlockInfo; size_t oldSize; void* newPtr; size_t copySize; unsigned char *src, *dst; if(ptr == NULL){ return malloc(size); } if(size == 0){ free(ptr); return NULL; } // 取旧块信息 oldBlockInfo = (BlockInfo*) UNSCALED_POINTER_SUB(ptr, WORD_SIZE); oldSize = SIZE(oldBlockInfo->sizeAndTags); // 旧块足够大直接返回 if (oldSize >= size){ return ptr; } // 申请新块,加空指针校验 newPtr = malloc(size); if(newPtr == NULL){ return NULL; } // 计算实际要拷贝的大小 copySize = oldSize < size ? oldSize : size; // 逐字节拷贝payload,不需要调用任何原生拷贝函数 src = (unsigned char *)ptr; dst = (unsigned char *)newPtr; for(size_t i = 0; i < copySize; i++){ dst[i] = src[i]; } // 释放旧块返回新指针 free(ptr); return newPtr; }
内容的提问来源于stack exchange,提问作者Killerbee
相关产品推荐
相关产品推荐

