记一次StackOverflow

本文记录了一次StackOverflow问题的分析过程,涉及Chromium的base模块和友商模块的交互。问题出现在base库的task_runner线程中,调用友商模块时栈溢出。通过IDA分析发现,栈在调用_alloca_probe时崩溃,原因是线程栈大小不足。在main函数和std::thread线程中调用则正常,因为栈会自动增长。调整线程栈大小为10*1024(0x2800)导致问题,但实际使用达到了0xA000,原因待进一步研究。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

概述

  1. 目前项目会使用chromium项目的base模块
  2. 在调用友商一模块时,出现StackOverflow

事件分析

  1. 在base库的task_runner线程中,调用该模块,会出现StackOverflow
  2. 在另一种std::thread创建的线程中,调用该模块,正常
  3. 在main函数中,调用该模块,正常

因此初步推断友商模块可能对base模块的task_runner水土不符?

上IDA进行分析,发现在调用 _alloca_probe函数时出现的崩溃。

参考连接:解析__alloca_probe
该函数有1个参数,表示要展开的栈的大小。

所以 _alloca_probe 是用来开栈的,也就是说,问题不在友商,而是我们,因为线程栈耗尽,而导致崩溃
在调用友商模块时,分析线程状态:

StackBase:            043a0000
StackLimit:           04396000

esp=0439ad90

根据这几个参数,可以看出:
栈大小为 0x043a0000 - 0x04396000 = 0xA000
栈剩余大小为 0x0439ad90 - 0x04396000 = 0x4D90

继续深入,在 _alloca_probe函数前,发现栈使用了 0x4908,也就是说,在调用 _alloca_probe函数前,栈中剩余空间只有 0x4D90 - 0x4908 = 0x488字节。

我们看调用 _alloca_probe函数前代码:

.text:5C5331F3                 mov     eax, 4020h
.text:5C5331F8                 call    __alloca_probe

可知,会使用 _alloca_probe函数开0x4020字节的栈,而此时栈的可用空间只有0x488字节!

那为什么在main函数(主线程)和std::thread线程调用不会崩溃?

在main函数中,观察线程栈状态:

StackBase:            00b40000
StackLimit:           00b3b000

esp=00b3f8b0

栈大小:0x00b40000 - 0x00b3b000 = 0x5000
栈剩余大小:0x00b3f8b0 - 0x00b3b000 = 0x48B0

这不科学!为什么这个可用大小更少,但是不会StackOverflow呢?
我们继续观察调用完模块后,线程栈状态:

StackBase:            00b40000
StackLimit:           00b36000

esp=00b3f8b0

栈大小:0x00b40000 - 0x00b36000 = 0xA000
栈剩余大小:0x00b3f8b0 - 0x00b36000 = 0x98B0
栈大小变大了,也变成了0xA000,那是因为栈最大只能是0xA000而我们用的太多导致的么?
于是我在调用模块前,在栈用申请一块大小为0x7000内存:

StackBase:            00500000
StackLimit:           004f6000

esp=004f8230

栈大小:0x00500000 - 0x004f6000 = 0xA000
栈剩余大小:0x004f8230 - 0x004f6000 = 0x2230

很不错,这下该崩溃了吧😁?然而事与愿违!

StackBase:            00500000
StackLimit:           004ef000

esp=004f8230

栈大小:0x00500000 - 0x004ef000 = 0x11000
栈剩余大小:0x004f8230 - 0x004ef000 = 0x9230
好家伙,又双叒叕变大了!

所以栈是会根据需要自动增长的。但是为什么task_runner线程不会呢?

最后发现同事将线程栈大小设置为10*1024。改为0就没有问题了。

那么问题又双叒叕来了,为什么栈大小设置为10*1024(0x2800),但是实际用到了0xA000呢?

情况较复杂,等有空单独研究。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值