如何对待 Azure CTO 呼吁遏制使用 C/C++,并用 Rust 作为替代语言?
如何对待 Azure CTO 呼吁遏制使用 C/C++,并用 Rust 作为替代语言? 现在的问题是,Rust要取代C++项目,但偏偏它对手真的不是C++。这两个真的不矛盾。对于C++来说,缺失的官方性质的包管理,ABI标准等等,对于业务逻辑很致命,但对写高性能的组件以及底层库的用户来说无所谓,现在有xmake这种高效率的,保姆级的,还兼容cmake的构建,配置,包管理工具,配合LSP开发效率极高,反观Rust在这一点上也是殊途同归,该unsafe手动操作内存的也一个不能少,那么既然都殊途同归了,连库之间互相引用都做到了,这都算亲兄弟了,还代替个卵。。而那些本来要被换掉的古老的C++编写的业务逻辑,或者刚立项,还未立项的项目,可能在未来本会选择Java, Go, C#等语言,但因为有了Rust从而多了个选择。那么作为Rust的有好感(相对那些语言)的路人,我对其能否代替这些语言有些担忧。因为以前在C++和高级语言们之间选择时有相当多理由不选择C++,不安全,没反射,以及上面提到的包管理ABI等等,所以这种选择根本不成立,就算没有Rust,C++都得挤到角落,但当现在Rust有机会解决这些问题的时候,这种选择就又浮了上来。那么,团队管理者是否会认为语言的复杂与性能的优势成比例从而优先选择Rust?在选择后能否让那些基础不牢固的开发者接受并学习这些在我们看来习以为常的内存管理知识?以及更长远的问题,Rust若能普及,能否倒逼从业人员完成技术上的达尔文式的进化?对此我本人既期盼,又担忧道阻且长。 我先交代背景:我是Rust铁粉,6年全职Rust,用Rust创了业,招了人,带了新手,也折腾过开源项目。
C++只有大概两年全职的经验,离精通差了十万八千里,但是因为我当年是做逆向然后开发工具的,为了少写汇编整了很多的C++奇技淫巧加上日常无符号调试,所以应该不需要给我普及C++用法和内存安全是什么。
首先,我发现有些人吹Rust根本就不是Rust的用户。排除掉新手不知道自己在说什么,其他的一些煽风点火的你去看看他的资料就会发现根本就是利益相关。他们并不用Rust来做项目,对他们来说,Rust的最大价值是求赞,卖课而已。往往每次一出现有推荐Rust的声音,他们最爱用春秋笔法改写了搬运,贩卖一下除了Rust其他语言都要完蛋的焦虑,这样你才能点赞,买课。注意,我不否认这些“传教士“对于普及Rust起到的积极作用,只是当你要讨论工程问题时,他们并不是很好的对象。
我认为Rust和C++是对立的是一个极大的误解。事实上,在Rust的项目里使用C/C++代码是一个非常常见的需求。Rust的build script调用C/C++工具链来使用C/C++的库非常常见。如果作为一个Rust程序员你从来没有这样做过,那么多半是别人的build script写得好,你没发现而已。而且很多时候并不止是简单的调用binding,而是在Rust的项目里写C++,或在C++的项目里引用Rust的库。(看看cc, cxx这两个crate是干嘛的)
我举两个我项目中遇到的实际例子:
[*]某项目包含一个传统的Web项目前端和后端(C#/React)加Unreal做的渲染器,要求Unreal可以和前后端实时的交互。所以我设计了一个Rust的服务用来和Web的前后端交互加上控制Unreal。这个服务用C++能不能,显然可以。你当然可以利用Unreal已经提供的class,加上从C++生态里面找到你需要的库,然后链接进来。但是当你用过Rust来解决这个问题,你绝对不会再想去用C++。你会惊讶的发现,用Rust实现这个需求,无论从开发速度,代码可读性,可维护性上都比C++好一大截:Rust的HTTP库的易用性已经和前端差不多的时候,Unreal的FHttpModule还在用callback形式的API;和serde比,Unreal的serialization像是个玩具;和cargo直接添加依赖相比,搞明白C++依赖的构建和配置纯属浪费生命。
[*]还是这个项目,需要写一个动态生成Geometry的算法,最后一步需要三角形化,Rust没有能用的相关的库,C++有好几个。直接用cxx,包装一下库的调用,Rust的struct直接生成了可供C++调用的header,C++的函数直接生成了Rust的FFI代码,直接用,没有惊喜。如果cxx再完善一些,我觉得以后C/C++这种写法可以改一下,改成C/C++/Rust。
Rust在部分场景下确实可以替代C++。例如网络相关的程序,最近
How we built Pingora, the proxy that connects Cloudflare to the Internet
除了道听途说的新闻,我个人也有实际的项目作为证据:
我利用业余时间,一个人用Rust重写了魔兽争霸3的服务器系统。功能远远超过暴雪的原版,并且在架构上支持低成本的全球部署,现在已经稳定可靠的运行了300万场以上的游戏。我承认这依然是个业余项目,但这已经可以证明Rust的异步网络编程生态已经足够成熟可以支持这样的需求。
Rust在快速的进步中,所以如果你没有在使用Rust,你对Rust的了解很有可能已经过时了。随便列一点我想得到的:
[*]proc macro进入stable,解锁了很多元编程的用法
[*]async rust从无到有,futures从0.1的勉强能用,到0.2的试错,到0.3终于稳定
[*]rust-analyzer从大项目基本没法用,到现在稳定。
[*]const generic, GAT取得了很大进展,MVP已经或者即将进入stable。
[*]生态:hyper(http)从能用,但是性能堪忧,到可以参加性能刷榜;tokio从满地bug,API奇葩,到现在1.0能提供你需要的异步网络编程的一切;国人开发的async-graphql,可以说是所有语言的GraphQL服务器端实现的佼佼者。。。
C++有C++98,也有C++23。Rust也一样。BS老爷子说Rust是“new and shiny things“说了好多年了,不知道他有没有了解过这几年来Rust社区的努力带来的进步?
我觉得Azure CTO的说法应该加上一些前提。他说的是“当你要新开一个项目,并且新开的这个项目必须使用非GC的语言时”。我认为还应该加上
[*]你的项目不依赖于某个特定C++框架
[*]你的团队已经熟悉了Rust
[*]你确定Rust生态系统能满足你的绝大多数要求,或者你善于造轮子
[*]不过,以上三条如果你还需要别人提醒的话这里建议您不要开新项目
Stroustrup说。。。
"We can now achieve guaranteed perfect type and memory safety in ISO C++. That is, every object is used according to the type it was defined with. That implies that we eliminate uses of dangling pointers, catch range errors, and eliminate data races. Note that every 'safe' language, including Rust, has loopholes allowing unsafe code."他的意思是说,ISO C++是完美的类型和内存安全的,所以不安全的C++程序都是因为历史原因或者写的太烂的原因吗?
等等,C++的是内存安全的? 我不匿名,我对rust没啥意见,用过一段时间但感觉并不成熟持观望态度,但我非常讨厌rust这种语言的饭圈气息,甚至听到rust我就很反感。
人家好歹做二进制安全的,做那个行业扎那个坑发这种言论你能理解为什么别人会这么说。
问题是现在碰到一大群一群代码都没写过几行,cve给他看都看不懂,什么是uaf什么是double free都不清楚,给他exploit都不会用,用c写个链表都写不利索的,也整天那边memory safe
不是,你把你全部代码扒出来,你碰到过几个memory safe问题啊,你是上手了几个亿的项目啊?还是用户百万就因为这个问题没能走上人生巅峰啊?结下了那么多深仇大恨?业务逻辑一塌糊涂,数据结构一问三不知,paper连abstract都啃不下去,写过的代码还没别人的零头多,代码写个两三年毛都没长齐呢,也整天那边建议指导别人用rust。
梁静茹给你的自信吗?
啊? 他们恨不得把所有人忽悠来用Rust重写,当其他人还在熟悉Rust的语法规则时,他们已经又用C/C++完成了一个项目了(手动狗头)
Mark Russinovich是Azure的CTO,微软的CTO是Kevin Scott。
针对 Mark Russinovich 的言论,The Register 采访了 C++ 之父 Bjarne Stroustrup;Stroustrup 则为 C++ 进行了辩护:https://www.theregister.com/2022/09/20/rust_microsoft_c/
“人们 -- 尤其是一些高管 -- 总是会迷恋那些承诺会使他们的生活更轻松的新事物,这是很正常的。而且,支持新事物远比解决旧的和众所周知的工具的已知问题更令人兴奋。不幸的是,新的语言通常需要多年的时间和重大的努力,才能在其广泛的应用领域中与成熟的语言相媲美。发烧友们很少看到这一点,他们的评论往往是相当片面的”。
Stroustrup 表示,考虑到安全性的重要程度,多年来他一直在致力于提高 C++ 的安全性;从而现在在 ISO C++ 中实现了可靠的完美类型和内存安全。也就是说,每个对象都根据它定义的类型来使用;这意味着消除了 dangling pointers 的使用、捕获范围错误并消除了数据争用。
他还强调称,包括 Rust 在内的每一种 “安全” 语言都存在着允许不安全代码的漏洞。
页:
[1]