【发布时间】:2021-01-20 19:21:46
【问题描述】:
我正在尝试为某个测验实现memmove() 函数,因此我在交换操作中动态分配了一块内存,其中 ptr 缓冲区作为临时持有者,并且交换在一个循环中完成。当我提交此代码时,它给了我 3 个测试用例中的一个错误答案。当我将交换分成两个 for 循环时,所有情况都成功。那么有什么区别呢?
-
在相同的循环中交换(一种情况错误):
uint8_t *my_memmove(uint8_t *src, uint8_t *dst, size_t length) { uint8_t *buffer; buffer = (uint8_t*)reserve_words(length); for (uint8_t i = 0; i < length; i++) { *(buffer+i) = *(src+i); *(dst+i) = *(buffer+i); } return dst; free_words((uint32_t*)buffer); } -
在两个循环中交换(所有情况都成功):
uint8_t *my_memmove(uint8_t *src, uint8_t *dst, size_t length) { uint8_t *buffer; buffer = (uint8_t*)reserve_words(length); for (uint8_t i = 0; i < length; i++) { *(buffer+i) = *(src+i); } for (uint8_t i = 0; i < length; i++) { *(dst+i) = *(buffer+i); } return dst; free_words((uint32_t*)buffer); } -
使用的reserve_words函数(用户定义):
int32_t *reserve_words(size_t length) { int32_t *ptr; ptr = (int32_t *)malloc(length * sizeof(int32_t)); return ptr; }
【问题讨论】:
-
考虑如果
src和dst有重叠区域会发生什么。 -
请注意,您会泄漏内存,因为您的
free()在您的return之后。由于您将长度乘以sizeof(int32_t),因此您还分配了四倍所需的内存。在使用分配的内存之前,您应该检查内存分配是否成功。 -
为什么你有
reserve_words函数而不是简单的malloc调用? -
@JonathanLeffler 没有可移植的方法来判断它们是否重叠,因为您无法比较不同数组之间的指针。
memmove()的真正实现并不受此限制。 -
@Barmar — 是的,这就是标准使用备用内存进行恶作剧的原因,但特定实现的库可以知道您是否可以便携式比较指针,尽管标准有限制,并且因此可以做出这样的决定。这就是为什么它是一个标准库函数——标准库是为特定的实现量身定制的。在大多数机器上,您可以进行这种比较——可能通过将地址转换为
uintptr_t值——但标准不保证它是可移植的(但实现知道它是安全的)。
标签: c pointers memory memory-management memmove