微軟官宣:GSL 3.0.0發佈

GSL 3.0.0 正式發佈

我們高興地宣佈:C++ Core Guidelines Support Library (GSL)的微軟實現3.0.0版本已經正式可用。gsl::span的微軟實現在C++ 20 的span標準化進程中扮演著一個非常關鍵的角色。但是,標準中並沒有包含用於內存邊界安全的運行時檢查。在微軟的自身產品中,gsl::span所提供的內存邊界安全特性成功地避開了一些安全問題。這次的發佈版本在繼續維護內存邊界安全的同時,還對我們的實現進行了現代化升級,從而和C++ 20 span保持一致。

有哪些更新

> 新的gsl::span和gsl::span_iterator實現,保持與C++ 20標準的一致性。

> 對Contract Violation行為的更改。

> 添加CMake支持。

> gsl::multi_span和gsl::strided_span被標記為廢棄。

在什麼情況下我應該使用gsl::span,而不是std::span?

默認情況下,如果你已經啟用了C++ 20模式並且不需要內存邊界運行時檢查,則可以使用VS2019 v16.6(在v16.7中,有一些額外的接口變更)自帶的std::span。如果你需要支持C++ 20以下的版本(gsl::span支持C++ 14及以上)或者需要內存邊界運行時檢查(所有執行在gsl::span上的操作和它的迭代器都會有顯式的邊界安全檢查)。

gsl::span

隨著對span的標準化即將完成,我們決定是時候將我們的實現保持和標準設計一致了。在新的實現中提供了全功能的邊界檢查,確保了當底層數據有效時的邊界安全。

主要的修改要點

gsl::span被重新實現主要是為了和標準的std::span保持一致。最大的變化是span的大小現在被定義為了無符號整數類型。之前我們使用的是std::ptrdiff_t這個類型,在新的實現中,我們改用了std::size_t來表示。另外對於它的擴展來說,dynamic_extent現在被定義為static_cast(-1),而不是之前的-1。

> span::size_type取代了原有的span::index_type。

> 添加了CTAD(Class Template Argument Deduction)支持。

接口一致性

在接口層面,還有如下的一些改動來保持gsl::span和std::span的一致性。

移除的函數

> span::operator()

> span::at

> span::cbegin

> span::cend

> span::crbegin

> span::crend

新增的函數

> span::front

> span::back

重命名的函數

span::as_writeable_bytes被重新命名為span::as_writable_bytes

gsl::span_iterator的修改要點

在我們對span_iterator的新版實現中,我們徹底地重寫了全部的代碼,使之看起來更加像一個範圍(range-like)。在之前的實現中,我們使用了一個span的指針和一個偏移,而在新版本中,我們使用了三個指針,它們分別是:begin, end和current。

新版實現的好處

新版實現自身可以執行所有的邊界檢查,而不是調用span。通過依賴指向底層數據的指針,而不是指向span的指針,新版的span_iterator可以擁有比底層span更長的生命週期。

新的頭文件

有些用戶可能會需要依賴舊版本的span實現,但是這些舊版實現在span的標準版實現中已經被移除了,為了支持這些用戶,我們創建了新的頭文件。

從中被刪除的並加入到中的元素

> span comparison operators

> gsl::make_span

> span specialization of gsl::at

> gsl::begin

> gsl::rbegin

> gsl::crbegin

> gsl::end

> gsl::rend

> gsl::crend

契約違規

契約違規不再是可配置的。如果發生了違規,都會導致程序終止運行,而不是像之前那樣可以通過提供編譯器開關來拋出異常或者忽略違規。不過,這可能在將來的實現中發生改變。需要注意的是,移除拋出異常這種行為可能會要求我們將現有的測試套件從Catch2遷移到Google Test,因為Google Test可以在測試契約違規用例時更加容易的支持失效測試(Death Tests)。

CMake的改進

新版實現中現已支持find_package。一旦新版本完成安裝,則可以使用find_package(Microsoft.GSL CONFIG)輕鬆找到GSL庫。

關於multi_span和strided_span的廢棄聲明

為了將GSL的微軟實現和C++ 核心規範(Core Guidelines)更好地保持一致,我們決定將gsl::multi_span和gsl::strided_span的實現聲明為廢棄。雖然現在我們還是會提供這些頭文件,但是它們將不會再進行開發和維護,除非C++核心規範需要它們。

實現變更可能導致的編譯失敗及修復措施

變更:在gsl::span中,原來帶符號的std::ptrdiff_t類型修改成無符號的std::size_t可能會導致帶符號/無符號的不一致。修復措施:使用static_cast或者gsl::narrow_cast來解決這個不一致問題。

變更:gsl::multi_span和gsl::strided_span被聲明為廢棄。修復措施:以常量引用的方式傳遞多維數組,而不是使用gsl::multi_span。

變更:使用到了moved span幫助函數的代碼可能會產生編譯錯誤。例如span比較操作符,gsl::make_span等。修復措施:當你使用到這些函數的時候,請包含,而不是。

變更:對契約違規拋出異常已經不再支持。修復措施:當應用程序終止運行之前,請使用一個終止處理例程來記錄相關的診斷信息。對拋出異常這一行為的依賴將不再被確保是安全的。

總結

內存越界的確是一個很容易被忽略且難以診斷的問題,如果善用GSL,應該會顯著的減少此類編碼錯誤,進而提升產品健壯性。


微軟官宣:GSL 3.0.0發佈


分享到:


相關文章: