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

两段看似相同的字典树代码为何触发SIGSEGV?求错误原因

为什么直接用*str-'0'作为数组下标会触发段错误,而先存变量就没事?

这是个典型的C++未定义求值顺序导致的坑!我来给你一步步拆解清楚:

两段代码的核心差异

你遇到的问题根源其实在return语句里的表达式,你标记的if判断行只是错误爆发的地方:

原代码的风险点

原代码的return语句是:

return chd[*str-'0']->add(++str);

这里的致命问题是:表达式中的*str(获取当前字符)和++str(移动指针到下一个字符)的求值顺序是未定义的。C++标准并没有规定这两个操作的执行顺序,编译器可以自由选择先执行哪一个。

如果编译器先执行++str,再计算*str-'0':

  1. 比如处理第一个字符'9'时,++str会把指针直接移动到'1'
  2. 此时*str-'0'得到的是1,而不是预期的9
  3. 因为chd[1]还没有被初始化(是nullptr),你会调用nullptr->add(...)
  4. 进入add函数后,this指针是无效的(nullptr),此时访问this->chd(也就是chd[*str-'0'])就会触发段错误(SIGSEGV)

修改后代码的安全点

你修改后先把当前字符的下标存到变量i中:

int i = *str-'0';
// ...
return chd[i]->add(++str);

这里i的值在++str执行前就已经确定了,不管编译器什么时候执行++str,chd[i]指向的都是当前字符对应的正确节点,不会出现访问nullptr的情况,自然不会触发段错误。

为什么错误会在if (chd[*str-'0'] == 0)爆发?

当你调用nullptr->add(...)时,成员函数add会被执行(因为成员函数的地址是编译期确定的,不需要this指针来查找),但函数内部访问任何成员变量(比如chd数组)时,需要通过this指针来定位内存,而this是nullptr,所以访问chd就会触发内存访问错误,也就是你看到的段错误。

额外的小建议

  1. 尽量避免在同一个表达式中同时修改指针/变量和读取它的值,这很容易触发未定义行为
  2. C++中字符串字面量应该用const char*接收,而不是char*(虽然很多编译器兼容,但这是不符合标准的写法)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.12 04:02:24