我思考這個問題的原由是 Codeoforces Avito Challenges 2018 的 E 題,我想到了正解,但寫得太慢,最後一刻才提交。有個地方寫錯,結果是 Runtime error on pretest 13。
那個錯誤是個數組越界。代碼片斷以下:html
#define rng(i, a, b) for(int i = (a); i < (b); ++i) vv<pii> fact(2e5+5); // 計算 fact vv<bool> dp(m, vb(ma)); // m 和 ma 是正整數 vv<int> pre(m, vi(ma)); rng (i, 0, SZ(fact[a[0]])) { dp[0][i] = true; } rng(i, 0, m) { // 錯誤出在這裏 auto &cur = fact[a[i]]; auto &nxt = fact[a[i + 1]]; rng(j, 0, SZ(fact[a[i]])) { if(dp[i][j]) { int t = cur[j].second; for (int k = 0; k < SZ(nxt); k++) { if(t < nxt[k].first) { dp[i+1][k] = true; pre[i+1][k] = j; } } } } }
那個 for 循環本應是 rng(i, 0, m-1)
。個人寫法經過了三個樣例,交上去在 pretest 13 RE 了。倉促改了另一個地方又交上去結果在 pretest 2 就 RE 了。數組越界這個問題何時會觸發 RE 是不肯定的。數組
賽後我想起曾經看到過 std::vector
會自動檢查數組越界,但是我在 CLion 中編譯運行上面的代碼爲什麼運行時沒提示數組越界呢,何況 CLion 的 Run/Debug Configurations 還顯示處於 Debug 模式。ui
圖-1this
圖中紅線框出的那裏,左邊的 algo 是當前選擇的 target 的名字,target 是在 CMakeLists.txt
中定義的。紅框圈起來的東西,官方名稱 是 run/debug configuration selector。命令行
圖-2debug
因而我搜了一下怎樣開啓數組越界檢查。在 StackOverflow 上找到一個答案。辦法就是編譯時加上選項 _GLIBCXX_DEBUG
其實這是個宏定義,沒必要做爲 g++
的命令行選項, 在代碼里加上 #define _GLIBCXX_DEBUG
也能夠,和其餘宏定義沒區別,只不過會被編譯器識別,並對編譯器產生影響。3d
我加了這個宏定義再編譯運行原來的代碼,果真就報錯了。不過並無指明錯誤是由哪一行代碼引發的,對於 debug 幫助不大,這個問題請移步這裏。不過雖然未能指出是那一行代碼出的錯,可是指出了是訪問 3 這個位置越界了,那麼就說明對應的 vector 的 size 應該是 3,這個信息對於這道題目的 debug 仍然頗有幫助,據此能夠知道這個 3 是 m 的值。調試
圖-3code
個人疑問是 CLion 的 Build/Debug Configurations 框裏的那個 Debug 究竟是什麼含義(What does it imply?)先看看這個 Debug 到底是什麼含義。orm
首先要介紹 CLion 中的一個重要概念 Run/Debug Configrations。
To run or debug your code in CLion, you can use numerous run/debug configurations. Each run/debug configuration represents a named set of run/debug startup properties. When you perform run, debug, or test operations with CLion, you always start a process based on one of the existing configurations using its parameters.
CLion comes with a number of run/debug configuration types for the various running, debugging and testing issues. You can create your own run/debug configurations of specific types.
關於 Run/Debug Configurations 的更多細節,見 Create and Edit Configurations。
其實 圖-1 紅框裏的那個 Debug 是當前所選擇的 configuration 所採用的 CMake profile 的名字。能夠在下圖中的加號(+)上面看到 「profiles」 字樣。
圖-4
上圖是 CMake settings dialog。
固然這個 name 是能夠改的,好比改爲 debug,那麼第一幅圖紅框裏也會相應地由 Debug 變成 debug。
如今咱們收集到的信息有
如今咱們要問:當 build type 爲 Debug 時,是否會把相似於 _GLIBCXX_DEBUG
這樣的選項傳遞給編譯器呢?
答案是不會。
咱們能夠從 CLion 文檔中關於 build type 的頁面上示例代碼中推測出來
圖-5
關於 圖-4 中的 build option -j 6
,CLion 文檔是這樣解釋的:
Build options In this text field, specify the options to be passed to the build tool used by CMake.
Find more information about the available build options in the CMake documentation.If nothing is specified, the default settings are used. Note, that default settings depend on the selected environment. For example, if
make
generator is selected, the default value is-j <number_of_cpu>
, while for Microsoft Visual C++ the field is empty.
我採用的 toolchain 是 MinGW,所用的 generator 天然是 make
,另外個人 laptop 的 CPU 是 Intel Core i7-8750H,# of Cores = 6,所以默認的 build option 是 -j 6
。
在 CMake 文檔裏關於 CMAKE_BUILD_TYPE
這個 variable 的說明頁面,我找到線索
... For example, in a build tree configured to build type
Debug
, CMake will see to havingCMAKE_C_FLAGS_DEBUG
settings get added to theCMAKE_C_FLAGS
settings.
我猜當 build type 是 Debug
時 CMake 只是把 -g
之類的調試選項傳給編譯器了。
Run/Debug Configurations 是控制可執行文件生成之後的執行與調試的,而 Build Configurations 是控制從源代碼生成可執行文件的過程的。我應該去修改 Build Configrations 也就是 CMake profile,好比能夠把 -D_GLIBCXX_DEBUG
添加到 Build option。在代碼中加上 #define _GLIBCXX_DEBUG
也是可行的。