递归调用为何会溢出?从栈帧结构到尾递归优化的完整技术解析

打开Python解释器,输入一个简单的递归函数: def count(n): if n <= 0: return 0 return 1 + count(n - 1) print(count(10000)) 程序崩溃,抛出 RecursionError: maximum recursion depth exceeded。把同样的逻辑翻译成Scheme,却能轻松处理百万次递归调用。这不是Python的bug,而是两种语言对函数调用栈的根本性设计差异。 ...

10 min · 4672 words

函数调用约定为何如此分裂:从十六位到六十四位的四十年ABI博弈

当你在C代码中写下一行简单的函数调用result = add(a, b, c),编译器需要回答一系列问题:参数a、b、c应该放在哪里?是寄存器还是栈?如果是寄存器,用哪些?返回值result又该如何传递?调用前后谁负责保存寄存器?栈指针需要调整多少? ...

16 min · 7724 words

WebAssembly十年:从浏览器的第四种语言到「隐形」的基础设施

2017年6月,Figma工程团队在官方博客发布了一组测试数据:将C++渲染引擎从asm.js迁移到WebAssembly后,大型设计文档的加载时间缩短了3倍。这是WebAssembly早期最有力的一次「实力展示」,也让很多人相信这项技术将彻底改变Web开发的格局。 ...

9 min · 4410 words

别被编译器骗了:为什么你的安全检查代码可能正在被悄悄删除

Google Native Client团队曾遭遇过一次令人后背发凉的漏洞:沙箱逃逸保护机制被编译器悄无声息地删除了。问题出在一行看似无害的代码重构:将 aligned_tramp_ret = tramp_ret & ~(nap->align_boundary - 1) 改成了 return addr & ~(uintptr_t)((1 << nap->align_boundary) - 1)。 ...

8 min · 3607 words