You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

glibc2.18 PowerPC平台malloc崩溃:_int_malloc传NULL参数异常求助

malloc崩溃排查:ar_ptr为NULL却调用_int_malloc的矛盾分析

遇到malloc异常崩溃,从glibc2.18的__libc_malloc源码逻辑来看,调用_int_malloc前已经通过if(!ar_ptr) return 0;判断ar_ptr不为NULL,但gdb回溯结果显示_int_malloc的第一个参数av=0x0(NULL),出现明显矛盾。

环境信息

  • glibc版本:2.18
  • CPU架构:PowerPC

gdb回溯信息

#13 _int_malloc (av=av@entry=0x0, bytes=bytes@entry=18) at malloc.c:3300
    fb = <optimized out>
    pp = <optimized out>
    nb = 24
    idx = 1
    bin = <optimized out>
    victim = <optimized out>
    size = <optimized out>
    victim_index = <optimized out>
    remainder = <optimized out>
    remainder_size = <optimized out>
    block = <optimized out>
    bit = <optimized out>
    map = <optimized out>
    fwd = <optimized out>
    bck = <optimized out>
    errstr = 0x0
    __func__ = "_int_malloc"
#14 0x0fec80cc in __GI___libc_malloc (bytes=18) at malloc.c:2869
    ar_ptr = 0x0
    victim = <optimized out>
    hook = <optimized out>
    __func__ = "__libc_malloc"

glibc2.18对应__libc_malloc源码片段

void*
__libc_malloc(size_t bytes)
{
  mstate ar_ptr;
  void *victim;

  void *(*hook) (size_t, const void *)
    = force_reg (__malloc_hook);
  if (__builtin_expect (hook != NULL, 0))
    return (*hook)(bytes, RETURN_ADDRESS (0));

  arena_lookup(ar_ptr);

  arena_lock(ar_ptr, bytes);
  if(!ar_ptr)
    return 0;
  victim = _int_malloc(ar_ptr, bytes);
  if(!victim) {
    ar_ptr = arena_get_retry(ar_ptr, bytes);
    if (__builtin_expect(ar_ptr != NULL, 1)) {
      victim = _int_malloc(ar_ptr, bytes);
      (void)mutex_unlock(&ar_ptr->mutex);
    }
  } else
    (void)mutex_unlock(&ar_ptr->mutex);
  assert(!victim || chunk_is_mmapped(mem2chunk(victim)) ||
     ar_ptr == arena_for_chunk(mem2chunk(victim)));
  return victim;
}

矛盾原因分析

1. 内存篡改(栈/堆 corruption)

在arena_lookup(ar_ptr)获取有效ar_ptr后,到if(!ar_ptr) return 0;之间的代码(比如arena_lock执行过程)可能触发了内存越界写入,直接篡改了栈上的ar_ptr变量,使其变为NULL。PowerPC架构的栈布局或编译器对栈变量的分配方式,可能让ar_ptr更容易被相邻内存的越写影响。

2. 编译器优化导致逻辑重排

虽然源码中先判断if(!ar_ptr)再调用_int_malloc,但开启O2/O3等优化级别时,编译器可能对代码进行重排:比如认为ar_ptr在判断后不会被修改,提前生成_int_malloc的调用指令,或者将判断逻辑合并到其他代码中,导致实际执行时绕过了NULL检查。

3. 多线程竞态条件

多线程环境下,arena的全局状态可能被其他线程破坏:比如其他线程在当前线程的arena_lock到if(!ar_ptr)之间,修改了arena相关的内存,导致当前线程的ar_ptr变为NULL。尽管glibc的arena机制自带锁,但不排除PowerPC架构下锁实现存在bug,或者自定义内存钩子、第三方库修改了arena逻辑,破坏了锁的有效性。

4. 栈帧破坏导致回溯失真

实际ar_ptr不为NULL,但栈帧被内存篡改破坏,导致gdb读取参数时获取到错误的NULL值。不过这种情况概率较低,因为回溯中__libc_malloc的ar_ptr也显示为0x0,说明栈中该变量确实被设置为NULL。

内容的提问来源于stack exchange,提问作者shuaishuai

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.16 13:15:21