標籤:

不只是開源才有問題

昨天看到 @vczh 發文說 libstdc++ 實現上有bug。好漢不提當年勇,當時libstdc++敢把Regex的介面做好、實現放空這檔子事情我們就不提了。

其實何止libstdc++有bug,C++ standard也是一屁股屎擦不幹凈。

我們舉個例子(這裡援引的條款都來自於草案N4567,絕大部分都與C++14相同):

  • Allocator只要求CopyConstructible,沒說必須具有默認構造函數(17.6.3.5)。其實我覺得這個問題當初標委會就糊塗過。一個Stateless的Allocator除了TLS和Global Pool外還有個卵用啊。對於 Stateful Allocator 的話,這個Default Constructor不管雞肋還容易出錯。所以C++17到底搞了個Polymorphic Allocator;

  • Container,比如String(21.4 / 3)。對於Allocator Awareness Container(粗暴的講就是類似於Vector<T, Alloc>這樣的)來說,如果要DefaultConstructible,就需要Allocator是DefaultConstrutible的(23.2.1/16, Table 98);
  • 如果Allocator自己沒有Default Constructor,那麼String的在構造的時候必須要傳遞一個Allocator進去(23.2.1/16, Table 98)。

OK,其實到這裡都沒有問題。至於像什麼

std::vector<std::vector<int, Alloc1>, Alloc2> sh1t;n

中的Alloc1到底是否需要 Default Constructible 這種複雜的問題,我們就不討論了。這種問題自身就相對矛盾,本來就不太好解決。

所以,到這裡都沒問題,說明C++標準委員會的人什麼都懂。

但是這幫子人到寫代碼的時候還是懵逼了。 我們來看basic_string的實現(21.4.6.2):

你不要小看這個「Effects」,實際上很多庫真的就是原模原樣這麼實現的 —— 這樣也才是個符合標準的實現。但是這個實現有什麼問題呢,對於Stateful的Allocator,比如Polymorphic Allocator(C++ 17),basic_string(first, last); 和 append 的 this 可能壓根用的就不是同一個內存分配器。

如果basic_string的allocator不支持default constructor(這並沒有什麼問題),那麼basic_string(first, last) 就會導致編譯錯誤。我特么不過用了一個allocator,你好意思讓我assign都assign不成嗎?

一個符合標準也更加合理的實現是:

append(basic_string(first, last, get_allocator()); // Effects.n

嗯,這個問題兩個月前我report過了,在我report的時候這還不算一個known issue我猜C++17這個問題會被修正的,這也算是我為標準做了一點微小的工作。

所以啊,Naive的並不只是開源。做C++的人,沒有不Naive的,雖然他們一點都不Simple。

————————————————————

這個問題其實我15年前學C++的時候就暈菜過。

但是現在我才發現,這並不是我垃圾。在坐的各位,包括我,在面對現實世界各種Divergency的問題的時候,都是垃圾。

只不過C++標委會的人比我屌的地方在於,他們會八仙過海翻著花樣的垃圾,比如glvalue的問題(GCC 7開始支持)。這個問題年輕的、比我牛逼10倍的C++大牛 @劉雨培 聚聚在文章中提到過:C++ 17 最大的改變——Guaranteed copy elision ,我就不細說了。

————————————————————

螳螂婊蟬,黃雀操後 ,CppTemplateTutorial群 裡面已經開始有人婊我了。


推薦閱讀:

為什麼越深入的學習法律,越覺得法律的漏洞越多?
WIN10將文件或文件夾固定到快速訪問,提示參數錯誤,怎麼解決?
如何看待能自動修復bug的CodePhage?
iPhone越獄黑客:天才往左,成功往右
malloc時出錯。提示 0xC0000374: 堆已損壞 (參數: 0x778CD8D0)什麼原因?

TAG:C标准 | Bug |