C++内存重叠
内存重叠是指在内存中存在两个或多个区域,它们的地址范围有交叉部分。在 C++ 中,内存重叠可能会导致程序出现不可预期的行为,因此我们需要了解它的原因和如何避免。
内存重叠的原因
内存重叠的主要原因是指针的使用。当我们使用指针访问内存时,如果指针指向的内存区域与另一个区域有交叉部分,就会产生内存重叠。
如下图,内存拷贝的两种情况:

第一种情况下,拷贝重叠的区域不会出现问题,内容均可以正确地被拷贝。
第二种情况下,问题出现在右边的两个字节,这两个字节的原来的内容首先就被覆盖了,而且没有保存。所以接下来拷贝的时候,拷贝的是已经被覆盖的内容,显然这是有问题的。
举个代码例子,下面的代码片段就会导致内存重叠:
char str[] = "Hello World";
char* p = str + 1;
memcpy(p, str, 11);
在上面的代码中,我们定义了一个字符数组 str,并使用指针 p 指向 str 中的第二个字符。接着,我们使用 memcpy 函数将 str 中的 11 个字符复制到了 p 指向的区域。由于 p 指向的区域与 str 有交叉部分,因此就产生了内存重叠。因为 memcpy 是直接按位复制拷贝,代码如下,所以会遇到情况二,拷贝的是已经被覆盖的内容。
void *memcpy(void *dest, const void *src, size_t count)
{
char *tmp = dest;
const char *s = src;
while (count--)
*tmp++ = *s++;
return dest;
}
如何避免内存重叠
为了避免内存重叠,我们需要注意以下几点:
- 尽量避免使用指针,尤其是指针运算和类型转换;
- 在使用指针时,确保指针指向的内存区域与其他区域没有交叉部分;
- 使用安全的内存操作函数,如
memcpy_s、memmove等,这些函数可以确保在复制内存时不会产生内存重叠。
那 memmove 是怎么避免内存重叠的影响呢,我们看看 memmove 的代码:
void *memmove(void *dest, const void *src, size_t n)
{
char *d = dest;
const char *s = src;
if (d < s) {
while (n--)
*d++ = *s++;
} else {
// 采用倒序拷贝
char *lasts = (char *)s + (n - 1);
char *lastd = d + (n - 1);
while (n--)
*lastd-- = *lasts--;
}
return dest;
}
memmove 判断如果 dest ≥src 的时候(也就是前面图片的情况2),采用倒序拷贝,避免了内容被覆盖导致拷贝不完整的问题。
其原理图如下:

memcpy 与 strcpy 都没有内存重叠的问题,实际可以根据需要使用 memmove 。
总结
本文介绍了 C++ 中的内存重叠问题,指出了指针的使用是内存重叠的主要原因,并提供了避免内存重叠的方法,如尽量避免使用指针,确保指针指向的内存区域与其他区域没有交叉部分,使用安全的内存操作函数等。此外,还介绍了 memmove 函数如何避免内存重叠的影响。
C++内存重叠的更多相关文章
- C++中两块内存重叠的string的copy方法
如果两段内存重叠,用memcpy函数可能会导致行为未定义. 而memmove函数能够避免这种问题,下面是一种实现方式: #include <iostream> using namespac ...
- memmove 和 memcpy的区别以及处理内存重叠问题
区别: memcpy和memmove()都是C语言中的库函数,在头文件string.h中,作用是拷贝一定长度的内存的内容,原型分别如下: void *memcpy(void *dst, const v ...
- [整理]内存重叠之memcpy、memmove
函数原型: void *memcpy( void *dest, const void *src, size_t count ); void *memmove( void* dest, const vo ...
- strcpy,memcpy,memmove和内存重叠分析
一:strcpy函数用法和实现: /* GNU-C中的实现(节选): */ char* strcpy(char *d, const char *s) { char *r=d; while((*d++= ...
- C++中的内存重叠问题
内存重叠,直到做到一个笔试题才知道了什么是内存重叠.先上题目吧,是一个淘宝的笔试题,当时有点懵,不知道这个名词是啥子意思. 题目:补充下面函数代码: 如果两段内存重叠,用memcpy函数可能会导致行为 ...
- C语言标准库函数memcpy和memmove的区别以及内存重叠问题处理
①memcpy()和memmove()都是C语言中的标准库函数,定义在头文件string.h中,作用是拷贝一定长度的内存的内容,原型分别如下: void *memcpy(void *dst, cons ...
- 【C语言】模拟实现memmove函数(考虑内存重叠)
//模拟实现memmove函数(考虑内存重叠) #include <stdio.h> #include <assert.h> #include <string.h> ...
- C++ 浅析调试,内存重叠查看
这里举个例子查看内存, 环境为:vs 2017 测试为strcpy[因为测试老api,需要在 预处理中 添加 _CRT_SECURE_NO_WARNINGS ] 测试问题:内存溢出 源码: #incl ...
- 避免内存重叠memmove()性能
#include <iostream> #include <string.h> using namespace std; void* memmove(void *dst, co ...
- memcpy不能复制内存重叠区域,memmove可以拷贝重叠内存
http://blog.csdn.net/li_ning_/article/details/51418400 下面s和s2指向的内存区域有重叠,memcpy不能正确复制,src赋值给dst时,可能会修 ...
随机推荐
- 打车起步价8元(3KM以内) 超过3KM,超出的每公里1.2元 超过5KM,超出的每公里1.5元 请在键盘上接收公里数,得出总价。
import java.util.Scanner; public class Taxi { public static void main(String []agrs){ Scanner s = ne ...
- Java的访问控制修饰符有哪些?各有什么访问权限?请对照第7页ppt的表格分别写程序验证。
Java的访问控制修饰符有哪些? JAVA主要有两类修饰符: 访问控制修饰符 : default, public , protected, private 非访问控制修饰符 : final, abst ...
- dos命令初学
DOS命令 打开DOS命令方式 开始+系统+命令提示符 WIN键盘+R 输入CMD 打开控制台(推荐使用) 在任意文件夹下面,按住shift键加鼠标右键点击,在此处打开命令行窗口 自愿管理器的地址栏前 ...
- Python从dic中随机取值
import random a = {'lab-1': '短视频', 'lab-1': '直播'} print(random.choice(list(a.keys()))) # 从keys的list中 ...
- GitLab版本定版
定版指令: git add -Agit commit -m ""git push origin develops:V5.2
- maven的下载与安装 win10系统
1.安装maven的前提是jdk环境要配置好 不然下载jar包的时候会出错 2. Maven软件安装包下载 (推荐官网下载) 官网地址https://maven.apache.org/ 然后 3.下载 ...
- 4组-Alpha冲刺-4/6
一.基本情况 队名:摸鲨鱼小队 组长博客:https://www.cnblogs.com/smallgrape/p/15553653.html 小组人数:8人 二.冲刺概况汇报 组长:许雅萍 过去两天 ...
- 狐漠漠养成日记 Cp.00002 第一周
主要目标 (1)考研 考研数学二16-22年的真题卷(已完成真题卷:0/7) 记忆考研英语中高频词汇(已记忆词汇:高频:0/10:中频:0/10) 考研英语二16-22年的真题卷(已完成真题卷:0/7 ...
- k8s集群查看node和pod的实时资源使用情况
一.部署步骤 1.准备metrics-server官方yaml文件 2.部署metrics-server 3.查看资源使用情况 二.准备metrics-server官方yaml文件 [root@loc ...
- java_web----1
一.HTML 1.网页的构成 结构:HTML 超文本标记语言 标签语言 标签写法: <标签名> </标签名> <标签名/> 表现:CSS 行为:JavaScrip ...