最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網 會員登陸 & 注冊

一個 C 系程序員的 Rust 初體驗

2022-05-07 18:25 作者:Databend  | 我要投稿

引言:在工作里使用 Rust 已經有兩個多月的時間了,談談我做為一名多年的 C 系(C、C++)程序員,對 Rust 的初體驗。

一個 C 系程序員的 Rust 初體驗

最近由于工作的原因,使用上了 Rust 語言,在此之前我有多年的 C、C++ 編碼經驗(以下將C、C++ 簡稱 C 系語言)。

使用 C 系語言編碼時,最經常面對的問題就是內存問題,諸如:

  • 野指針(Wild Pointe):使用了不可知的指針變量,如已經被釋放、未初始化、隨機,等等。

  • 內存地址由于訪問越界等原因被覆蓋(overflow),這不但是可能出錯的問題,還有可能成為程序的內存漏洞被利用。

  • 內存分配后未回收。

連 Chrome 的報告都指出,Chrome 中大約 70% 的安全漏洞都是內存問題。見:Memory safety[1]。

C 系語言發(fā)展到今天,已經有不少可以用于內存問題檢測的利器了,其中最好用的莫過于 AddressSanitizer[2],它的原理是在編譯時給程序加上一些信息,一旦發(fā)生內存越界訪問、野指針等錯誤都會自動檢測出來。

但是即便有這些工具,內存問題也不好解決,其核心的原因在于:這些問題絕大部分都是運行時(Runtime)問題,即要在程序跑到特定場景的時候才會暴露出來,諸如上面提到的 AddressSanitizer 就是這樣。

都知道解決問題的第一步是能復現(xiàn)問題,而如果一個問題是運行時問題,這就意味著:復現(xiàn)問題可能會是一件很麻煩的事情,有時候還可能到生產環(huán)境去復現(xiàn)。

以我之前經歷的一個 Bug 來看這類工作的復雜度,見?線上存儲服務崩潰問題分析記錄 - codedump 的網絡日志[3],這是一個很典型的發(fā)生在生產環(huán)境上由于內存錯誤導致的崩潰問題:

  • 不好復現(xiàn),因為跟特定的請求相關,還跟線程的調度有關;

  • 本質是由于使用了被釋放的內存導致的錯誤。

這個線上問題,記得當時花了一周時間來復現(xiàn)問題解決。

換言之,如果一個問題要等到運行時才能發(fā)現(xiàn),那么可以預見的是:一旦出現(xiàn)問題,要復現(xiàn)問題可能要花費大量的精力,以及需要很多經驗才行。如果一個問題還是在特定場景,或者用戶現(xiàn)場才出現(xiàn)的,那就更麻煩了,C 系程序員以往一般都是這樣來保存“現(xiàn)場”:

  • 出現(xiàn)崩潰的時候保存 core 文件來查看調用堆棧、變量等信息。

  • 發(fā)明了各種復制流量重放的工具,比如 tcpcopy[4]?等。

總而言之,運行時問題一旦出現(xiàn)是很麻煩的,而解決這類問題的時間是難以預期的。

Rust 給這類內存問題的解決提供了另一個解決思路:

  • 一個內存地址同時只能被一個變量使用。

  • 不能使用未初始化的變量。

  • ...

簡而言之,凡是可能出現(xiàn)內存錯誤的地方,都在語言的語法層面給予禁止,換來的就是更多的編譯時間,因為要做這么多檢查嘛,而需要更多的編譯時間反過來就需要更好的硬件。我想這也是 Rust 到了最近幾年才開始慢慢流行開來的原因之一,畢竟即便是現(xiàn)在,一些大型的 Rust 項目普通的機器編譯起來也還是很耗時。

“編譯時間(compile time)”是一個可以預期的固定時間,能通過增加硬件性能(比如買更好的機器來寫 Rust)來解決;而“運行時問題”一旦出現(xiàn),查找起來的時間、精力、場景(比如出現(xiàn)在用戶現(xiàn)場、幾百萬次才能重現(xiàn)一次等)不確定性可就很高了。

兩者權衡,我選擇解決“編譯時間”問題。而且,在我意識到有這樣的工具能夠在編譯期解決大部分內存問題時,反過來再看使用 C 系語言的項目,幾乎可以預期的是:只要代碼和復雜度上了一定規(guī)模,那么這類項目都要花上相當的一段時間才能穩(wěn)定下來。原因在于:類似內存問題這樣的運行時問題,是需要場景去積累,才能暴露出來的,而場景的積累,就需要很多的小白鼠和運行時間了。

總結一下我的觀點:

  • C 系語言最多的問題就是各類內存問題,而這些問題大多是運行時問題。即便現(xiàn)在已經有了各種工具,解決其運行時問題也很困難。

  • Rust 解決這類問題的思路,是在語法層面禁止一切可能出現(xiàn)內存問題的操作,換來的代價就是更多的編譯時間。

  • 解決可預期的“編譯時間”和難預期的“運行時問題”,我選擇前者。

番外篇

rr

rr: lightweight recording&deterministic debugging[5]?也是出自 Mozilla 的另一款調試 C 系程序的利器,rr 是 Record and Replay 的簡稱,目的還是為了解決各種運行時問題,由于運行時問題中存在著各種不確定的因素,包括:

  • 變量值。

  • 進程、線程環(huán)境,比如不同的線程調度順序可能導致了不同的結果。

  • 輸入不同的數據,能得到不同的結果。

于是,rr 要解決的核心問題,就是讓一個程序在運行時有一個固定的環(huán)境,它可以抓取程序運行的環(huán)境保存下來。這樣在出現(xiàn)問題之后,就能使用它可以記錄下來程序運行時的環(huán)境,不停的重放來調試解決問題。

但是,即便是這樣,rr 可能更適合于明確知道問題的情況下去抓取環(huán)境,不可能在線上直接打開這個工具。所以又回到前面的結論了:調試運行時問題可能面對的困難,包括場景、時間、用戶現(xiàn)場等等不確定因素。

rr 和 Rust 一樣,都出自 Mozilla,我想不是偶然的。Mozilla 和 chrome 等一樣,都是使用 C++ 編碼的超大型項目,而這里一定遇到了各種運行時問題,不止于內存問題,所以才要使用各種工具來輔助解決這類問題。

吃上硬件升級的紅利了嗎?

前面提到過,Rust 目前較大的問題是編譯時間過長,這可能是導致它最近幾年才開始逐漸流行開來的原因。其實反過來說,在硬件升級之后,應該能盡量利用上硬件,在編譯期盡量多檢查出錯誤來,減少運行時發(fā)現(xiàn)問題的數量。這樣,才能吃上硬件升級的紅利,利用硬件來減少自己的犯錯。

一方面硬件升級給了編程語言能施展更大、更快的的“舞臺”,隨著舞臺的更新,就會有更新、更好的工具出現(xiàn);另一方面做為從業(yè)者,也應該與時俱進,多學習跟進這些工具的演進。

我看到有一些人,強調自己多早就已經用 C 語言寫代碼了,但是查內存問題還在用慢的不行的 Valgrind,沒聽過更不知道怎么用 Address Sanitizer。想說如果技能點都已經不更新了,強調多早學的有什么意義?好比 1950 年就會打算盤,有意義嗎?強調多早就用 C 語言類似的言論,在我看來就是“倚老賣老”,但是技術日新月異的領域,賣老的意義不大。

《Rust for Rustaceans》

推薦 Rust for Rustaceans[6]?作者 Jon Gjengset 的油管頻道:https://www.youtube.com/c/JonGjengset/playlists

有很多很有深度的 Rust 分享,比如:

  • Implementing TCP in Rust (part 1) - YouTube[7]

  • Porting Java's ConcurrentHashMap to Rust (part 1) - YouTube[8]

參考資料

[1]Memory safety:?https://www.chromium.org/Home/chromium-security/memory-safety/

[2]AddressSanitizer:?https://en.wikipedia.org/wiki/AddressSanitizer

[3]線上存儲服務崩潰問題分析記錄 - codedump的網絡日志:?https://www.codedump.info/post/20190413-problem-fix/

[4]tcpcopy:?https://github.com/session-replay-tools/tcpcopy

[5]rr: lightweight recording & deterministic debugging:?https://rr-project.org/

[6]Rust for Rustaceans:?https://rust-for-rustaceans.com/

[7]Implementing TCP in Rust (part 1) - YouTube:?https://www.youtube.com/watch?v=bzja9fQWzdA&list=PLqbS7AVVErFivDY3iKAQk3\_VAm8SXwt1X

[8]Porting Java's ConcurrentHashMap to Rust (part 1) - YouTube:?https://www.youtube.com/watch?v=yQFWmGaFBjk&list=PLqbS7AVVErFj824-6QgnK\_Za1187rNfnl

關于我們

Databend 是一款開源、彈性、低成本,基于對象存儲也可以做實時分析的新式數倉。期待您的關注,一起探索云原生數倉解決方案,打造新一代開源 Data Cloud。

  • Databend 文檔:https://databend.rs/

  • twitter:https://twitter.com/Datafuse\_Labs

  • Slack:https://datafusecloud.slack.com/

  • Wechat:Databend

  • GitHub :https://github.com/datafuselabs/databend

文章首發(fā)于公眾號:Databend


一個 C 系程序員的 Rust 初體驗的評論 (共 條)

分享到微博請遵守國家法律
岐山县| 东乌珠穆沁旗| 平凉市| 曲周县| 庆云县| 延安市| 安图县| 武冈市| 屏边| 乳源| 黔西| 汾西县| 金门县| 东平县| 衡南县| 陇南市| 同德县| 合水县| 疏附县| 阿拉尔市| 景宁| 马关县| 那坡县| 柳州市| 新乡市| 同德县| 尼勒克县| 永寿县| 桂阳县| 即墨市| 扶余县| 黄大仙区| 昂仁县| 修武县| 新巴尔虎左旗| 秦皇岛市| 苗栗县| 沅陵县| 伊春市| 瑞丽市| 漳浦县|