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时,可能会修 ...
随机推荐
- Linux 第二节(基本命令)
www.linuxcool.com 一.ifconfig 1.Ip 地址 2.MAC地址 3.收到的数据包(RX) 4.发送的数据包(Tx) 二.uname uname -a //查看系统内核及 ...
- javascript向tabale中动态添加数据
<table width="600" border="1" cellspacing="0"> <thead> < ...
- python -m pip install --upgrade pip 解决升级不成功问题
使用pip 提示更新: You are using pip version 18.1, however version 20.0.2 is available. You should consider ...
- c++学习2 基础关键词
三 volatile强制访问内存 在一个变量的频繁使用中,系统为了提高效率,会自动将内存里面的数据放入CPU里的寄存器里.但在某些特殊场景下,放入寄存器这个操作反倒会导致CPU无法及时获取最新的一手数 ...
- Mysql存储类型长度
分析MySQL数据类型的长度 MySQL有几种数据类型可以限制类型的"长度",有CHAR(Length).VARCHAR(Length).TINYINT(Length).SMALL ...
- P1296 奶牛的耳语
P1296 奶牛的耳语 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) 本题核心思路: 1.读入后要排序以达到剪枝的目的 2.模拟,遇到不能再交流就转入下一头牛,否则计数器加一 3. ...
- 中值滤波 ordfilt2函数
滤波是过滤掉信号中没用的波段 ordfilt2函数语法格式为:B=ordfilt2(A,order,domain)B=ordfilt2(A,order,domain,S)B=ordfilt2(..., ...
- 对Java要学东西的认识 (一点点javascript见解)
JavaScript是一种脚本语言,它采用小程序段的方式实现编程.像其它脚本语言一样,JavaScript同样已是一种解释性语言,它提供了一个易的开发过程.它的基本结构形式与C.C++.VB十分类似. ...
- C#发送字符串转字节含空格与0x需删去
主要作用:清除发送字符串转字节中的空格和16进制前缀0x, 字节转换按两位字符转换为一个字节,多余一位按一位字符转换一个字节 //清除空格和16进制前缀发送 String sendstr;// = n ...
- Python测试——安装篇总结
测试用到的工具自己知道的有: 写脚本类:sublime ,PyCharm,Eclipse+PyDev,目前我知道的只有这么多,大家知道的肯定还有很多,欢迎留言哈 录制脚本类:火狐自带的seleniu ...