memcpy和memmove的区别
其实很早就知道两个函数其中有一个在面临内存覆盖时行为有点特别, 但是工作中很少用到此场景, 也就没有深究. 现在居然面试遇到了, 那就把研究清楚吧.
- memcpy 简单粗暴, 不考虑内存重叠问题. 后果程序员自负
- memmove 比memcpy多了层检查内存重叠的考虑,如果发现重叠, 则反向拷贝, 性能和memcpy基本一样. 就是多了个检查是否重叠的代码.
综上所述, 以后干脆就用memmove吧. 省的那么多事. 反正性能几乎没有损失.
测试代码:
1 | int main(int argc, char **args) |
输出结果如下:
1 | original str : hello world |
扩展阅读, memmove是如何实现的?
由于该函数比memcpy安全的一点在于要考虑内存是否重叠,如果重叠则反向copy避免还没有copy的地方被覆盖.
实现要点:
1) 检查是否内存重叠,如果没有重叠,则直接调用memcpy.
2) 如果重叠,则从src+len,到dst+len倒序copy.
此时不能利用memcpy,因为memcpy是正向copy的. 需要按照类似memcpy的实现,在汇编指令中把cld替换为std,把方向标记位改下即可.
内存重叠的含义是什么呢?
1)如果dst < src 则无论dst和src距离多远都没问题.
2)如果dst > src,并且两者的差值>=len, 则虽然dst在后面,因距离很远, 也没有重叠
3)如果dst > src 并且差值<len, 那么copy时则会重叠导致不可预测的结果.
glibc 2.17 的memmove源码如下
1 | rettype |