• C++内存重叠


    内存重叠是指在内存中存在两个或多个区域,它们的地址范围有交叉部分。在 C++ 中,内存重叠可能会导致程序出现不可预期的行为,因此我们需要了解它的原因和如何避免。

    内存重叠的原因

    内存重叠的主要原因是指针的使用。当我们使用指针访问内存时,如果指针指向的内存区域与另一个区域有交叉部分,就会产生内存重叠。

    如下图,内存拷贝的两种情况:

    img

    第一种情况下,拷贝重叠的区域不会出现问题,内容均可以正确地被拷贝。

    第二种情况下,问题出现在右边的两个字节,这两个字节的原来的内容首先就被覆盖了,而且没有保存。所以接下来拷贝的时候,拷贝的是已经被覆盖的内容,显然这是有问题的。

    举个代码例子,下面的代码片段就会导致内存重叠:

    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_smemmove 等,这些函数可以确保在复制内存时不会产生内存重叠。

    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 判断如果 destsrc 的时候(也就是前面图片的情况2),采用倒序拷贝,避免了内容被覆盖导致拷贝不完整的问题。

    其原理图如下:

    img

    memcpy 与 strcpy 都有内存重叠的问题,实际可以根据需要使用 memmove 。

    总结

    本文介绍了 C++ 中的内存重叠问题,指出了指针的使用是内存重叠的主要原因,并提供了避免内存重叠的方法,如尽量避免使用指针,确保指针指向的内存区域与其他区域没有交叉部分,使用安全的内存操作函数等。此外,还介绍了 memmove 函数如何避免内存重叠的影响。

  • 相关阅读:
    C#/VB.NET 将XML转为PDF
    notepad++去除每一行第二个等号之后的内容解决ResolvePackageNotFound
    C++ make_heap等堆函数的使用
    Linux下安装MySQL教程
    华为云云耀云服务器 L 实例评测|配置教程 + 用 Python 简单绘图
    视觉SLAM14讲笔记-第7讲-视觉里程计1
    [兔子私房课] Mybatis开发详解与项目实战02
    ADFS和NingDS两种统一身份认证,哪种方案更适合现代中小企业?(上)
    一些简单却精妙的算法
    java毕业设计网上拍卖系统设计源码+lw文档+mybatis+系统+mysql数据库+调试
  • 原文地址:https://www.cnblogs.com/listenwind666/p/17248368.html