macのVSCodeでc++をデバッグする (AtCoderの解答をデバッグする事例つき)

AtCoderでブラウザ上で書いたコードが通らず、macのVSCodeでデバッグしようとして苦戦したログです。

私は普段はWindowsのVisualStudioを使っていますが、macのVSCodeでAtCoderやってみようと色気付いた素人です。
至らないところがありましたら、アドバイスお願いします<(_ _)>

## 事例：AtCoderの問題が解けない

[AtCoder に登録したら次にやること ～ これだけ解けば十分闘える！過去問精選 10 問 ～](https://qiita.com/drken/items/fd4e5e3630d0f5859067)

この素晴らしい導入記事に祝福され、一つずつ問題を解いていました。
この時点ではAtCoderの提出ページに直接コードを書いています。

途中までは良かったのですが、[AGC012A](https://atcoder.jp/contests/agc012/tasks/agc012_a)で詰まってしまいました。
以下提出コードです。

```c++
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;

int main(){
  int N;
  cin >> N;
  vector<int> vec(N);
  for(auto& v : vec){
    cin >> v;
  }
  sort(vec.begin(), vec.end(), greater<int>());

  int ans = 0;
  int count = N;
  bool second = false;
  for(auto& v : vec){
    if(second == false){
      second = true;
    }
    else{
      ans += v;
      second = false;
      --count;
      if(count == 0){
        break;
      }
    }
  }
  cout << ans << endl;
}
```

<img width="1111" alt="スクリーンショット 2019-08-14 7.44.12.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/73825/62a3ff61-f6b7-6398-2d94-280d50e420a8.png">

目視確認してもどうにもわからないので、デバッグしたいと思います。
VSCodeでc++のデバッグができそうなのでやってみました。

## 前提：VSCodeの公式ドキュメントを参考にする

下記ページで@OcoToOoさんがおっしゃっているように、ネットの記事に書いてある挙動と、私の環境での挙動が違うことが多くて混乱しました。

> アップデートが頻繁に行われ、記載した情報がすぐに古くなってしまい役立たなくなる可能性があるので、現時点では英語しかないみたいですが、公式ドキュメントを参照することを強くお勧めします。
[Visual Studio Code での C++ の初期設定 (Windows x gcc(MinGW) 編)](https://qiita.com/OcoToOo/items/f1d0a125327f5659ad52)

ということで、以降は2019年8月16日現在の公式ドキュメントの内容に従って設定していきます。
うまくいかない場合は、公式ドキュメントを参照することを強くお勧めします。

公式ドキュメント
[Get Started with C++ and Clang/LLVM in Visual Studio Code on macOS](https://code.visualstudio.com/docs/cpp/config-clang-mac)

## VSCodeのインストール

VSCodeのインストールは下記ページが参考になりました。
日本語化もしておきます。
[MacにVSCode (Visual Studio Code)をインストールする方法 | カレリエ](https://www.karelie.net/install-vscode-mac/)

## 拡張機能"C/C++"のインストール

拡張機能"C/C++"をインストールします。
[C/C++ - Visual Studio Marketplace](https://marketplace.visualstudio.com/items?itemName=ms-vscode.cpptools)

VSCode上で"shift+command+x"で拡張機能を開いて"C/C++"を検索してインストールでもOKです。

## ターミナルからVSCodeを開く

VSCodeのコマンドを環境変数に追加します。
"shift+command+p"を押してコマンドパレットを開き、"shell"を入力します。
出てきた"Shell Command: Install 'code' command in PATH"を選択します。
これでターミナルから、現在のディレクトリをワークスペースとしてVSCodeを開けます。

<img width="430" alt="スクリーンショット 2019-08-17 22.09.01.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/73825/1da64922-c52e-c41d-9be9-942377323eae.png">

公式ドキュメントに従って、"project"ディレクトリのサブディレクトリ"helloworld"をターミナルからワークスペースとして開いてみます。
いったんVSCodeを閉じ、ターミナルで以下のコマンドを入力します。

> ```bash
mkdir projects
cd projects
mkdir helloworld
cd helloworld
code .
```
[Start VS Code in a folder](https://code.visualstudio.com/docs/cpp/config-clang-mac#_start-vs-code-in-a-folder)

すると、以下のように"helloworld"ディレクトリをワークスペースとして開いた状態でVSCodeが起動します。

<img width="463" alt="スクリーンショット 2019-08-16 23.32.44.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/73825/7751e608-4cee-6c7a-b7ea-ef29874bede9.png">

## c_cpp_properties.jsonを設定する

VSCodeでのデバッグ実行に必要なファイルが３つあります。

|ファイル|説明|
|---|---|
|c_cpp_properties.json|コンパイラパスとインテリセンスの設定|
|tasks.json|ビルドの設定|
|launch.json|デバッガの設定|

まずは"c_cpp_properties.json"を作成します。
"shift+command+p"を押してコマンドパレットを開き、"c/c++: edit"を入力します。
出てきた"C/C++: Edit Configrations (UI)"を選択します。

<img width="234" alt="スクリーンショット 2019-08-16 23.35.49.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/73825/ff9577ef-6943-1a84-b1e5-9e4772544633.png">

すると"C/C++ Configuration"ページが開きます。

<img width="684" alt="スクリーンショット 2019-08-16 23.39.23.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/73825/e57699ad-ca02-a621-6caf-e38aba957ba0.png">

特に変更しなくても動いたので、そのまま閉じてもOKですが、AtCoderをやる場合は現状ではC++14なので、"C++ standard"を"C++14"に変更しておきます。

<img width="459" alt="スクリーンショット 2019-08-16 23.45.19.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/73825/e35c6d70-e23f-fe00-4294-02a9d0eff170.png">

これで".vscode"ディレクトリに"c_cpp_properties.json"が作られました。

<img width="700" alt="スクリーンショット 2019-08-16 23.54.58.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/73825/3e683baa-06ac-e0d5-92b2-ef2f55478959.png">

```json:c_cpp_properties.json
{
    "configurations": [
        {
            "name": "Mac",
            "includePath": [
                "${workspaceFolder}/**"
            ],
            "defines": [],
            "macFrameworkPath": [
                "/System/Library/Frameworks",
                "/Library/Frameworks"
            ],
            "compilerPath": "/usr/bin/clang",
            "cStandard": "c11",
            "cppStandard": "c++14",
            "intelliSenseMode": "clang-x64"
        }
    ],
    "version": 4
}
```

## tasks.jsonを設定する

次にビルドタスクとなる"tasks.json"を作成します。
"shift+command+p"を押してコマンドパレットを開き、"task"を入力します。
出てきた"Tasks: Configure Default Build Task"を選択します。
(公式ドキュメントでは"Tasks: Add a default build task"を選べとあるが、そんなもんない)

<img width="277" alt="スクリーンショット 2019-08-17 0.12.42.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/73825/64714b20-2233-ca5e-f486-341de6dd62e1.png">

"テンプレートからtasks.jsonを生成"を選択。

<img width="236" alt="スクリーンショット 2019-08-17 0.18.39.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/73825/883ba044-fc98-38af-7f28-1275b8f26c88.png">

"Others"を選択。

<img width="299" alt="スクリーンショット 2019-08-17 0.21.22.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/73825/1841c89f-56bb-2935-3411-ce81559378a5.png">

これで".vscode"ディレクトリに"tasks.json"が作られました。

<img width="787" alt="スクリーンショット 2019-08-17 0.22.22.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/73825/b409c98a-a438-f787-720a-fde2e264c868.png">

このままでは動かないので、公式ドキュメントに従って内容を書き換えて保存します。
例によってAtCoderはC++14なので、"-std=c++14"に変更しておきます。
"args"にあるファイル名やビルドオプションは都度変更してください。

```json:tasks.json
{
    "version": "2.0.0",
    "tasks": [
        {
            "label": "Build with Clang",
            "type": "shell",
            "command": "clang++",
            "args": [
                "-std=c++14",
                "-stdlib=libc++",
                "helloworld.cpp",
                "-o",
                "helloworld.out",
                "--debug"
            ],
            "group": {
                "kind": "build",
                "isDefault": true
            }
        }
    ]
}
```

ちなみに`"isDefault": true`は"shift+command+b"を押したときにこのタスクが実行されることを指定しています。

## launch.jsonを設定する

そろそろ疲れてきましたが、次はデバッグ設定のlaunch.jsonを作成します。
"shift+command+p"を押してコマンドパレットを開き、"debug"を入力します。
出てきた"Debug: Open launch.json"を選択します。

<img width="198" alt="スクリーンショット 2019-08-17 0.39.56.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/73825/63bb37ba-bc65-2cba-8c0d-09627a83a645.png">

環境の選択は"C++ (GDB/LLDB)"を選択。

<img width="154" alt="スクリーンショット 2019-08-17 0.42.11.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/73825/7b08268f-2542-6535-f308-1789b8c8aada.png">

これで".vscode"ディレクトリに"launch.json"が作られました。

<img width="974" alt="スクリーンショット 2019-08-17 0.43.52.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/73825/88c9165a-73db-01d1-38d8-df5dee07706b.png">

このままでは動かないので、公式ドキュメントに従って内容を書き換えて保存します。
"program"にある実行ファイル名は都度変更してください。

```json:launch.json
{
    "version": "0.2.0",
    "configurations": [
        {
            "name": "(lldb) Launch",
            "type": "cppdbg",
            "request": "launch",
            "program": "${workspaceFolder}/helloworld.out",
            "args": [],
            "stopAtEntry": true,
            "cwd": "${workspaceFolder}",
            "environment": [],
            "externalConsole": true,
            "MIMode": "lldb",
            "logging": {
                "trace": true,
                "traceResponse": true,
                "engineLogging": true
            }
        }
    ]
}
```

ちなみに`"externalConsole": true`で実行時にコンソールが開いて、cinでのAtCoderの入力ができるようになります。

## ソースコードファイルの追加

三種の神器を作成し終わったので、ようやくソースコードです。
"helloworld"ディレクトリを選択した状態で"新しいファイル"アイコンで"helloworld.cpp"を作成します。
(".vscode"ディレクトリ内に作らないように注意)

<img width="177" alt="スクリーンショット 2019-08-17 1.24.43.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/73825/5c823097-d328-0812-e1a2-5f849a8037b8.png">

本記事のAtCoder事例コードを貼り付けて保存します。
（ファイル名"helloworld"は不適当ですが、設定変更がめんどいのでそのまま行きます）

<img width="719" alt="スクリーンショット 2019-08-17 1.18.34.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/73825/8c31e859-9393-af1b-2594-aec154bd9be7.png">

これで以下ができるようになりました。

- インテリセンスでの情報表示

<img width="478" alt="スクリーンショット 2019-08-17 1.41.31.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/73825/f95321e4-1669-8e08-38ca-7d2c5e95f4ab.png">

- "shift+command+b"でのビルド

<img width="678" alt="スクリーンショット 2019-08-17 1.42.02.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/73825/64d6bee0-f357-52ae-55de-7c76ddb80042.png">

- "F5"でのデバッグ

<img width="719" alt="スクリーンショット 2019-08-17 1.45.00.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/73825/fdd0a600-779e-112f-f0bf-af913fed0b2e.png">


「勝ったッ！第3部完！ :muscle:」

## vectorの中身が見れない

「もうちっとだけ続くんじゃ :turtle:」

先ほどのコードを実際にデバッグしてみます。手順は以下。

- "shift+command+b"でビルド
- 実行を止めたい行で"F9"でブレークポイント設置（赤点がつく）
- "F5"でのデバッグ開始
- 裏で開いたコンソールでcinを入力(AGC012Aの入力例１を入力)

```
2
5 2 8 5 1 5
```

これでvectorが確保されたはずですが、デバッグ情報を見るとsize=0になっています。
Nは２になっているので入力は受け付けているようですが、なぜだ……

<img width="731" alt="スクリーンショット 2019-08-17 21.55.23.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/73825/587ab37d-7fb7-d207-16e4-e5b0f2bb934e.png">

ググったところ、同様の問題について対応されているページを見つけました。
VSCodeの拡張機能の"CodeLLDB"をインストールすれば表示されるようです。

[How to display local valiables of STL container classes when debugging C++ with LLDB on Visual Studio Code(macOS) - pyてょん日記](https://pyteyon.hatenablog.com/entry/2019/02/25/191049)

上記ページに従って、拡張機能の"CodeLLDB"をインストールし、"launch.json"の内容を下記のように変更しました。

```json:launch.json
{
    "version": "0.2.0",
    "configurations": [
        {
            "name": "(lldb) Launch",
            "type": "lldb",
            "request": "launch",
            "program": "${workspaceFolder}/helloworld.out",
            "args": [],
            "cwd": "${workspaceFolder}",
            "preLaunchTask": "Build with Clang"
        }
    ]
}
```

変更点は以下です。

- CodeLLDBのデバッガを使うよう`"type": "lldb"`に変更
- `"type": "lldb"`にしたことで無効になった項目を削除
- "preLaunchTask"にtask.jsonのビルドタスク"Build with Clang"を指定し、デバッグ時にビルドさせる
- （記載はないが、デフォルトで"terminal": "integrated"になってるらしく、VSCodeのコンソールでcinの入力が可能になっている）

この設定で再びデバッグ実行します。ビルドが自動で行われ、VSCodeのコンソールでcinの入力ができます。
すると、vectorのsize=2となり、中身もみれるようになりました！やった！

<img width="706" alt="スクリーンショット 2019-08-17 23.20.25.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/73825/2f64645f-cf47-cfed-851d-338c094d37c1.png">

## あとがき：AtCoderの解答のデバッグ

ここまでで"macのVSCodeでc++をデバッグする"は終わりですが、いちおう解答のデバッグ過程も記載します。
（コードの汚さには目をつぶってください( ⁎ᵕᴗᵕ⁎ )）

まず、vectorのsize=2がおかしいです。size=6になってほしい。
`vec(N)`を`vec(N*3)`に変更します。
これで提出したところ、WAがまだありました。

<img width="1106" alt="スクリーンショット 2019-08-17 23.45.24.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/73825/5ceda2a3-a1e5-6dda-d94b-002d551ffd47.png">

とりあえず"02.txt"の確認をしたいのでググったところ、AtCoderのテストケースがdropboxにありました。

[AtCoder のテストケース - AtCoder](https://atcoder.jp/posts/20)

```
// AGC012A 02.txt
// in
32
831110 85251598 809080936 4793 72499 406623270 49977839 82000 37391447 9667 4919 70349952 427 2 70814878 45827985 68 31437 6314566 44439 106047980 24 26 956 928 165903 73988 536 664777502 326 89 1081 5717 906 63 853 777895841 497384632 7454 769603857 437829321 27 60 2702070 842641727 346778983 677250412 85127322 384 13 12959963 316689 849040 483749 18679 4 87267 50249 212 162575 915 460731 560519748 624679 413 3 330775 3109 503452301 13 6718 47204018 7295103 100 584846 756668 1101 60 4757227 27 416135 40 6280524 895 819694 56 8199501 681384688 997756780 22490044 1 69 21 50810020 94677372 505547595
// out
4806411324
```
これを入力したところ、出力が511444028になりました。
正解の4806411324がintの最大2147483647を超えているので、オーバーフローしてます。
`int ans`を`long ans`にして提出し、無事ACになりました。

```c++
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;

int main(){
  int N;
  cin >> N;
  //vector<int> vec(N);
  vector<int> vec(N * 3);
  for(auto& v : vec){
    cin >> v;
  }
  sort(vec.begin(), vec.end(), greater<int>());
  //int ans = 0;
  long ans = 0;
  int count = N;
  bool second = false;
  for(auto& v : vec){
    if(second == false){
      second = true;
    }
    else{
      ans += v;
      second = false;
      --count;
      if(count == 0){
        break;
      }
    }
  }
  cout << ans << endl;
}
```

<img width="1101" alt="スクリーンショット 2019-08-18 0.09.50.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/73825/cc018d1b-5a4c-c127-13fe-57fe295c1e1d.png">

## おわりに

どうせこの記事の内容も、時間が経てば通らなくなると思うので、書く意味あるんかという気持ちでいっぱいです。
（個人的に非常に勉強になりましたが）

繰り返しになりますが、うまくいかない場合は、公式ドキュメントを参照することを強くお勧めします。
それでは、よきプログラミングライフを :tea: