如何查找 C++ 中的内存泄漏

2024-04-19

在嵌入式环境中检测 C++ 内存泄漏的好方法是什么?我尝试重载 new 运算符来记录每个数据分配,但我一定做错了什么,这种方法不起作用。还有其他人遇到过类似的情况吗?

这是 new 和 delete 运算符重载的代码。

EDIT:

完全披露:我正在寻找程序中的内存泄漏,并且我正在使用其他人编写的代码来重载 new 和 delete 运算符。我的部分问题是我不完全理解它的作用。我知道目标是记录调用者和前一个调用者的地址、分配的大小、如果我们正在分配则为 1、如果我们正在释放则为 2。加上正在运行的线程的名称。

感谢您的所有建议,我将尝试工作中有人建议的不同方法。如果它有效,我会将其发布在这里。

再次感谢所有一流的程序员花时间回答。

StackOverflow 太棒了!

结论

感谢所有的答案。不幸的是,我不得不转向另一个更紧迫的问题。这次泄漏仅发生在极不可能的情况下。我对放弃它感到很糟糕,如果我有更多时间,我可能会再回去。我选择了我最有可能使用的答案。

#include <stdlib.h>
#include "stdio.h"
#include "nucleus.h"
#include "plus/inc/dm_defs.h"
#include "plus/inc/pm_defs.h"

#include "posix\inc\posix.h"

extern void* TCD_Current_Thread;
extern "C" void rd_write_text(char * text);
extern PM_PCB * PMD_Created_Pools_List;

typedef struct {
    void* addr;
    uint16_t size;
    uint16_t flags;
} MemLogEntryNarrow_t;

typedef struct {
    void* addr;
    uint16_t size;
    uint16_t flags;
    void* caller;
    void* prev_caller;
    void* taskid;
    uint32_t timestamp;
} MemLogEntryWide_t;

//size lookup table
unsigned char MEM_bitLookupTable[] = {
 0,1,1,2,1,2,2,3,1,2,2,3,1,3,3,4
};

//#pragma CODE_SECTION ("section_ramset1_0")
void *::operator new(unsigned int size)
{
   asm(" STR R14, [R13, #0xC]");  //save stack address temp[0]
   asm(" STR R13, [R13, #0x10]");  //save pc return address temp[1]

   if ( loggingEnabled )
   {
      uint32_t savedInterruptState;
      uint32_t currentIndex;

      // protect the thread unsafe section.
      savedInterruptState = NU_Local_Control_Interrupts(NU_DISABLE_INTERRUPTS);

      // Note that this code is FRAGILE.  It peeks backwards on the stack to find the return
      // address of the caller.  The location of the return address on the stack can be easily changed
      // as a result of other changes in this function (i.e. adding local variables, etc).
      // The offsets may need to be adjusted if this function is touched.
      volatile unsigned int temp[2];

      unsigned int *addr = (unsigned int *)temp[0] - 1;
      unsigned int count = 1 + (0x20/4);   //current stack space ***

      //Scan for previous store
      while ((*addr & 0xFFFF0000) != 0xE92D0000)
      {
         if ((*addr & 0xFFFFF000) == 0xE24DD000)
         {
            //add offset in words
            count += ((*addr & 0xFFF) >> 2);
         }
         addr--;
      }

      count += MEM_bitLookupTable[*addr & 0xF];
      count += MEM_bitLookupTable[(*addr >>4) & 0xF];
      count += MEM_bitLookupTable[(*addr >> 8) & 0xF];
      count += MEM_bitLookupTable[(*addr >> 12) & 0xF];

      addr = (unsigned int *)temp[1] + count;
      // FRAGILE CODE ENDS HERE

      currentIndex = currentMemLogWriteIndex;
      currentMemLogWriteIndex++;

      if ( memLogNarrow )
      {
         if (currentMemLogWriteIndex >= MEMLOG_SIZE/2 )
         {
            loggingEnabled = false;
            rd_write_text( "Allocation Logging is complete and DISABLED!\r\n\r\n");
         }
         // advance the read index if necessary.
         if ( currentMemLogReadIndex == currentMemLogWriteIndex )
         {
            currentMemLogReadIndex++;
            if ( currentMemLogReadIndex == MEMLOG_SIZE/2 )
            {
               currentMemLogReadIndex = 0;
            }
         }

         NU_Local_Control_Interrupts(savedInterruptState);

         //Standard operator 
         //(For Partition Analysis we have to consider that if we alloc size of 0 always as size of 1 then are partitions must be optimized for this)
         if (size == 0) size = 1;

         ((MemLogEntryNarrow_t*)memLog)[currentIndex].size = size;
         ((MemLogEntryNarrow_t*)memLog)[currentIndex].flags = 1;    //allocated

         //Standard operator
         void * ptr;
         ptr = malloc(size);

         ((MemLogEntryNarrow_t*)memLog)[currentIndex].addr = ptr;

         return ptr;
      }
      else
      {
         if (currentMemLogWriteIndex >= MEMLOG_SIZE/6 )
         {
            loggingEnabled = false;
            rd_write_text( "Allocation Logging is complete and DISABLED!\r\n\r\n");
         }
         // advance the read index if necessary.
         if ( currentMemLogReadIndex == currentMemLogWriteIndex )
         {
            currentMemLogReadIndex++;
            if ( currentMemLogReadIndex == MEMLOG_SIZE/6 )
            {
               currentMemLogReadIndex = 0;
            }
         }

         ((MemLogEntryWide_t*)memLog)[currentIndex].caller = (void *)(temp[0] - 4);
         ((MemLogEntryWide_t*)memLog)[currentIndex].prev_caller = (void *)*addr;
         NU_Local_Control_Interrupts(savedInterruptState);
         ((MemLogEntryWide_t*)memLog)[currentIndex].taskid = (void *)TCD_Current_Thread;
         ((MemLogEntryWide_t*)memLog)[currentIndex].size = size;
         ((MemLogEntryWide_t*)memLog)[currentIndex].flags = 1;    //allocated
         ((MemLogEntryWide_t*)memLog)[currentIndex].timestamp = *(volatile uint32_t *)0xfffbc410;   // for arm9

         //Standard operator
         if (size == 0) size = 1;

         void * ptr;
         ptr = malloc(size);

         ((MemLogEntryWide_t*)memLog)[currentIndex].addr = ptr;

         return ptr;
      }
   }
   else
   {
       //Standard operator
       if (size == 0) size = 1;

       void * ptr;
       ptr = malloc(size);

       return ptr;
   }
}
//#pragma CODE_SECTION ("section_ramset1_0")
void ::operator delete(void *ptr)
{
   uint32_t savedInterruptState;
   uint32_t currentIndex;

   asm(" STR R14, [R13, #0xC]");  //save stack address temp[0]
   asm(" STR R13, [R13, #0x10]");  //save pc return address temp[1]

   if ( loggingEnabled )
   {
      savedInterruptState = NU_Local_Control_Interrupts(NU_DISABLE_INTERRUPTS);

      // Note that this code is FRAGILE.  It peeks backwards on the stack to find the return
      // address of the caller.  The location of the return address on the stack can be easily changed
      // as a result of other changes in this function (i.e. adding local variables, etc).
      // The offsets may need to be adjusted if this function is touched.
      volatile unsigned int temp[2];

      unsigned int *addr = (unsigned int *)temp[0] - 1;
      unsigned int count = 1 + (0x20/4);   //current stack space ***

      //Scan for previous store
      while ((*addr & 0xFFFF0000) != 0xE92D0000)
      {
         if ((*addr & 0xFFFFF000) == 0xE24DD000)
         {
            //add offset in words
            count += ((*addr & 0xFFF) >> 2);
         }
         addr--;
      }

      count += MEM_bitLookupTable[*addr & 0xF];
      count += MEM_bitLookupTable[(*addr >>4) & 0xF];
      count += MEM_bitLookupTable[(*addr >> 8) & 0xF];
      count += MEM_bitLookupTable[(*addr >> 12) & 0xF];

      addr = (unsigned int *)temp[1] + count;
      // FRAGILE CODE ENDS HERE

      currentIndex = currentMemLogWriteIndex;
      currentMemLogWriteIndex++;

      if ( memLogNarrow )
      {
         if ( currentMemLogWriteIndex >= MEMLOG_SIZE/2 )
         {
            loggingEnabled = false;
            rd_write_text( "Allocation Logging is complete and DISABLED!\r\n\r\n");
         }
         // advance the read index if necessary.
         if ( currentMemLogReadIndex == currentMemLogWriteIndex )
         {
            currentMemLogReadIndex++;
            if ( currentMemLogReadIndex == MEMLOG_SIZE/2 )
            {
               currentMemLogReadIndex = 0;
            }
         }

         NU_Local_Control_Interrupts(savedInterruptState);

         // finish logging the fields.  these are thread safe so they dont need to be inside the protected section.
         ((MemLogEntryNarrow_t*)memLog)[currentIndex].addr = ptr;
         ((MemLogEntryNarrow_t*)memLog)[currentIndex].size = 0;
         ((MemLogEntryNarrow_t*)memLog)[currentIndex].flags = 2;    //unallocated
      }
      else
      {
         ((MemLogEntryWide_t*)memLog)[currentIndex].caller = (void *)(temp[0] - 4);
         ((MemLogEntryWide_t*)memLog)[currentIndex].prev_caller = (void *)*addr;

         if ( currentMemLogWriteIndex >= MEMLOG_SIZE/6 )
         {
            loggingEnabled = false;
            rd_write_text( "Allocation Logging is complete and DISABLED!\r\n\r\n");
         }
         // advance the read index if necessary.
         if ( currentMemLogReadIndex == currentMemLogWriteIndex )
         {
            currentMemLogReadIndex++;
            if ( currentMemLogReadIndex == MEMLOG_SIZE/6 )
            {
               currentMemLogReadIndex = 0;
            }
         }
         NU_Local_Control_Interrupts(savedInterruptState);

         // finish logging the fields.  these are thread safe so they dont need to be inside the protected section.
         ((MemLogEntryWide_t*)memLog)[currentIndex].addr = ptr;
         ((MemLogEntryWide_t*)memLog)[currentIndex].size = 0;
         ((MemLogEntryWide_t*)memLog)[currentIndex].flags = 2;    //unallocated
         ((MemLogEntryWide_t*)memLog)[currentIndex].taskid = (void *)TCD_Current_Thread;
         ((MemLogEntryWide_t*)memLog)[currentIndex].timestamp = *(volatile uint32_t *)0xfffbc410;   // for arm9
      }

      //Standard operator
      if (ptr != NULL) {
         free(ptr);
      }
   }
   else
   {
      //Standard operator
      if (ptr != NULL) {
        free(ptr);
      }
   }
}

如果你正在运行Linux,我建议尝试Valgrind http://www.valgrind.org/.

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何查找 C++ 中的内存泄漏 的相关文章

  • C++ win32设置光标位置

    我知道要使用哪个功能 但我无法让它正常工作 我用了SetCursorPos 唯一的问题是它将光标设置为屏幕坐标而不是窗口坐标 我也尝试过ScreenToClient 但它并没有起作用 这是我的代码 pt x 113 pt y 280 Scr
  • C# 中的简单获取字符串(忽略末尾的数字)

    我认为正则表达式太过杀伤力 而且它需要我一些时间来编写一些代码 我想我现在应该学习 因为我知道一些正则表达式 分隔字母数字字符串中的字符串的最简单方法是什么 它将永远是 LLLLDDDDD 我只想要字母 l 通常只有 1 或 2 个字母 T
  • LINQ TO ENTITY 无法与枚举类型进行比较

    下面是枚举叶子 public enum Leaves Annual 0 Medical 1 Hospitalization 2 Unpaid 3 下面是linq查询 public ActionResult ApproveLeave int
  • 在opencv中保存帧而不压缩

    我正在尝试使用写 OpenCV 函数 我想保存帧 TIFF扩大 我遇到的问题是保存的图像被压缩 所以我无法使用它们 知道如何摆脱这种压缩吗 提前致谢 不要介意西奇说的话 TIFF 标志通过 LZW 压缩硬编码在 opencv 二进制文件中
  • 在运行时配置 ASP.NET 会话状态

    我们有一个使用 SQL Server 会话状态的 ASP NET 网站 状态配置在Web config like
  • Windows Server / Datacenter:设置 CPU 关联性 > 64 个核心

    SetThreadAffinityMask 允许为 64 个逻辑核心 处理器 设置关联掩码 但是 Windows Datacenter 最多可以有 64 个 CPU 每个 CPU 都有多个内核 请参阅here http social tec
  • 为什么 C++11/Boost `unordered_map` 在擦除时不重新散列?

    我想知道为什么 C 11 和 Boost 的 hashmap 在通过迭代擦除元素时不会调整大小 即使这在技术上不是内存泄漏 我认为这可能是应用程序中的一个严重问题 这对我来说是一个隐藏的问题 很难追踪它 并且它实际上可能会影响许多应用程序
  • boost::unordered_map 是...有序的吗?

    我有一个 boost unordered map 但它看起来是有序的 给我一种压倒性的 你做错了 的感觉 为什么输出是这样的 我希望底层的哈希算法能够随机化这个顺序 include
  • Clang 使用 -nostdlib 生成崩溃代码

    我正在尝试为可执行文件设置自己的运行时环境 但无法使用 clang v3 4 1ubuntu1 目标 x86 64 pc linux gnu 来生成没有段错误的可执行文件 我已将问题简化为以下内容 如果我有一个文件 crt1 c 除了满足
  • 将 size_t 变量添加到指针

    我想向指针添加 size t 类型 有些像这样 void function size t sizeA size t sizeB void pointer pointer malloc sizeA pointer pointer sizeB
  • 使用 .NET Core Razor Pages 将文件下载到浏览器

    使用 ASP NET Razor Pages 我尝试将文件下载到浏览器 在页面 html 中 使用这样的链接效果很好 href DownloadableFiles testB csv download newname gt Download
  • 委托:方法名称预期错误

    我正在尝试让以下简单的委托示例正常工作 根据我从中取出的一本书 应该没问题 但我得到了Method name expected error namespace TestConsoleApp class Program private del
  • 二叉树实现C++

    二叉树插入 include stdafx h include
  • C# SerialPort BaseStream ReadAsync - CancellationToken 从未取消?

    我尝试以异步方式从串行端口读取数据 请记住操作所花费的时间不得超过指定的时间段 我使用的代码 private async Task
  • 产量回报延迟迭代问题

    我知道yield return 利用了延迟加载 但我想知道我是否可能滥用迭代器或者很可能需要重构 我的递归迭代器方法返回给定的所有祖先PageNode包括pageNode itself public class PageNodeIterat
  • ASP.NET MVC - 路由 - 具有文件扩展名的操作

    有没有办法实现调用URLhttp mywebsite myarea mycontroller myaction xml这基本上是 假 请求文件 但结果将是一个为动态创建的文件提供服务的操作操作 我试过这个 context MapRoute
  • 使用C#在SQL Server上执行sql文件

    我有很多程序 视图 函数等文件 我想在 SQL Server 2005 2008 上的适当数据库中执行这些文件 创建组件 还有一点是我想使用 C 来执行它们 另一点需要提及的是 我希望应用程序也可以在远程 SQL Server 上执行此文件
  • 如何将 typedef 结构传递给函数?

    此刻我正在努力 void avg everything 但这给了我错误 error subscripted value is neither array nor pointer 当我今天早些时候收到此错误时 这是 因为我没有正确地将 2D
  • Web 服务无法使用 GAC 中的类型创建类型错误

    遇到一个不寻常的问题时 我似乎喜欢做一些不常见的事情 我有一个复合控件 它检查给定的 Web 服务文件是否存在于我的应用程序的根目录中 如果不存在 它会在标记中创建带有必要指令的文件以进行滚动 如下所示 反过来 它被保存到输出中 完成此步骤
  • 为什么我能够使用无效的类指针进行函数调用

    在下面的代码片段中 虽然指针未初始化 但调用仍然成功 temp ptr ptr gt func2 是C 语言特性的问题 还是VC 6编译器的作弊 class temp public temp a 9 int func1 return a b

随机推荐

  • CPython的静态对象地址和碎片

    I read 对于Python来说 if x 是存储x的内存地址 这是给定的id对象的属性永远不会改变 这意味着对象在其生命周期中始终存储在给定的内存地址中 这就引出了一个问题 虚拟 内存碎片怎么样 说一个物体A位于地址 1 有id1 占用
  • IIS7的工作进程是什么?

    我正在尝试在 Visual Studio 2008 中执行 附加到进程 进行调试 但我无法弄清楚要附加到哪个进程 帮助 事实上它仍然是 w3wp exe 您需要检查 显示所有会话中的进程 让它显示的选项 这也让我困惑了一段时间
  • 如果不调用notify(),等待线程会发生什么?

    如果不调用notify 等待线程会发生什么 这是虚假唤醒吗 If a waiting Thread is not notified通过致电notify or notifyAll 在所述线程正在等待的对象上 则可能会发生以下任一情况 the
  • Chrome 调试协议:HeapProfiler.getHeapSnapshot 忽略回调

    我正在开发一个测试套件 作为 Chrome 扩展实现 该套件使用 Chrome Chromium 的远程调试协议以编程方式获取和分析堆快照 因为Profiler 似乎不是公共协议的一部分 我正在使用这一页 http trac webkit
  • HTML 多选框

    我只是想知道下面的表格的名称是什么 我从早上就在谷歌上搜索 HTML 表单列表 但我在任何地方都找不到这种表单 谁能告诉我这个表单的确切名称以及它是否可以在 HTML 表单中使用 我只想在我的网站中添加这种形式 它适用于 HTML 还是我应
  • 将变量传递给 Google Cloud Functions

    我刚刚在 Beta Python 3 7 运行时中使用 HTTP 触发器编写了 Google Cloud Function 现在我试图弄清楚如何在调用函数时将字符串变量传递给函数 我已阅读文档 但没有找到任何相关内容 我的触发器类似于 ht
  • 如何在光线平行且不使用光线模式的情况下运行函数?

    After sudo pip3 install ray 我创建了一个函数foo 在射线装饰器中定义 import ray ray init ray remote def foo x print x 我希望能够使用foo并行和常规模式 忽略装
  • ViewModel 和 Service 类的实例化

    我试图理解 ViewModel 和 Service 类的实例化 并将其写下来供其他人使用 请在需要的地方更正 添加 ViewModel 和服务的实例化并不是以最常见的方式完成的 这是使用反射完成的 在 TipCalc 中 您有 public
  • 在特定日期触发 UILocalNotification

    我想开火UILocalNotification在特定日期 如果我使用这段代码 NSCalendar gregorian NSCalendar alloc initWithCalendarIdentifier NSGregorianCalen
  • 尝试理解 Pytorch 的 LSTM 实现

    我有一个包含 1000 个示例的数据集 其中每个示例都有5特征 a b c d e 我想喂7LSTM 的示例 以便它预测第 8 天的特征 a 阅读 nn LSTM 的 Pytorchs 文档 我得出以下结论 input size 5 hid
  • Akka 通过可堆叠行为拦截接收

    Akka 和 Scala 新手 请根据需要随意编辑问题 以便清楚地表达我在 Scala 和 Akka 领域的意图 在展示代码片段之前 这是我想要解决的问题 我本质上想开发一个通用模块 供我的团队在使用 Akka Actor 开发应用程序时使
  • Tcl正则表达式

    set d aa1 1 set d aa2 1 set d aa3 1 set d aa4 1 set d aa5 1 set d aa6 1 set d aa7 1 set d aa8 1 set d aa9 1 set d aa10 1
  • Fortran 读取混合文本和数字

    我正在使用 Fortran 90 读取包含以下格式数据的文件 number 125 var1 2 var2 1 var3 4 number 234 var1 3 var2 5 var3 1 我尝试了以下命令并且工作正常 read 2 tem
  • Ionic Jasmine:env.stopOnSpecFailure 编译成功后不是函数

    将 Ionic 与 jasmine karma 一起使用 在运行测试时 编译成功 但在 jasmine 仪表板中出现空屏幕 控制台中出现错误 以下教程 https leifwells github io 2017 08 27 testing
  • 受范数不等式约束的二次函数最小化

    我正在尝试解决以下不等式约束 给定 N 只股票的时间序列数据 我试图构建一个投资组合权重向量以最小化回报的方差 目标函数 min w T sum w s t e n T w 1 left w right leq C where w是权重向量
  • 从外部访问 Google 地图

    我有一些 javascript 代码 可以绘制 v3 GoogleMap 我想从外部访问地图对象 另一个js文件 是否有可能不创建额外的全局变量来引用地图 单独的 JS 文件在同一范围内加载和执行 因此无论您使用一个还是多个 JS 文件 都
  • 将参数从 tasklet 步骤添加到作业上下文,并在 Spring Batch 的后续步骤中使用

    目前 我使用 jobParameters 来获取 FlatFileItemReader 和 FlatFileItemWriter 的文件名 测试我的批次是可以的 但我的目标是读取某个目录中的文件 该目录中只有这个文件 并且文件名可能会改变
  • 错误:invalid_request 缺少必需参数:范围(Restify 和 Passportjs w/ Google OAuth2)

    因此 我在使用 Restify 和 Passportjs Google OAuth2 策略 时遇到了 Node js 应用程序的问题 当我使用passport authenticate 它给了我以下错误 400 这是一个错误 错误 无效 请
  • 提高Python代码的速度

    我有一些包含许多类的 python 代码 我用了cProfile发现程序运行总时间为68秒 我发现一个类中有以下函数Buyers这 68 秒中大约需要 60 秒 我必须运行该程序大约 100 次 因此速度的任何提高都会有所帮助 您能建议通过
  • 如何查找 C++ 中的内存泄漏

    在嵌入式环境中检测 C 内存泄漏的好方法是什么 我尝试重载 new 运算符来记录每个数据分配 但我一定做错了什么 这种方法不起作用 还有其他人遇到过类似的情况吗 这是 new 和 delete 运算符重载的代码 EDIT 完全披露 我正在寻