如何获得一个内存破坏的根本原因在嵌入式环境?

问题描述 投票:3回答:7

我在嵌入式环境中检测到了一个内存破坏(我的计划是在机顶盒上运行了专有的操作系​​统)。但我无法得到它的根本原因。存储器腐败,本身而言,发射和多次退出应用的压力测试后检测。让我不能设置一个内存断点,因为corruptued变量变化的每一个应用程序启动时它的地址,有什么想法抓住这个腐败的根本原因?

(A存储器断点是打破当环境改变给存储器地址的值点发射)

还注意到,我的所有的软件是用C语言开发的。

谢谢你的帮助。

memory embedded corruption
7个回答
6
投票

这些总是在嵌入式系统中的疑难问题,并没有简单的答案。一些技巧:

  • 看看内存获取与破坏的价值。这可以给出一个明确的暗示。
  • 看看数据结构的内存损坏旁边。
  • 看看是否有在内存损坏的模式。是否总是在相似的地址?
  • 看看你是否可以设置在运行时内存断点。
  • 请问嵌入式系统允许沙盒内存区域?建立沙箱来保护您的数据存储。

祝好运!


4
投票

其中存储的数据和它是如何通过参与这两个进程访问?

如果结构被分配掉了堆,尝试分配一个更大的块和前后结构之后把大的保护区域。这应该给你它是否已溢出到相同的配置为你的结构周围堆分配的一个想法。如果你发现你的周围结构的存储是不变的,只有结构本身损坏则表明腐败是由一些具有你的结构的位置有一定的了解,而不是随机存储器跺脚引起的。

如果结构是在数据部中,检查你的连接图输出,以确定在结构附近存在其它数据。检查是否这些也被损坏,介绍保护区,并检查问题是否遵循结构,如果你强迫它移动到不同的位置。这再次表明是否损坏是由一些与你的结构的位置的知识造成的。

也可以通过从所述堆切换数据为数据部分或反之亦然测试此。

如果你发现在别处移动,或引入保护区后的结构不再损坏,您应检查连接地图或跟踪堆,以确定就在附近,还有什么其他的数据,并检查访问的缓冲区溢出的领域。

您可能会发现,虽然,这个问题确实跟随着它所处的结构。如果是这种情况,那么审核所有周围的结构引用代码。和之前每次访问后检查的内容。

要检查是否损坏正被另一个过程中造成或中断处理程序中添加钩子到每个任务切换及前后各有ISR被调用。钩子应该检查是否内容已损坏。如果他们有,你将能够识别哪个进程或中断负责。

如果结构读过到本地进程堆栈,尝试增加进程堆栈并确认是否有超支阵列等时有发生。即使不读入堆栈时,很可能,你将有一个指向它的堆栈在某一点上。检查所有子功能称为在附近的可能导致指针被代码无关块错误地使用堆栈问题或相似的。

另外还要考虑编译器或RTOS是否可能发生故障。请尝试关闭编译器优化,否则要求检查生成的代码。同样考虑是否可能是由于您的专有RTOS一个错误的上下文切换。

最后,如果您共享与其他硬件设备或CPU内存和已启用数据高速缓存,请确保您使用通过非高速缓存的存取或类似的策略照顾这一点。


4
投票

是的,这些问题可能会很难跟踪与调试。

一些想法:

  • 做定期code reviews(不是很快在跟踪一个特定的错误,但有价值的捕一般这样的问题)
  • 注释掉或#if 0出部分代码,然后运行切下来的应用程序。尝试注释出不同的部分,试图缩小在错误发生的代码的哪个部分。
  • 如果你的架构可以让你轻松的运行,通过排除法禁用某些进程/任务也许您可以缩小是哪个进程导致的错误。
  • 如果你的操作系统是合作多任务如循环赛(这将是太难我认为对于抢占式多任务):将代码添加到“拥有”结构的任务结束后,保存结构的“检查”。这种检查可能是一个的memcpy(如果你有时间和空间),或CRC。然后,所有其他任务运行后,添加一些代码来验证结构相比,节省检查。这将检测到任何变化。

2
投票

我被你的问题,假设你的意思是你怀疑专有代码的某些部分是造成问题。

我已经处理了使用的是什么同事这么高雅的所谓的“遗书”在过去的一个类似的问题。我将分配能够存储一个数字,被破坏的结构的拷贝的一个缓冲器。我会用这个缓冲区像一个圆形的列表,定期存储结构的当前状态的副本。如果检测到损坏的“遗书”将被倾倒到一个文件或串行输出。这会给我什么改变,以及如何,并通过增加日志的频率,我能够缩小腐败行动的好照片。

根据您的操作系统,你可以通过查看所有正在运行的进程,看到哪些是当前占用一个信号量来检测到损坏的反应(你正在使用某种形式的共享内存的访问控制机制,对吧?)。通过采取这一数据的快照也一样,你或许可以登录罪魁祸首损坏您的数据之前抓住了锁。沿着相同的路线,尽量保持锁止到所述共享存储器区域的时间的长度荒谬,看看是否有问题的程序抱怨。有时,他们会给拥有它可以帮助你调查的重要信息(例如,行号,函数名,或代码偏移量问题的程序)的错误信息。

如果您准备好了做一个小的连接器功夫,你可以最有可能相对于程序的起始地址指定任何静态分配数据的地址。这可能给你一个一致的,足够的内存地址来设置存储器断点。

不幸的是,这样的问题并不容易调试,特别是如果你没有来源的一个或多个参与的程序。如果你能得到足够的信息来了解您的数据是如何被损坏,您可以调整结构,期望和预计腐败(与代码不完全符合规范或标准的工作时,有时需要) 。


1
投票

您检测内存损坏。你能不能更具体的怎么样?它是一个核心转储崩溃,例如?

通常情况下,操作系统将完全免费的所有资源和处理程序具有程序退出时,正常或以其他方式。即使是专有操作系统管理得到这个权利,但它不是一个给定的。

因此,间歇性的问题会显得紧张之后被触发,但仅仅是偶然,还是可以在驱动程序或程序与通信等过程的初始化,或可能是坏的错误处理周围说,失败的内存分配时,操作系统本身是下压力如懒的整理了封闭的计划。

在自定义的malloc / realloc的/无代理功能,甚至将电栅栏式的自定义分配器printfs输出可能有助于如果那样简单缓冲区溢出。


1
投票

使用的内存分配的调试工具,如ElectricFence,dmalloc等 - 以最低的,他们可以(免费后超支,欠载,甚至在某些情况下,写(或读))搭上简单的错误,最适度复杂的,等我个人最喜欢的是dmalloc。


1
投票

专有的操作系​​统可能会限制你的选择一点。你也许能够做的一件事是运行台式机上的问题代码(假设你可以存根出特定的硬件代码),并利用现有的存在更复杂的工具(即guardmalloc,电围栏)。

您使用可包括用于检测堆损坏一些例程(glibc的那样,例如)的C库。打开那些,与任何跟踪设施,让您有沿,所以你可以看到当堆已损坏,发生了什么事。

© www.soinside.com 2019 - 2024. All rights reserved.