如何为大型项目制作一个简单的工具来检测Linux中的双倍空闲或内存溢出
How to make a simple tool to detect double free or memory overflow in Linux for a large project?
我有一个运行Linux的大型嵌入式项目。此外,它还运行着各种进程和线程。我不能记录所有的malloc和新调用,因为这会使嵌入式机顶盒变得迟钝。此外,由于互斥超时或其他原因,迟缓可能会导致崩溃。因此,我想制作一个工具来帮助调试与内存相关的问题,比如内存溢出。
例如,当您执行一个4字节的malloc时。但是,你写的是8个字节。这可能会在所分配的其他数据块上产生问题。数据头的另一块可以被篡改。因此,free()将失败或崩溃。我如何制作一个工具来检测这样的问题。此外,还有一个追踪内存泄漏的工具。有办法做到这一点吗?我不能使用valgrind,因为它会减慢我的STB。因此,我想开发我的工具,可以检查内存头损坏或内存泄漏。根据我的选择,它可以进行内存损坏检查或内存泄漏检测。此外,它应该是一个轻量级。
首先,可能没有办法将其称为"简单"。其次,如果您使用C++,我强烈建议不要使用malloc/free,而是使用new/delete。覆盖这些运算符的选项要灵活得多。
C++提供了许多工具来提高内存安全性:
- 智能指针(性能成本确实值得安全改进)
- 将事物封装在类中。例如,如果您使用std::array::at(i),那么如果您的访问超出范围,它将抛出异常。参考
- 最后,在代码中正确使用断言可以在很大程度上捕捉错误
我的观点只是,您不应该依赖调试工具来否定使用良好C++编程方法的必要性。
好的,所以现在下一步你需要覆盖新的和删除。谷歌搜索将提供许多方法来做到这一点。链接1对于您的问题,全局重载delete/new可能更有意义。
缓冲区溢出检测这是问题的第一部分。您需要做的是在新的重载指令中分配额外的内存,以便在内存前后有一些内存缓冲区,然后只返回中间部分。缓冲区的大小由您选择。伪代码:
inline void* operator new(size_t s)
{
void* mem = malloc(s+2*BUFFER);
memset(mem,0x5A,s+2*BUFFER);
return (mem+BUFFER)
}
在未来的某个阶段,您需要检查BUFFER区域是否保持0x5A的值。你可能应该在对free()的调用中这样做,但你也可以有自己的函数来做这件事,你可以定期调用它。为了加快这个过程,也许可以使用memcmp这样的函数。
内存泄漏检测检测内存泄漏并非易事。首先,我建议尽可能使用基于堆栈的对象,以避免在不需要时在堆上分配内存。关于内存泄漏的主要问题是知道某个内存块是否应该被删除。99%的内存泄漏问题可能只需使用智能指针就可以解决。然而,最难捕捉的内存泄漏之一是不断增长的数据结构。(例如一个随时间缓慢增长的链表)
首先,在重载的新malloc函数中,保留当前分配的所有内存的列表。还有一个分配内存总数的计数器。
方法1:阈值检测:
基本上,每当程序的内存使用量超过阈值时,都会报告并增加阈值。如果您的程序在继续运行的过程中继续超过阈值,则会出现问题。
方法2:比较分析:在pseudeo代码中:
Value1 = currentAmountOfMemoryUsed;
runSomeCode()
if (currentAmountOfMemoryUsed != Value1) reportProblem()
这是否可能在很大程度上取决于runSomeCode()中发生的事情,因为有些代码可以合法地"保存"一些内存,以便以后再次运行。
方法3:程序退出时的泄漏检测:
前提是,如果你的代码写得100%正确,那么在你的程序存在时,分配的每一位内存都应该被释放。这种方法并不总是可行的,因为也许你的程序需要无限期运行,而且你的程序可能会因为你的错误而在检测到之前很久就出现故障。
编译器支持在较低级别上,大多数编译器都支持进入整个内存管理系统,但处理此问题的方法100%特定于编译器/平台。例如Visual Studio C++这就是为什么我强烈建议不要直接使用malloc/free,因为这对以这种方式进行调试是有问题的,并且会破坏C++的构造函数/析构函数设计模式。
重写malloc/free然而,有一种更实际的方法可以重写malloc/firee。这是通过定义您自己的malloc/free函数来实现的。通常在调试过程中,这将使用宏在调用中包括FILE和LINE:
#ifdef NDEBUG
#define myMalloc(s) myMallocImplementation(s,__FILE__,__LINE__);
#else
#define myMalloc(s) malloc(s)
#endif
这允许您的malloc实现保存分配内存的源位置。然而,这种方法不会捕获您正在使用的库中malloc/free的使用情况。这对于新的/删除调用来说有点困难,因为它通常需要在运行时对调用堆栈进行一定的挖掘,以找出谁调用了您的new()函数,这也是编译器特有的。另请参阅:MSDN博客文章
记忆冻结考虑到我喜欢的一切,我只想提到一些在安全关键代码中非常常见的东西(如机动车辆和/或飞机等)在初始化之外,安全关键程序通常不允许使用malloc/free/new/delete。因此,所有内存分配都必须在初始化期间进行,然后一旦程序以某种方式冻结,通常malloc/free就会被冻结。之后对malloc/free的任何调用都将导致断言。在C++环境中使用这可能是一个相当大的限制,但它确实会产生非常健壮的代码。请注意,这对缓冲区溢出访问或无效指针访问问题没有任何作用。
- 如何检测 CDRom 是否是 Linux 上的 DVD
- 如何在 Linux/MacOs 平台中检测到内存泄漏?
- 如何使用选择正确检测我是在Windows还是Linux中构建C 代码
- 我可以在Linux中检测箭头键
- 如何检测和与Linux下的另一个过程进行通信
- 有没有办法在C++中检测或更改从 Windows 到 Linux 的 EOL 格式
- 在 Linux 下的 Qt,如何检测一个进程已经在运行
- 如何在非网关接口 Linux 上检测互联网连接
- Linux中的SDL桌面分辨率检测
- 在发布模式下检测到缓冲区溢出 - linux
- 检测Linux C 上的键盘和密钥事件
- Linux-检测闲置
- Qt::如何识别/检测系统是否被Linux中的其他系统远程访问
- TCP套接字:在发送之前检测对等方是否已关闭?(Linux)
- 如何为大型项目制作一个简单的工具来检测Linux中的双倍空闲或内存溢出
- 在Linux中检测到从pipe/fifo的另一端读取的尝试
- 检测 Linux 上多线程C++应用程序中的堆栈溢出/覆盖
- Linux C++ 检测用户外壳(csh,bash等)
- 检测 HDMI 电缆何时插入桌面 Linux
- 检测 Linux 下的 32 位进程是否在 64 位环境中运行