开发者

C++利用对象池优化内存管理解决MISRA报警的代码详解

目录
  • 1. 背景与问题起因
    • 初始需求:
    • 初始代码(示意):
    • 遇到的问题:
    • 风险点:
  • 2. 初步尝试:对象池(ProcessorObjectPool)设计
    • 基本思路:
    • 优点:
    • 缺点:
    • 使用场景:
  • 3. 二次优化:shared_ptr + 自定义删除器版本
    • 核心思路:
    • 优点:
    • 缺点:
    • 使用场景:
  • 4. 解决过程中的 MISRA / AUTOSAR 报警问题记录
    • 5. 整体优化成果
      • 6. 最python终对比总结
        • 7. 建议总结
          • 附录:完整示例代码(建议放文末)

            1. 背景与问题起因

            初始需求:

            • 动态创建/销毁 AOI 和 Controller 处理器对象
            • 原实现用传统 new / delete
            • 通过工厂函数 CreateProcessor() 分配对象

            初始代码(示意):

            IProcessor* CreateAoiProcessor() {
                return new CAoiProcessor();
            }
            
            void ReleaseProcessor(IProcessor* pProcessor) {
                delete pProcessor;
            }
            

            遇到的问题:

            • MISRA / AUTOSAR 检查工具报错:

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

            风险点:

            • new/delete 不可控、难追踪、不可预测(OOM、碎片)
            • 对于嵌入式、工业控制项目,这是大小禁忌
            • MISRA / AUTOSAR 标准严禁使用动态分配

            2. 初步尝试:对象池(ProcessorObjectPool)设计

            基本思路:

            • 缓存还未被使用的对象,避免重复创建
            • 使用 std::unique_ptr 确保所有权android限独占
            • 用户需要手动 Release ,将对象归还池内

            优点:

            • 消除 new/delete,满足标准
            • 超高性能,极简单的内存管理
            • 适合静态存储、有限对象数量场景

            缺点:

            • 必须手动 Release,容易忘记
            • 外部用法算是稍复杂

            使用场景:

            • 简单异步性不高的应用,如单线编码器系统
            • 对象使用常性很高,能确保不会忘记 Release 的项目
            • 推荐第一次试测或无需交叉线编程的场景

            3. 二次优化:shared_ptr + 自定义删除器版本

            核心思路:

            1. 对象池内部预分配完整对象,禁止动态分配
            2. 对外接口选择 std::shared_ptr,绑定自定义删除器
            3. 当用户释放对象时,并非 delete,而是将对象归还池内

            优点:

            • 手动释放的问题全部消失,用户不需关心
            • 外部用法极简单,与普通 shared_ptr 无差
            • 满足 MISRA / AUTOSAR,依然是静态内存分配

            缺点:

            • 少量的引用计数跟踪负担
            • 但对于当前项目,很值,算中级性能优化

            使用场景:

            • 对象需要被多个模块共享、交付或经过多级层传递的场景
            • 需要自动管理生命周期,避免手动释放风险
            • 常见于有较复杂逻辑或有多线程跨线使用需求的应用

            4. 解决过程中的 MISRA / AUTOSAR 报警问题记录

            报警规则编号报警信息解决方案
            A18-4-1禁止动态内存分配(禁止 new/delete)替换为对象池,固定数组预分配
            M6-6-5函数必须只有一个出口统一 return,避免提前返回
            M4-2-1if/else 必须成对补全 else 分支
            命名规范成员变量必须加 m_ 前缀全部重命名为 m_xxx
            OOP50-CPP构造/析构中不能调用虚函数移除析构中 Stop() 调用
            M12-1-1构造/析构中禁止访问对象的动态类型(虚函数风险)构造函数内只做初始化,不调虚函数
            命名规范static 成员必须加 s_ 前缀全部 static 变量改为 s_xxx

            5. 整体优化成果

            • 代码质量显著提升
            • 消除全部 MISRA 报警
            • 对象复用,减少内存开销
            • 支持多线程,自动释放,维护成本降低

            6. 最终对比总结

            版本内存分配安全性易用性MISRA合规性
            原版 new/delete动态堆分配容易泄漏简单但危险不合规
            unique_ptr 对象池版静态预分配手动释放安全一般合规
            shared_ptr 对象池版静态预分配自动回收最安全最易用合规

            7. 建议总结

            • 工业、嵌入式、MISRA/AUTOSAR 场景下,强烈推荐对象池 + shared_ptr 删除器方案
            • 适用于所有“对象个数固定、生命周期可控、性能敏感”的系统

            附录:完整示例代码(建议放文末)

            ProcessorObjectPool.hpp

            // unique_ptr 对象池版本源码
            #pragma once
            
            #include <stack>
            #include <memory>
            #include <mutex>
            
            /**
             * @brief 通用的处理器对象池模板。
             * @tparam T 实际实现 IProcessor 的派生类。
             */
            template <typename T>
            class ProcessorObjectPool {
            public:
                using Ptr = std::unique_ptr<T>;
            
                /**
                 * @brief 获取一个处理器对象。
                 * @return 智能指针,包装了一个 T 类型实例。
                 */
                Ptr Acquire();
            
                /**
                 * @brief 回收一个处理器对象。
                 * @param pObj 要回收的对象(智能指针)。
                 */
                void Release(Ptr pObj);
            
                /**
                 * @brief 获取对象池的单例实例。
                 * @return 静态的对象池实例。
                 */
                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 conswww.devze.comtexpr std::size_t MAX_POOL_SIZE = 64;  ///< 池中最大缓存对象数量
            };
            
            // 模板实现必须包含在头文件中
            #include "ProcessorObjectPool.inl"
            
            //============================================================================================
            //============================================================================================
            
            // shared_ptr 对象池版本源码
            #pragma once
            
            #include <array>
            #include <memory>
            #include <mutex>
            #include <bitset>
            #include <cstddef>
            
            /**
             * @file ProcessorObjectPool.h
             * @brief 基于静态内存的对象池模板类,适配 MISRA / AUTOSAR C++。
             * @tparam T 对象类型(必须支持默认构造)。
             * @tparam N 对象池大小,最大可同时持有的对象数量。
             */
            template <typename T, std::size_t N>
            class ProcessorObjectPool {
            public:
                /**
                 * @brief 对象指针类型,使用 shared_ptr 包装,带自定义回收逻辑。
                 */
                using Ptr = std::shared_ptr<T>;
            
                /**
                 * @brief 获取对象池的单例实例。
                 * @return 返回静态单例。
                 */
                static ProcessorObjectPool& Instance();
            
                /**
                 * @brief 获取一个可用对象指针。
                 * @return 有效 shared_ptr,如果池已满返回空指针。
                 */
                Ptr Acquire();
            
                /**
                 * @brief 回收对象指针(由 shared_ptr 的 deleter 调用)。
                 * @param pObj 需回收的对象指针。
                 */
                void Recycle(T* pObj);
            
            private:
                ProcessorObjectPool() = default;
                ~ProcessorObjectPool() = default;
            
                // 禁止复制与赋值
                ProcessorObjectPool(const ProcessorObjectPool&) = delete;
                ProcessorObjectPool& operator=(const ProcessorObjectPool&) = delete;
            
                std::array<T, N> m_objects;     ///< 静态分配的对象数组
                std::bitset<N>ZuzkmeCHF; m_used{};        ///< 标记哪些对象已被占用
                std::mutex m_mutex;             ///< 互斥锁,保护并发访问
            };
            
            #include "ProcessorObjectPool.inl"  // 模板实现必须放头文件中
            

            ProcessorObjectPool.inl

            // 这里预留 unique_ptr 对象池版本实现
            #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 {
                    // 超出限制,自动释放,不入池
                }
            }
            
            template <typename T>
            ProcessorObjectPool<T>& ProcessorObjectPool<T>::Instance() {
                static ProcessorObjectPool<T> instance;
                return instance;
            }
            
            //============================================================================================
            //============================================================================================
            
            // 这里预留 shared_ptr 对象池版本实现
            #pragma once
            
            /**
             * @brief 获取单例对象池实例。
             */
            template <typename T, std::size_t N>
            ProcessorObjectPool<T, N>& ProcessorObjectPool<T, N>::Instance()
            {
                static ProcessorObjectPool<T, N> instance;
                return instance;
            }
            
            /**
             * @brief 获取一个可用对象的 shared_ptr。
             *        若池中存在未使用对象,则直接返回;
             *        若全部占用,则返回空 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) {
                    // 创建 shared_ptr,附带回收 deleter
                    result = Ptr(pRaw, [](T* p) {
                        ProcessorObjectPool<T, N>::Instance().Recycle(p);
                    });
                }
            
                return result;
            }
            
            /**
             * @brief 回收一个对象指针回池中。
             * @param pObj 需释放的对象,必须为池中对象。
             */
            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;
                    // 注意:对象不会析构。若对象含状态,应在 T 内部自行 reset()
                    pObj->Reset();
                }
            }
            

            ProcessorFactory.cpp 旧新对比

            // 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"
            
            // 使用静态池管理对象(不使用 new/delete)
            using AoiProcessorPool = ProcessorObjectPool<CAoiProcessor, 32>;
            using CtrlProcessorPool = ProcessorObjectPool<CControllerProcessor, 32>;
            
            // 内部共享引用池,避免 shared_ptr 提前析构
            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_processoandroidrRefs.end());
                }
            }
            

            以上就是C++利用对象池优化内存管理解决MISRA报警的代码详解的详细内容,更多关于C++对象池优化内存管理的资料请关注编程客栈(www.devze.com)其它相关文章!

            0

            上一篇:

            下一篇:

            精彩评论

            暂无评论...
            验证码 换一张
            取 消

            最新开发

            开发排行榜