当前位置:首页 > 科技资讯 > 正文

C++的未来:在不确定的技术浪潮中寻找确定性

“在追求物理极限性能的同时,C++仍是无可替代的选择。”

随着Rust的崛起和AI编程的兴起,C++这座历经四十载风雨的编程大厦,正面临前所未有的挑战。

内存安全漏洞是否真无解?

AI生成的代码是福音还是隐患?

当“未定义行为”从优化基石变为安全梦魇,C++标准委员会将如何应对?

带着这些深刻问题,在2025全球C++及系统软件技术大会的采访间,奇点智能研究院首席技术咨询师吴咏炜与Adobe首席科学家、C++标准委员会资深委员David Sankel展开了一场深度对话。

C++的未来:在不确定的技术浪潮中寻找确定性 C++ Rust 内存安全 未定义行为 第1张

左:吴咏炜,右:David Sankel

David Sankel直面每一个敏感话题。从揭示“新代码比旧代码更脆弱”的反直觉真相,到坦陈C++在工具链生态上被Rust“降级打击”的无奈,再到对AI编程助手“既依赖又怀疑”的矛盾心态,Sankel以顶尖语言设计者的视野,为我们还原了一个真实、复杂且充满生命力的C++世界。

这不仅是一场技术探讨,更是一次思想碰撞,探讨如何在不确定的技术浪潮中寻找确定性。

以下为对话全文:

吴咏炜:嗨David,欢迎来到全球C++及系统软件技术大会的采访间。请先向大家打个招呼。

David Sankel:大家好。很高兴来到这里,感觉特别棒。

吴咏炜:首先,我们来探讨一下现代代码与遗留系统的安全性问题。你在本次大会演讲中提到一个耐人寻味的趋势:大多数内存安全漏洞源于新编写的代码,而非遗留系统。你认为这是什么原因造成的?是语言复杂性、现代特性误用、开发者经验不足,还是工程流程和工具链存在缺口?

David Sankel:这个现象的核心在于“代码硬化”的过程,它通常只发生在长期承受巨大安全审查压力的旧代码上。

以Zlib这个古老的C语言库为例,多年来,无数人都在试图攻破它。在这个过程中,绝大多数潜在漏洞已被挖掘并修复。只要对抗性压力持续存在,代码就会随着时间变得越来越坚固。

漏洞出现在新代码中的原因,仅仅是因为这些代码还没有时间在那种对抗性压力下“历练”。这完全是关于漏洞生存周期的问题。旧Zlib代码刚出来时也有许多漏洞,但随着时间的推移,这些漏洞逐渐减少。这更像是公共领域软件的一种现象,因为人们总是在试图攻击它。

因此,这主要是一个成熟度的问题:代码越成熟,Bug自然越少。

这种现象积极的一面是,我们不需要回头处理所有代码库。例如Adobe Photoshop有6800万行代码,我们无法回头修复所有旧代码。但好消息是,我们不必像防范新代码那样焦虑旧代码。我们将防御重点集中在新引入的代码上,这让内存安全问题从“不可能完成的任务”变成了“可控的工程问题”。

吴咏炜:我们知道,在C语言中,由于开发者需要直接管理定长数组和原始内存,缓冲区溢出等问题非常普遍。理论上,C++引入了许多现代特性,应大幅降低此类风险。但现实数据表明,我们仍面临大量内存相关漏洞。为什么在机制更完善的C++中,这类问题依然无法根除?

David Sankel:C++确实通过引入高级抽象降低了内存安全漏洞的发生频率,但这并不意味着它从根本上消除了隐患。

工程师仍然容易写出导致越界访问的代码。过去是对C风格数组的越界,现在则是对std::vector的越界访问——本质依然是相同的内存安全问题。使用未初始化变量的风险在C++中也并未消失。

归根结底,C++继承了C语言的底层内存模型和许多“不安全”的基因。只要这些从C语言遗留下来的底层机制仍然被允许使用,或者现代容器的使用方式缺乏强制性的安全约束,内存安全漏洞的温床就依然存在。

吴咏炜:相比十年前,我们现在拥有强大得多的动态分析工具。例如Memory Sanitizer (MSan)、Address Sanitizer (ASan)、Thread Sanitizer (TSan)以及Undefined Behavior Sanitizer (UBSan)等等。

David Sankel:你说得完全正确。问题是:这些工具是否在C++生态系统中被普遍使用了?遗憾的是,我认为答案是否定的。

阻碍工具普及的原因可分为两类:一类是主观因素——例如开发者缺乏认知或不在乎;但更关键的是客观门槛:这些工具的配置成本极高。

要让这套Sanitizer组合在构建系统中完美运行,需要巨大的工程代价。这通常要求你在项目启动之初就具备极高的前瞻性并投入资源去配置基础设施。但在项目早期,你甚至不知道它能否存活下去,往往无暇顾及这些。

这就导致了一个典型的“成功悖论”:等到你的开源库大获成功、被广泛采用时,它可能一直是在没有Sanitizer保护的“裸奔”状态下开发的。突然之间,潜伏的漏洞随着你的库扩散到整个生态链。

更糟糕的是,即便你现在亡羊补牢加上防护,下游用户依然可能在使用你的旧版本代码。为什么?因为在C++生态中,依赖管理和版本升级是一项昂贵的工程活动。用户往往因为升级成本过高而停留在有漏洞的旧版本上。

吴咏炜:但我认为你的论点可能是我们不想用C++写新代码。但其实我们可以在新代码中使用这些工具而不是在旧代码中。因为旧代码可能有更多兼容性问题。在新代码中我们绝对可以使用新工具。

David Sankel:你的论点建立在一个关键假设之上:即只要使用这些新工具就能解决所有或至少绝大部分的内存安全漏洞。诚然它们能大幅缓解问题但现实数据却给我们泼了一盆冷水。

让我们看看Google的数据。在Android系统开发中他们拥有世界顶级的工程师团队并且在C++开发流程中强制启用了所有的Sanitizer和最佳实践。即便武装到这种程度他们依然持续发现C++代码中的内存漏洞。

更令人震惊的对比来自于他们引入Rust之后的数据:在同样的严苛标准下C++代码产生的内存安全漏洞数量几乎是Rust代码的1000倍。

这是一个非常“硬”的数据它揭示了一个残酷的现实:工具只能缓解症状却无法根治病灶。

如果单靠打开Sanitizer就能彻底解决问题那么Google根本不需要大费周章引入新语言。既然连拥有最强技术实力的Google都无法在C++中彻底封堵这些漏洞这就证明这是一个极其艰深甚至可能是目前范式下无解的难题。

吴咏炜:是的抽象是一个大问题会让测试constexpr函数变得很难……我认为模板元编程还要更难。实际上我最近也遇到了这样的问题也是在元编程中。我实际上立即发现了问题因为程序崩掉了但要弄清楚问题到底在哪真的很难因为问题隐藏得很深而且仅在某些特殊场景里才出现。

David Sankel:对他的情况也是一模一样的。

吴咏炜:好的让我们转向下一个关于C++价值主张的问题。如今Rust凭借“内存安全”特性迅速崛起Python在AI时代占据主导也确实吸走了一部分原本依赖C++的用户。但在游戏引擎、系统底层、高性能计算等核心场景C++依旧稳固。在你看来C++最核心的不可替代的优势是什么?为什么这些优势至今仍难被其他语言取代?

David Sankel:“利基市场”是任何人都夺不走的C++核心价值主张在于它允许开发者通过承担“未定义行为”(Undefined Behavior)的风险来换取绝对极致的性能。

让我用一个对比案例来说明:有一段C++代码执行某种整数运算其中可能隐含溢出或除以零的风险。但在编译器的优化下这段代码被极致精简为一条汇编指令:一个移动加一个加法。

“代价是”:如果输入数据错误程序行为完全不可控(未定义)。

“收益是”:如果你能保证数据正确它就是物理上能达到的最快速度。

当开发者试图在Rust中复刻这段代码时困难出现了。Rust的安全机制强制要求检查“除以零”和“整数溢出panic”。为了让Rust代码达到和C++一样的指令级效率开发者不得不使用大量的unsafe块、特殊的编译器提示(Hint)和注解。最终性能确实追平了但代码量膨胀了四倍且可读性大打折扣。

“这正是C++的生存空间所在”——当你愿意接受这种激进的权衡时:

...(内容同上)...

...(内容同上)...

...(内容同上)...
...(内容同上)...
...(内容同上)...