欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

C++利用對(duì)象池優(yōu)化內(nèi)存管理解決MISRA報(bào)警的代碼詳解

 更新時(shí)間:2025年07月25日 09:10:31   作者:mr.Darker  
本篇詳細(xì)講解如何用對(duì)象池技術(shù)優(yōu)化C++項(xiàng)目中的內(nèi)存管理,徹底消除new/delete帶來的MISRA報(bào)警,兼顧高性能與安全規(guī)范,需要的朋友可以參考下

1. 背景與問題起因

初始需求:

  • 動(dòng)態(tài)創(chuàng)建/銷毀 AOI 和 Controller 處理器對(duì)象
  • 原實(shí)現(xiàn)用傳統(tǒng) new / delete
  • 通過工廠函數(shù) CreateProcessor() 分配對(duì)象

初始代碼(示意):

IProcessor* CreateAoiProcessor() {
    return new CAoiProcessor();
}

void ReleaseProcessor(IProcessor* pProcessor) {
    delete pProcessor;
}

遇到的問題:

  • MISRA / AUTOSAR 檢查工具報(bào)錯(cuò):

Rule A18-4-1:Dynamic heap memory allocation shall not be used.

風(fēng)險(xiǎn)點(diǎn):

  • new/delete 不可控、難追蹤、不可預(yù)測(OOM、碎片)
  • 對(duì)于嵌入式、工業(yè)控制項(xiàng)目,這是大小禁忌
  • MISRA / AUTOSAR 標(biāo)準(zhǔn)嚴(yán)禁使用動(dòng)態(tài)分配

2. 初步嘗試:對(duì)象池(ProcessorObjectPool)設(shè)計(jì)

基本思路:

  • 緩存還未被使用的對(duì)象,避免重復(fù)創(chuàng)建
  • 使用 std::unique_ptr 確保所有權(quán)限獨(dú)占
  • 用戶需要手動(dòng) Release ,將對(duì)象歸還池內(nèi)

優(yōu)點(diǎn):

  • 消除 new/delete,滿足標(biāo)準(zhǔn)
  • 超高性能,極簡單的內(nèi)存管理
  • 適合靜態(tài)存儲(chǔ)、有限對(duì)象數(shù)量場景

缺點(diǎn):

  • 必須手動(dòng) Release,容易忘記
  • 外部用法算是稍復(fù)雜

使用場景:

  • 簡單異步性不高的應(yīng)用,如單線編碼器系統(tǒng)
  • 對(duì)象使用常性很高,能確保不會(huì)忘記 Release 的項(xiàng)目
  • 推薦第一次試測或無需交叉線編程的場景

3. 二次優(yōu)化:shared_ptr + 自定義刪除器版本

核心思路:

  1. 對(duì)象池內(nèi)部預(yù)分配完整對(duì)象,禁止動(dòng)態(tài)分配
  2. 對(duì)外接口選擇 std::shared_ptr,綁定自定義刪除器
  3. 當(dāng)用戶釋放對(duì)象時(shí),并非 delete,而是將對(duì)象歸還池內(nèi)

優(yōu)點(diǎn):

  • 手動(dòng)釋放的問題全部消失,用戶不需關(guān)心
  • 外部用法極簡單,與普通 shared_ptr 無差
  • 滿足 MISRA / AUTOSAR,依然是靜態(tài)內(nèi)存分配

缺點(diǎn):

  • 少量的引用計(jì)數(shù)跟蹤負(fù)擔(dān)
  • 但對(duì)于當(dāng)前項(xiàng)目,很值,算中級(jí)性能優(yōu)化

使用場景:

  • 對(duì)象需要被多個(gè)模塊共享、交付或經(jīng)過多級(jí)層傳遞的場景
  • 需要自動(dòng)管理生命周期,避免手動(dòng)釋放風(fēng)險(xiǎn)
  • 常見于有較復(fù)雜邏輯或有多線程跨線使用需求的應(yīng)用

4. 解決過程中的 MISRA / AUTOSAR 報(bào)警問題記錄

報(bào)警規(guī)則編號(hào)報(bào)警信息解決方案
A18-4-1禁止動(dòng)態(tài)內(nèi)存分配(禁止 new/delete)替換為對(duì)象池,固定數(shù)組預(yù)分配
M6-6-5函數(shù)必須只有一個(gè)出口統(tǒng)一 return,避免提前返回
M4-2-1if/else 必須成對(duì)補(bǔ)全 else 分支
命名規(guī)范成員變量必須加 m_ 前綴全部重命名為 m_xxx
OOP50-CPP構(gòu)造/析構(gòu)中不能調(diào)用虛函數(shù)移除析構(gòu)中 Stop() 調(diào)用
M12-1-1構(gòu)造/析構(gòu)中禁止訪問對(duì)象的動(dòng)態(tài)類型(虛函數(shù)風(fēng)險(xiǎn))構(gòu)造函數(shù)內(nèi)只做初始化,不調(diào)虛函數(shù)
命名規(guī)范static 成員必須加 s_ 前綴全部 static 變量改為 s_xxx

5. 整體優(yōu)化成果

  • 代碼質(zhì)量顯著提升
  • 消除全部 MISRA 報(bào)警
  • 對(duì)象復(fù)用,減少內(nèi)存開銷
  • 支持多線程,自動(dòng)釋放,維護(hù)成本降低

6. 最終對(duì)比總結(jié)

版本內(nèi)存分配安全性易用性MISRA合規(guī)性
原版 new/delete動(dòng)態(tài)堆分配容易泄漏簡單但危險(xiǎn)不合規(guī)
unique_ptr 對(duì)象池版靜態(tài)預(yù)分配手動(dòng)釋放安全一般合規(guī)
shared_ptr 對(duì)象池版靜態(tài)預(yù)分配自動(dòng)回收最安全最易用合規(guī)

7. 建議總結(jié)

  • 工業(yè)、嵌入式、MISRA/AUTOSAR 場景下,強(qiáng)烈推薦對(duì)象池 + shared_ptr 刪除器方案
  • 適用于所有“對(duì)象個(gè)數(shù)固定、生命周期可控、性能敏感”的系統(tǒng)

附錄:完整示例代碼(建議放文末)

ProcessorObjectPool.hpp

// unique_ptr 對(duì)象池版本源碼
#pragma once

#include <stack>
#include <memory>
#include <mutex>

/**
 * @brief 通用的處理器對(duì)象池模板。
 * @tparam T 實(shí)際實(shí)現(xiàn) IProcessor 的派生類。
 */
template <typename T>
class ProcessorObjectPool {
public:
    using Ptr = std::unique_ptr<T>;

    /**
     * @brief 獲取一個(gè)處理器對(duì)象。
     * @return 智能指針,包裝了一個(gè) T 類型實(shí)例。
     */
    Ptr Acquire();

    /**
     * @brief 回收一個(gè)處理器對(duì)象。
     * @param pObj 要回收的對(duì)象(智能指針)。
     */
    void Release(Ptr pObj);

    /**
     * @brief 獲取對(duì)象池的單例實(shí)例。
     * @return 靜態(tài)的對(duì)象池實(shí)例。
     */
    static ProcessorObjectPool<T>& Instance();

private:
    ProcessorObjectPool() = default;
    ~ProcessorObjectPool() = default;

    ProcessorObjectPool(const ProcessorObjectPool&) = delete;
    ProcessorObjectPool& operator=(const ProcessorObjectPool&) = delete;

    std::stack<Ptr> m_pool;
    std::mutex m_mutex;
    static constexpr std::size_t MAX_POOL_SIZE = 64;  ///< 池中最大緩存對(duì)象數(shù)量
};

// 模板實(shí)現(xiàn)必須包含在頭文件中
#include "ProcessorObjectPool.inl"

//============================================================================================
//============================================================================================

// shared_ptr 對(duì)象池版本源碼
#pragma once

#include <array>
#include <memory>
#include <mutex>
#include <bitset>
#include <cstddef>

/**
 * @file ProcessorObjectPool.h
 * @brief 基于靜態(tài)內(nèi)存的對(duì)象池模板類,適配 MISRA / AUTOSAR C++。
 * @tparam T 對(duì)象類型(必須支持默認(rèn)構(gòu)造)。
 * @tparam N 對(duì)象池大小,最大可同時(shí)持有的對(duì)象數(shù)量。
 */
template <typename T, std::size_t N>
class ProcessorObjectPool {
public:
    /**
     * @brief 對(duì)象指針類型,使用 shared_ptr 包裝,帶自定義回收邏輯。
     */
    using Ptr = std::shared_ptr<T>;

    /**
     * @brief 獲取對(duì)象池的單例實(shí)例。
     * @return 返回靜態(tài)單例。
     */
    static ProcessorObjectPool& Instance();

    /**
     * @brief 獲取一個(gè)可用對(duì)象指針。
     * @return 有效 shared_ptr,如果池已滿返回空指針。
     */
    Ptr Acquire();

    /**
     * @brief 回收對(duì)象指針(由 shared_ptr 的 deleter 調(diào)用)。
     * @param pObj 需回收的對(duì)象指針。
     */
    void Recycle(T* pObj);

private:
    ProcessorObjectPool() = default;
    ~ProcessorObjectPool() = default;

    // 禁止復(fù)制與賦值
    ProcessorObjectPool(const ProcessorObjectPool&) = delete;
    ProcessorObjectPool& operator=(const ProcessorObjectPool&) = delete;

    std::array<T, N> m_objects;     ///< 靜態(tài)分配的對(duì)象數(shù)組
    std::bitset<N> m_used{};        ///< 標(biāo)記哪些對(duì)象已被占用
    std::mutex m_mutex;             ///< 互斥鎖,保護(hù)并發(fā)訪問
};

#include "ProcessorObjectPool.inl"  // 模板實(shí)現(xiàn)必須放頭文件中

ProcessorObjectPool.inl

// 這里預(yù)留 unique_ptr 對(duì)象池版本實(shí)現(xiàn)
#pragma once

#include <utility>

template <typename T>
typename ProcessorObjectPool<T>::Ptr ProcessorObjectPool<T>::Acquire() {
    std::lock_guard<std::mutex> lock(m_mutex);
    if (!m_pool.empty()) {
        Ptr obj = std::move(m_pool.top());
        m_pool.pop();
        return obj;
    } else {
        return std::unique_ptr<T>(new T());  // C++14 不能用 make_unique
    }
}

template <typename T>
void ProcessorObjectPool<T>::Release(Ptr pObj) {
    std::lock_guard<std::mutex> lock(m_mutex);
    if (m_pool.size() < MAX_POOL_SIZE) {
        m_pool.push(std::move(pObj));
    } else {
        // 超出限制,自動(dòng)釋放,不入池
    }
}

template <typename T>
ProcessorObjectPool<T>& ProcessorObjectPool<T>::Instance() {
    static ProcessorObjectPool<T> instance;
    return instance;
}

//============================================================================================
//============================================================================================

// 這里預(yù)留 shared_ptr 對(duì)象池版本實(shí)現(xiàn)
#pragma once

/**
 * @brief 獲取單例對(duì)象池實(shí)例。
 */
template <typename T, std::size_t N>
ProcessorObjectPool<T, N>& ProcessorObjectPool<T, N>::Instance()
{
    static ProcessorObjectPool<T, N> instance;
    return instance;
}

/**
 * @brief 獲取一個(gè)可用對(duì)象的 shared_ptr。
 *        若池中存在未使用對(duì)象,則直接返回;
 *        若全部占用,則返回空 shared_ptr。
 */
template <typename T, std::size_t N>
typename ProcessorObjectPool<T, N>::Ptr ProcessorObjectPool<T, N>::Acquire()
{
    std::lock_guard<std::mutex> lock(m_mutex);

    T* pRaw = nullptr;
    for (std::size_t i = 0; i < N; ++i) {
        if (!m_used[i]) {
            m_used[i] = true;
            pRaw = &m_objects[i];
            break;
        }
    }

    Ptr result;
    if (pRaw != nullptr) {
        // 創(chuàng)建 shared_ptr,附帶回收 deleter
        result = Ptr(pRaw, [](T* p) {
            ProcessorObjectPool<T, N>::Instance().Recycle(p);
        });
    }

    return result;
}

/**
 * @brief 回收一個(gè)對(duì)象指針回池中。
 * @param pObj 需釋放的對(duì)象,必須為池中對(duì)象。
 */
template <typename T, std::size_t N>
void ProcessorObjectPool<T, N>::Recycle(T* pObj)
{
    if (nullptr == pObj) {
	    return;
    }

    std::lock_guard<std::mutex> lock(m_mutex);
    const std::ptrdiff_t nIndex = pObj - m_objects.data();
    if ((nIndex >= 0) && (static_cast<std::size_t>(nIndex) < N)) {
        m_used[static_cast<std::size_t>(nIndex)] = false;
        // 注意:對(duì)象不會(huì)析構(gòu)。若對(duì)象含狀態(tài),應(yīng)在 T 內(nèi)部自行 reset()
        pObj->Reset();
    }
}

ProcessorFactory.cpp 舊新對(duì)比

// ProcessorFactory 舊源碼
#include "pch.h"
#include "ProcessorFactory.h"

#include "AoiProcessor.h"
#include "ControllerProcessor.h"

extern "C" {
    IProcessor* CreateAoiProcessor() {
        return new CAoiProcessor();
    }

    IProcessor* CreateControllerProcessor() {
        return new CControllerProcessor();
    }

    void ReleaseProcessor(IProcessor* pProcessor) {
        if (pProcessor) {
            delete pProcessor;
        }
    }
}

//============================================================================================
//============================================================================================

// ProcessorFactory 新源碼
#include "pch.h"
#include "ProcessorFactory.h"
#include "AoiProcessor.h"
#include "ControllerProcessor.h"
#include "ProcessorObjectPool.h"

// 使用靜態(tài)池管理對(duì)象(不使用 new/delete)
using AoiProcessorPool = ProcessorObjectPool<CAoiProcessor, 32>;
using CtrlProcessorPool = ProcessorObjectPool<CControllerProcessor, 32>;

// 內(nèi)部共享引用池,避免 shared_ptr 提前析構(gòu)
static std::vector<std::shared_ptr<IProcessor>> s_processorRefs;
static std::mutex s_mutex;

extern "C" {
    IProcessor* CreateProcessor(int nType) {
        std::shared_ptr<IProcessor> sp;
        IProcessor* pRaw = nullptr;

        if (nType == 0) {
            sp = AoiProcessorPool::Instance().Acquire();
        }
        else if (nType == 1) {
            sp = CtrlProcessorPool::Instance().Acquire();
        }
        else {
            sp = nullptr;
		}

        if (sp) {
            pRaw = sp.get();
            std::lock_guard<std::mutex> lock(s_mutex);
            s_processorRefs.emplace_back(std::move(sp));
        }

        return pRaw;
    }

    void ReleaseProcessor(IProcessor* pProcessor) {
        if (pProcessor == nullptr) {
            return;
        }

        std::lock_guard<std::mutex> lock(s_mutex);
        auto it = std::remove_if(s_processorRefs.begin(), s_processorRefs.end(), [=](const std::shared_ptr<IProcessor>& ptr) {
        	return ptr.get() == pProcessor;
        });
        s_processorRefs.erase(it, s_processorRefs.end());
    }
}

以上就是C++利用對(duì)象池優(yōu)化內(nèi)存管理解決MISRA報(bào)警的代碼詳解的詳細(xì)內(nèi)容,更多關(guān)于C++對(duì)象池優(yōu)化內(nèi)存管理的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • C語言 鏈?zhǔn)蕉鏄浣Y(jié)構(gòu)詳解原理

    C語言 鏈?zhǔn)蕉鏄浣Y(jié)構(gòu)詳解原理

    二叉樹的鏈?zhǔn)酱鎯?chǔ)結(jié)構(gòu)是指,用鏈表來表示一棵二叉樹,即用鏈來指示元素的邏輯關(guān)系。通常的方法是鏈表中每個(gè)結(jié)點(diǎn)由三個(gè)域組成,數(shù)據(jù)域和左右指針域,左右指針分別用來給出該結(jié)點(diǎn)左孩子和右孩子所在的鏈結(jié)點(diǎn)的存儲(chǔ)地址
    2021-11-11
  • Qt實(shí)現(xiàn)圖形裁減

    Qt實(shí)現(xiàn)圖形裁減

    這篇文章主要為大家詳細(xì)介紹了Qt實(shí)現(xiàn)圖形裁減,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-06-06
  • C++語法詳解之封裝、構(gòu)造函數(shù)、析構(gòu)函數(shù)

    C++語法詳解之封裝、構(gòu)造函數(shù)、析構(gòu)函數(shù)

    這篇文章主要介紹了C++語法詳解之封裝、構(gòu)造函數(shù)、析構(gòu)函數(shù)的相關(guān)知識(shí),通過實(shí)例代碼給大家詳細(xì)介紹,對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-03-03
  • c++顯式棧實(shí)現(xiàn)遞歸介紹

    c++顯式棧實(shí)現(xiàn)遞歸介紹

    大家好,本篇文章主要講的是c++顯式棧實(shí)現(xiàn)遞歸介紹,感興趣的同學(xué)趕快來看一看吧,對(duì)你有幫助的話記得收藏一下
    2022-01-01
  • 詳談signed 關(guān)鍵字

    詳談signed 關(guān)鍵字

    c++中關(guān)鍵字有幾十個(gè),其中類型修飾關(guān)鍵字有l(wèi)ong, short, singed, unsigned。今天我們就來談一下經(jīng)常被大家忽視的signed關(guān)鍵字
    2015-01-01
  • C/C++實(shí)現(xiàn)segy文件的讀取詳解

    C/C++實(shí)現(xiàn)segy文件的讀取詳解

    SEGY是地震數(shù)據(jù)一般以地震道為單位進(jìn)行組織,采用SEG-Y文件格式存儲(chǔ)。標(biāo)準(zhǔn)SEGY文件一般包括三部分:卷頭、道頭與地震道數(shù)據(jù)。本文將介紹利用C++讀取segy文件的方法,感興趣的可以了解一下
    2022-03-03
  • VC下實(shí)現(xiàn)fopen支持中文的方法

    VC下實(shí)現(xiàn)fopen支持中文的方法

    這篇文章主要介紹了VC下實(shí)現(xiàn)fopen支持中文的方法,需要的朋友可以參考下
    2014-07-07
  • Java3D實(shí)例之創(chuàng)建空間幾何模型的實(shí)現(xiàn)方法

    Java3D實(shí)例之創(chuàng)建空間幾何模型的實(shí)現(xiàn)方法

    本篇文章是對(duì)Java3D 創(chuàng)建空間幾何模型的實(shí)現(xiàn)方法進(jìn)行了詳細(xì)的介紹。需要的朋友參考下
    2013-05-05
  • C++編寫高性能服務(wù)器實(shí)例教程

    C++編寫高性能服務(wù)器實(shí)例教程

    這篇文章主要介紹了如何用C++編寫高性能服務(wù)器,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)C++有一定的參考價(jià)值,需要的朋友們可以了解下
    2020-06-06
  • Qt音視頻開發(fā)之視頻文件保存功能的實(shí)現(xiàn)

    Qt音視頻開發(fā)之視頻文件保存功能的實(shí)現(xiàn)

    和音頻存儲(chǔ)類似,視頻的存儲(chǔ)也對(duì)應(yīng)三種格式,視頻最原始的數(shù)據(jù)是yuv(音頻對(duì)應(yīng)pcm),視頻壓縮后的數(shù)據(jù)是h264(音頻對(duì)應(yīng)aac)。本文將利用Qt實(shí)現(xiàn)視頻文件保存功能,感興趣的可以了解一下
    2022-12-12

最新評(píng)論