C++記憶體重疊

来源:https://www.cnblogs.com/listenwind666/archive/2023/03/23/17248368.html
-Advertisement-
Play Games

記憶體重疊是指在記憶體中存在兩個或多個區域,它們的地址範圍有交叉部分。在 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 函數如何避免記憶體重疊的影響。


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • SpringBoot中註入Servlet&Filter&Listener 1.基本介紹 文檔:SpringBoot中註入Servlet&Filter&Listener 考慮到實際開發業務非常複雜和相容問題,SpringBoot支持將Servlet、Filter、Listener註入spring容器中 ...
  • Styled Components 備忘清單 IT寶庫整理的Styled Components快速參考備忘單提供了使用 CSS in JS 工具的各種方法入門,為開發人員分享快速參考備忘單。 開發速查表大綱 入門 安裝 快速開始 根據 Props 適配 擴展樣式 擴展樣式改變標簽 (as) 自定義組 ...
  • Stylus 備忘清單 IT寶庫整理的Stylus開發速查備忘單旨在快速理解 stylus 所涉及的主要概念,顯示了它的常用方法使用清單入門,為開發人員分享快速參考備忘單。 開發速查表大綱 入門 介紹 支持 CSS 嵌套語法 支持類 python 縮進語法 混合 Mixins 變數 Variable ...
  • 最近工作中經常使用Teamcenter、NX集成開發的情況,因此在這裡記錄UF_UGMGR函數的使用。使用UF_UGMGR相關函數需要有Teamcenter使用經驗,理解Teamcenter中文件夾、偽文件夾、零組件、零組件版本、數據集、關係、表單、命名引用等對象。 相關的可以看幫助中 Teamce ...
  • 本篇文章將深入介紹 Yarn 三種調度器。Yarn 本身作為資源管理和調度服務,其中的資源調度模塊更是重中之重。下麵將介紹 Yarn 中實現的調度器功能,以及內部執行邏輯。 ...
  • 本文實現一個Echo TCP Server 完整代碼:https://github.com/csgopher/go-redis interface/tcp/Handler.go type Handler interface { Handle(ctx context.Context, conn net ...
  • 繼上一個博客中生成 簽章圖片後,今日遇到一個問題, 本地不管如何改代碼,都會將簽名文字顯示出來。 但是.... ....... 一旦部署在linux系統後,一直列印不出來,,糾結的呀。。 完全沒想到, 原來是linux系統裡面不相容本地的字體,也就是沒有那麼多中文字體,除非安裝。 可以驚醒安裝字體: ...
  • 在java打演算法題的時候,Scanner類、Sout的速度太慢,所以要用PrintWriter和BufferReader&StreamTokenizer類來進行快速輸入。代碼如下: import java.io.*; public class Main { public static PrintWr ...
一周排行
    -Advertisement-
    Play Games
  • C#TMS系統代碼-基礎頁面BaseCity學習 本人純新手,剛進公司跟領導報道,我說我是java全棧,他問我會不會C#,我說大學學過,他說這個TMS系統就給你來管了。外包已經把代碼給我了,這幾天先把增刪改查的代碼背一下,說不定後面就要趕鴨子上架了 Service頁面 //using => impo ...
  • 委托與事件 委托 委托的定義 委托是C#中的一種類型,用於存儲對方法的引用。它允許將方法作為參數傳遞給其他方法,實現回調、事件處理和動態調用等功能。通俗來講,就是委托包含方法的記憶體地址,方法匹配與委托相同的簽名,因此通過使用正確的參數類型來調用方法。 委托的特性 引用方法:委托允許存儲對方法的引用, ...
  • 前言 這幾天閑來沒事看看ABP vNext的文檔和源碼,關於關於依賴註入(屬性註入)這塊兒產生了興趣。 我們都知道。Volo.ABP 依賴註入容器使用了第三方組件Autofac實現的。有三種註入方式,構造函數註入和方法註入和屬性註入。 ABP的屬性註入原則參考如下: 這時候我就開始疑惑了,因為我知道 ...
  • C#TMS系統代碼-業務頁面ShippingNotice學習 學一個業務頁面,ok,領導開完會就被裁掉了,很突然啊,他收拾東西的時候我還以為他要旅游提前請假了,還在尋思為什麼回家連自己買的幾箱飲料都要叫跑腿帶走,怕被偷嗎?還好我在他開會之前拿了兩瓶芬達 感覺感覺前面的BaseCity差不太多,這邊的 ...
  • 概述:在C#中,通過`Expression`類、`AndAlso`和`OrElse`方法可組合兩個`Expression<Func<T, bool>>`,實現多條件動態查詢。通過創建表達式樹,可輕鬆構建複雜的查詢條件。 在C#中,可以使用AndAlso和OrElse方法組合兩個Expression< ...
  • 閑來無聊在我的Biwen.QuickApi中實現一下極簡的事件匯流排,其實代碼還是蠻簡單的,對於初學者可能有些幫助 就貼出來,有什麼不足的地方也歡迎板磚交流~ 首先定義一個事件約定的空介面 public interface IEvent{} 然後定義事件訂閱者介面 public interface I ...
  • 1. 案例 成某三甲醫預約系統, 該項目在2024年初進行上線測試,在正常運行了兩天後,業務系統報錯:The connection pool has been exhausted, either raise MaxPoolSize (currently 800) or Timeout (curren ...
  • 背景 我們有些工具在 Web 版中已經有了很好的實踐,而在 WPF 中重新開發也是一種費時費力的操作,那麼直接集成則是最省事省力的方法了。 思路解釋 為什麼要使用 WPF?莫問為什麼,老 C# 開發的堅持,另外因為 Windows 上已經裝了 Webview2/edge 整體打包比 electron ...
  • EDP是一套集組織架構,許可權框架【功能許可權,操作許可權,數據訪問許可權,WebApi許可權】,自動化日誌,動態Interface,WebApi管理等基礎功能於一體的,基於.net的企業應用開發框架。通過友好的編碼方式實現數據行、列許可權的管控。 ...
  • .Net8.0 Blazor Hybird 桌面端 (WPF/Winform) 實測可以完整運行在 win7sp1/win10/win11. 如果用其他工具打包,還可以運行在mac/linux下, 傳送門BlazorHybrid 發佈為無依賴包方式 安裝 WebView2Runtime 1.57 M ...