2019年2月24日

[C++] How to Write Reliable Code

這篇只是下面這段演講的整理
How to write more reliable code - Egor Bredikhin - Meeting C++ 2018
投影片

總結來說有以下這幾點
  • Guidelines
  • Unit tests 
  • Code reviews
  • Static analysis
  • Dynamic analysis
  • Mordern C++


Guidelines

其實這點簡單來說就是目前已經有不少文章 / 書在講 coding 時的一些小原則 (像是 effective C++),遵從那些原則就能減少出 bug 的可能性。演講中有列出來的是下面這些
其實有點經驗的人對上面列的東西應該也會略知一二

Unit Tests

這個大概已經說到爛了,其中 TDD (Test-Driven Design) 算是滿常拿出來講的東西,總結一下他的結論的話是這些

優點:

  • TDD allows to find problems early
  • Facilitates changes (regression testing)
  • Encourages the creation of independent components
  • Tests act like a documentation

缺點:

  • You cannot test every execution path
  • Writing good realistic tests is time and effort consuming
  • Some problems cannot be easily tested-Platform differences
  • Code for unit tests is at least as buggy as the code it is testing
另外他也列了一些可以用的工具
  • Google Test
  • Boost.Test
  • CppUnit
  • Catch
  • QTest 
不過 TDD 跟 unit test 是個我到目前都還沒用過的東西 (汗

Code Reviews

這也滿容易理解的,就是讓其他人審視你寫的程式有沒有潛在問題

優點:

  • Complicated errors could be detected (跟缺點第二點相呼應 XD)
  • A better solution could be proposed (畢竟人有經驗)
  • Educates team members (這我是覺得有點硬塞就是 XD)

缺點:

  • High cost (畢竟超花時間)
  • Human reliability (我是覺得這算優點也是缺點就是,呼應優點第一點)

Static Analysis

靜態分析相關的工具其實已經有不少了,簡單來說就是在程式執行前把你的程式碼掃一遍,從中分析有那些問題 (像是型別轉換、沒有 return, dead code, array out of bound 這類),雖然不能保證執行時不會有問題 (比方說 multithread 這種),但是能減少一定的潛在風險 (不過也有可能誤報,或是你是故意的...)。

優點:

  • Covers all program branches
  • Detects misprints, copy-paste errors, and stuff (算是這類方法最適用的問題)
  • Performs control-flow and data-flow analysis
  • Platform independent
  • Some analyzers have a knowledge base

缺點:

  • False positives (他說沒錯不代表真的沒錯 XD)
  • Not so good in detecting memory leaks, parallel errors
這邊有列了一些可用的工具
  • Clang Static Analyzer& Clang Tidy
  • CppCheck
  • Coverity (目前公司在用的就是這套)
  • Klockwork
  • PVS-Studio

Dynamic Analysis

執行時期能分析的問題是甚麼? 當然就是 memory 相關的問題啦,只是通常這種就是在執行階段去監視程式的執行狀況,速度一定會被拉慢好幾倍就是

優點:

  • Detects leaks and memory corruption
  • Detects parallel errors (race conditions, deadlocks and stuff)
  • Detects uninitialized variables
  • Almost no false positives

缺點:

  • Still needs a set of tests to run on
  • Checks only executed paths
  • Sometimes it’s difficult to trace the exact place in code with an error
  • Slow and demanding
可用的工具的話包含
  • Dynamic binary instrumentation
    • Valgrind(Memcheck), Hellgrind (Valgrind 應該滿多人用的? 畢竟是 open source 的 tool)
    • Dr.Memory
    • Intel Inspector
  • Compile-time instrumentation (這東西我最近才知道,還沒試過)
    • Address sanitizer (use after free, use after return, oob, leaks
    • Memory sanitizer (uninitialized memory reads)
    • Thread sanitizer (data race detector)
Sanitizer 目前看起來 clang 都有支援 gcc 沒有 memory sanitizer,不過大多都只有在 Linux 環境下才支援。話雖如此,能用的話最好,畢竟這方法速度大概只會降到 1.5 ~ 2 倍左右,其實算是比較能接受的。

Mordern C++

雖然 C++ 11/14/17 到現在已經在討論 C++20 新增了許多新功能、函式庫...但是也有不少新增的標準是在程式中增加一些 tag 或是改善型別的處理方式讓程式更容易在編譯時期偵測到錯誤,這邊有舉例的是下面這些:
  • enum class (增加 enum 的型別強度)
  • nullptr (明確出這是個 pointer type,而不是想以前用 NULL 這個數值代表)
  • override, final (繼承體系好用)
  • constexpr, static_assert (增加編譯時期的檢查、最佳化)
  • [[no_discard]], [[fallthrough]] (同上,也算是提醒就是)
  • STL containers and algorithm
詳細原因我想就各自針對每項去理解吧,這邊不多談,畢竟已經有很多人/文章討論過了

沒有留言:

張貼留言