【问题标题】:Calling malloc() overwrites static table调用 malloc() 覆盖静态表
【发布时间】:2014-02-05 15:05:47
【问题描述】:

我正在研究 STM32F4 微控制器内部的 ARM Cortex M4F (M3),没有操作系统。语言是纯C。

我遇到了 malloc() 函数的问题。下面的代码使用从 SD 卡读取的全局和易失性数据表 (volatile unsigned char[] fat_sector_buffer)。在函数中,我声明了指针内存(用于从表中读取数据的结构类型为结构),并将内存分配为第二个结构,用于保存来自 RTC 的日期和时间。

问题是,当我使用 malloc() 时,内存分配在 fat_sector_buffer 上。

代码:

unsigned char fat16_update_entry()
{
uint8_t looking=1;
unsigned int i=0;
char ret=0;
Fat16Entry *data;   
DateTimeStruct *dt=malloc(sizeof(DateTimeStruct));
unsigned short time,date;
dt= read_calendar(dt); //Read calendar date and time
    ...

在 malloc 之后我得到的是: http://i.stack.imgur.com/Lv0Mn.png

为什么会发生,我该如何解决?

【问题讨论】:

  • 您能告诉我们 fat_sector_buffer 的分配方式和位置,以及您发布的代码与分配之间的关系吗?如果 malloc /really/ 是从全局堆中分配的(无需您做任何事情),则 libc 存在严重问题。如果这是正在发生的事情,我建议其他东西正在破坏堆并破坏 malloc()。你能在你的平台上运行 valgrind 吗?
  • 您好,对于 Valgrind,这是不可能的,因为这是无操作系统(嵌入式)应用程序。 fat_sector_buffer 是 unsigned char 数组,大小为 512。这不是索引出表的问题(错误位置的索引是 224)。我检查了内存配置,范围没有覆盖。
  • fat_sector_buffer 变量是内存映射变量,因此使用固定地址声明?如果是这样:这个地址真的可能会改变吗?或者你可以一起取消volatile(当然没有可能带来的优化问题)
  • 不太可能改变。事实上,之前它没有 volatile 标识符,因为这里不需要它,添加它只是为了看看它是否有帮助(它没有)。
  • 拜托,学习格式化代码,这看起来很糟糕!

标签: c pointers memory-management malloc stm32


【解决方案1】:

这篇文章没有说明 fat_sector_buffer 指向的内存是如何实际分配的,它有多大,或者它是如何被填充的。很难说它是否真的被改写了。

malloc 实际上并没有向它分配的内存写入任何内容。只需保留它并提供一个指针。

【讨论】:

  • fat_sector_buffer 是全局变量 volatile unsigned char fat_write_sector_buf[FAT_WRITE_BUFFER_SIZE];其中 FAT_WRITE_BUFFER_SIZE 等于 512。所以这不是读取/写入表索引的问题。
  • Post 表示它是一个字符数组。多大?
  • (不小心按了回车,上面写的是512)
  • @PudDog 欢迎来到 SO。您回答的可能是 cmets 中的问题。发布真实答案以获得声誉。
  • 会不会是malloc arena没有初始化或者是指向加载程序的内存?我假设 malloc 没有返回 NULL?
【解决方案2】:

根据您对上述问题的回答(您已确保 fat_sector_write_buf 已静态分配且足够大),我猜您的堆已损坏。对堆管理器说,fat_sector_write_buf 内有可用内存可供分配,这就是malloc() 返回它的原因。我猜有些东西正在覆盖堆上的指针。很遗憾您不能使用valgrind,因为它会很快找到。

因此,您将需要调试覆盖堆的任何内容。您的 libc 可能会提供一些 heap/malloc 调试,例如: http://www.gnu.org/software/libc/manual/html_node/Allocation-Debugging.html#Allocation-Debugging 虽然这将取决于您的 libc 构建。您可以(通过检查 libc 的源代码)确定堆是如何工作的,并调用一些东西来检查(在 malloc 之前),虚假块实际上是在堆上。您还可以使用远程调试来逐步检查malloc() 并找出它返回虚假值的原因。显然,这将取决于您的平台。

作为另一种可能性,您可能只是发生了内存泄漏并耗尽了内存。通常堆栈会向下增长,而堆会增长,因此超大的堆栈或堆首先遇到的就是另一个。但是,在嵌入式平台上,它很可能会命中静态数据。

【讨论】:

  • 至于泄漏,我一开始就假设了,但测试表明这几乎是不可能的。由于这个项目的性质 malloc 很少使用(在代码中使用了 20 次),所以我跟踪了所有“malloc”是否都有它们的“free”并且它们确实有。我会给你有用的,但我的声誉太低了。对不起。
  • 重新malloc,注意其他东西会通过堆分配器分配内存,例如strdup。我怀疑如果你不能使用共享 c 库 malloc 调试,你可能想使用你自己的 malloc 来调试包装现有的。
猜你喜欢
  • 2010-12-05
  • 1970-01-01
  • 1970-01-01
  • 2020-04-08
  • 1970-01-01
  • 2018-06-21
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多