VSCodeでMacOSにC言語デバッグ環境を構築

VSCodeでMacOSにC言語デバッグ環境を構築する方法の解説ページアイキャッチ

今回は VSCode でC言語プログラムをデバッグする方法について解説します。

これにより、C言語を任意の行で止めることができ、その時の変数の中身を確認することができるようになります。

VSCodeでC言語プログラムが停止する様子

はっきり言ってめっちゃ便利です!!

プログラムの問題の特定や修正が楽になりますので、その分開発や勉強も捗ります。

特に MacOSX ユーザー向けの解説になりますが、他の OS を利用している方にも参考になると思います。うまく VSCode でデバッグができない、設定できたけどその意味がまだ理解できていない、という方には是非読んでみていただければと思います!

前準備

まずは前準備を行っていきましょう!

コンパイラとデバッガーのインストール

VSCode で C言語をデバッグするためには、C言語のソースコードから実行可能ファイルを生成する「コンパイラ」と、その実行可能ファイルをデバッグするための「デバッガー」が別途必要になります。

まずはこの2つをインストールし、ターミナルアプリから実行できる環境を整えましょう!

特に MacOSX の方は、コンパイラとデバッガーとして下記をインストールすることをお勧めします。今後もこの2つを使用することを前提に解説を進めていきます。

  • コンパイラ:GCC
  • デバッガー:LLDB

この2つは Xcode + コマンドラインツールをインストールすることで同時にインストールすることができます。

下記のページあたりがわかりやすいので参考にすると良いと思います。

https://qiita.com/ShinichiOkayama/items/962e55ac7f8920a5f007

他の OS の方は、「”OS 名” gcc インストール」、「”OS 名” lldb インストール」のような感じでググれば詳しいインストール方法が載っているページにたどり着けるはずです。

スポンサーリンク

コンパイラとデバッガーの動作確認

続いてインストールしたコンパイラとデバッガーの動作確認を行っていきましょう。

コマンドラインで下記のコマンドを実行してみましょう!

gcc -v

エラーが発生することなく実行でき、下記のようにバージョン情報が表示されれば GCC のインストールは成功です。

Configured with: --prefix=/Library/Developer/CommandLineTools/usr --with-gxx-include-dir=/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/c++/4.2.1
Apple clang version 11.0.0 (clang-1100.0.33.17)
Target: x86_64-apple-darwin19.2.0
Thread model: posix
InstalledDir: /Library/Developer/CommandLineTools/usr/bin

表示内容は違っていても良いです。エラーが出ないことが重要です。

さらに、コマンドライン(MacOSX であればターミナルアプリ)で下記のコマンドを実行してみましょう。

lldb -v

こちらもエラーが発生することなく実行でき、下記のようにバージョン情報が表示されれば LLDB のインストールは成功です。

lldb-1100.0.30.12
Apple Swift version 5.1.3 (swiftlang-1100.0.282.1 clang-1100.0.33.15)

ここまでが確認できれば前準備はバッチリです。

これにより、GCC と LLDB がインストールされていることと、GCC と LLDB に PATH が通っていることが確認できました。

ここからは VSCode で C言語プログラムをデバッグする方法を解説していきますが、結局は GUI (VSCode の画面)で、ここまでで準備してきた GCC と LLDB を実行するだけです。

VSCode で C言語プログラムをデバッグ

それではここからは本題である VSCode で C言語をデバッグする方法について解説していきます。

CodeLLDB プラグインのインストール

特に MacOSX の Catalina (もしくはそれ以降)ユーザーにとって重要なのは、使用するのに GDB ではなく LLDB を用いることです。

なぜなら、MacOSX の Catalina 以降のバージョンでは、GDB は VSCode からうまく動作させられなくなっている可能性があるからです。

いや、もしかしたら本当は上手く GDB 使ってデバッグさせられるのかもしれません。ただ私はその方法がわかりませんでした…。ネットでググっても GDB にバグがあるなどの書き込みがあったりしましたので…。

ですので、特に MacOSX ユーザーの方は、ひとまず「GDB」は諦めて「LLDB」を使う方が無難だと思います。

で、LLDB 使うのであれば「CodeLLDB」プラグインだと楽にデバッグを始められると思いましたので、CodeLLDB をベースにこのページでは解説しています。

ちなみに「C/C++」プラグインでも LLDB は利用できるようですので、その方法についてはC/C++ プラグインでのデバッグで解説しています。

ちょっと前置きが長くなってしまいましたが、「CodeLLDB」のインストール方法は下記のとおりです。

プラグイン管理画面を表示する

まずは画面左側にある下記のボタンをクリックします。

するとプラグイン管理画面を表示されます

プラグイン管理画面表示ボタン

CodeLLDB を検索する

次にプラグイン管理画面上部にある検索フォームに「CodeLLDB」と入力します。

すると CodeLLDB プラグインが表示されます。

CodeLLDBを検索する様子

CodeLLDB をインストールする

あとは「Install」ボタンをクリックするだけです。これにより「CodeLLDB」プラグインがインストールされます。

スポンサーリンク

ワークスペースの作成

CodeLLDB のインストールが終わったら、次はワークスペースの作成を行います。

ワークスペースとは VSCode での作業場(フォルダ)のことです。VSCode からワークスペースに指定したフォルダ以下のファイルが操作(C言語ファイルの編集など)ができるようになり便利です。

メニューバーの「ファイル」の「フォルダーをワークスペースに追加…」をクリックします。

VSCodeにワークスペースを追加する様子

すると、フォルダを選択する画面が表示されますので、C言語ソースコードが格納されているフォルダ、もしくはそれより上の階層のフォルダを選択し、「追加」ボタンをクリックします。

VSCodeにワークスペースを追加する様子2

「追加」ボタンをクリックすると画面の左側にワークスペースの情報が表示されます。指定したフォルダ以下のファイルが表示されていればワークスペースの作成は完了です。

VSCodeにワークスペースを追加する様子3

ワークスペースは保存することが可能で、保存しておくと次回 VSCode を開いた際に再度そのワークスペースを開くことができるようになります。

ワークスペースの保存はメニューバーの「ファイル」→「名前を付けてワークスペースを保存…」により行うことができます。

.json の設定

続いてデバッグおよびビルドの設定を行なっていきます(ビルドとは C言語ソースコードをコンパイルやリンクを行って実行可能プログラムを作成する処理のことを言います)。

この設定は .json ファイルを編集することで行うことができます。具体的には launch.json と tasks.json を作成し、その設定を行います。

ここではまずデバッグを行うことを優先し、.json の作り方についてのみ説明していきます。.json の設定方法については .json の詳細以降で解説します。

launch.json の設定

まずは launch.json の設定を行なっていきます。launch.json はデバッグを行うための設定ファイルです。特に CodeLLDB プラグインにおいては、LLDB を用いてプログラムをデバッグするための設定ファイルとなります。

と言っても、ワークスペース作成直後の状態だと launch.json が存在しませんのでまずはこの launch.json を作成する必要があります。

そのためにメニューバーの「実行」→「デバッグの開始」をクリックします。

launch.jsonの作成1

すると、「環境の選択」メニューが表示されますので「LLDB」を選択します。

launch.jsonの作成2

選択すると、下記のようなエラーが表示されてしまいます。

launch.jsonの作成3

これはまずは気にしなくて良いです。「OK」ボタンをクリックしましょう。

「OK」ボタンをクリックすると、ワークスペース直下に自動的に .vscode フォルダが作成され、その中に launch.json が作成されます。

launch.jsonの作成4

この launch.json を選択すれば、launch.json の編集画面が画面右側に表示されます。

launch.jsonの作成5

この launch.json を編集することで、デバッガーの設定を行うことができます。

まずは丸々 launch.json の中身を削除し、下記をコピペして保存してください。

launch.json
{
    // IntelliSense を使用して利用可能な属性を学べます。
    // 既存の属性の説明をホバーして表示します。
    // 詳細情報は次を確認してください: https://go.microsoft.com/fwlink/?linkid=830387
    "version": "0.2.0",
    "configurations": [
        {
            "name": "c_debug",
            "type": "lldb",
            "request": "launch",
            "program": "${fileDirname}/${fileBasenameNoExtension}",
            "args": [],
            "cwd": "${fileDirname}",
            "preLaunchTask": "c_build"
        }
    ]
}

ひとまずコピペし、ファイルを保存していただければデバッガーを起動するための launch.json の設定は完了です。

tasks.json の設定

続いて tasks.json の設定を行なっていきます。launch.json はデバッガー(lldb)を実行するための設定ファイルであったのに対し、tasks.json はコンパイル(gcc)を実行するための設定ファイルとなります。

まずは tasks.json を作成します。

下の図のように、.vscode フォルダにマウスを合わせて右クリックを行い、さらに「新しいファイル」をクリックします。

tasks.jsonの作成1

すると新規ファイルのファイル名入力が行えますので、下図のように名前を「tasks.json」に設定します。すると「tasks.json」ファイルが作成されます。

tasks.jsonの作成2

さらに作成した「tasks.json」ファルをクリックすれば、下の図のように「tasks.json」の編集画面が画面右側に表示されます。

ここに下記をコピペし、ファイルの保存を行ってください。

tasks.json
{
    // tasks.json 形式の詳細についての資料は、
    // https://go.microsoft.com/fwlink/?LinkId=733558 をご覧ください
    "version": "2.0.0",
    "tasks": [
        {
            "type": "shell",
            "label": "c_build",
            "command": "gcc",
            "args": [
                "-g",
                "${file}",
                "-o",
                "${fileDirname}/${fileBasenameNoExtension}"
            ],
            "group": "build"
        }
    ]
}

ひとまずこれでビルドを行うための設定は完了です。

ブレークポイントの設定

ここからはいよいよデバッグ作業に移っていきます。

まずはワークスペースからデバッグを行いたい C言語ソースコードのファイルをクリックして選択します。画面右側にソースコードの内容が表示されると思います。

VScodeにソースコードが表示される様子

行番号の左側にマウスカーソルを合わせ、クリックを行うことで赤丸()を付加することができます(再度クリックすると赤丸が消える)。

ブレークポイントの設定2

この赤丸の部分がブレークポイントとなります。このブレークポイントを設定しておくことで、プログラムをその時点で一旦停止させることができます。

まずは好きな箇所にこのブレークポイントを設定してみましょう!

スポンサーリンク

デバッグの実行

次はいよいよデバッグの実行です。ブレークポイントを設定した C言語ソースコードを表示した状態で、メニューバーの「実行」から「デバッグ開始」をクリックします。

デバッグの実行1

すると、下の図のようにブレークポイントを設定した箇所でプログラムが停止し、その行が黄色背景で表示されるはずです。

デバッグの実行2

この状態で左側のデバッグ画面を見てみると、変数の中身やコールスタックが確認できると思います。

デバッグの実行3

これで .json が上手く設定され、デバッグ可能な状態になったことが確認できました!

scanf 関数などで標準入力からの受付を行う場合は画面下側の「ターミナル」から入力を行うことができます。

標準入力からの受付

表示されていない場合はメニューバーの「表示」→「ターミナル」を選択することで表示できます。

この標準入力が設定不要で行えるのは「CodeLLDB」の良いところだと思います(C/C++ プラグインだと設定が必要だったはず)。

様々なプログラム実行方法

このプログラムを停止させた状態からは下図で示すボタンをクリックすることで、様々なプログラムの実行が可能です。

プログラム操作ボタン

各ボタンを押した時にプログラムがどのように動作するかは下記にまとめた通りになります。

  • 続行ボタン [一番左のボタン]:次のブレークポイントまでプログラムを進める(ブレークポイントが他にない場合はプログラムは最後まで実行)
  • ステップオーバーボタン [左から二番目のボタン]:プログラムを1行だけ実行(その行が関数呼び出しの場合、関数実行後までプログラムが進む)
  • ステップインボタン [左から三番目のボタン]:プログラムを1行だけ実行(その行が関数呼び出しの場合、その関数の最初までプログラムが進む)
  • ステップアウトボタン [左から四番目のボタン]:プログラムを関数終了直後まで進める
  • 再起動ボタン [左から五番目のボタン]:プログラムを最初から再起動する
  • 停止ボタン [一番右側のボタン]:デバッグを終了する

.json の詳細

デバッグを行う際に、下記の2つの .json ファイルを作成しました。

  • launch.json
  • tasks.json

ここではこの2つの役割や記述されている内容について解説を行います。

スポンサーリンク

launch.json と tasks.json の役割

この2つの .json の役割を理解するために、まず思い浮かべていただきたいのが、C言語プログラムを実行する際の手順です。

ソースコードを書いたら、下記のことを行うと思います。

  1. ビルド実行(ソースコードをコンパイル・リンクしてプログラムを作成)
  2. プログラム実行(実行可能ファイルを実行)

.jsonの役割1

VSCode でこの2手順を GUI から実行するための設定ファイルが launch.json と tasks.json になります。

1. のビルド実行の設定を行うのが tasks.json です。

.jsonの役割2

この tasks.json を設定することで、VSCode の GUI からビルドを行うことが可能になります。

より具体的には、メニューバーの「ターミナル」→「タスクの実行 or ビルドタスクの実行」をクリックした際に、この tasks.json が読み込まれ、tasks.json に設定されたタスクを実行することができます。

そして 2. のプログラム実行の設定(デバッグの設定)を行うのが launch.json です。

.jsonの役割3

この launch.json を設定することで、VSCode の GUI からプログラム実行・デバッグを行うことが可能になります。

より具体的には、メニューバーの「実行」→「デバッグ開始 or デバッグなしで開始」をクリックした際に、この launch.json が読み込まれ、launch.json の設定に基づいてプログラム実行(デバッグ実行)が行うことができます。

MEMO

本当はこれらの .json で設定できるのはビルドやデバッグのみではありません

が、今回は C言語のデバッグに焦点を当てているので、この2つについてのみ解説します

launch.json 設定の詳細

それでは各 .json ファイルで設定する項目や launch.json の設定と tasks.json の設定で紹介した .json ではどのような設定を行なっていたのかについて解説していきたいと思います。

まずは launch.json から解説します。

launch.json
{
    // IntelliSense を使用して利用可能な属性を学べます。
    // 既存の属性の説明をホバーして表示します。
    // 詳細情報は次を確認してください: https://go.microsoft.com/fwlink/?linkid=830387
    "version": "0.2.0",
    "configurations": [
        {
            "name": "c_debug",
            "type": "lldb",
            "request": "launch",
            "program": "${fileDirname}/${fileBasenameNoExtension}",
            "args": [],
            "cwd": "${fileDirname}",
            "preLaunchTask": "c_build"
        }
    ]
}

各行は基本的に「”xxx” : “yyy”」の形式で記述されていますが(配列の場合は ” ” ではなく[ ] になる)、xxx は設定項目を表す key で、yyy はその設定値を表す value となります。

.jsonの書き方

上記の launch.json に出てきた key は、それぞれ下記の設定を行うものになります。

  • “name”:デバッグ設定の名前(分かり易ければ何でも OK)
  • “type”:デバッガーのタイプ( “lldb” のままで OK)
  • “request”:デバッグの仕方(”launch” だとプログラム実行してデバッグ、”attach” だと実行中のプログラムに対してデバッグ)
  • “program”:実行するプログラムのファイルパス
  • “args”:プログラムに渡す引数
  • “cwd:プログラムを実行するフォルダ
  • “preLaunchTask”:プログラム実行前に実行するタスクの名前

CodeLLDB プラグインを利用する場合は、基本的に “type” には “lldb” を設定すれば良いです。

preLaunchTask にはこの launch.json でプログラム実行を行う前に実行したいタスクを指定します。

ですので、ここにビルドを行うタスクの名前を記述しておけば、「デバッグ開始」「デバッグなしで開始」を実行した際に、ビルドを行なってからデバッグを行うことが可能になり便利です(上記の launch.json でも tasks.json で設定した名前のタスクを指定していることが確認できると思います)。

また launch.json や tasks.json では特定の変数が利用できます。

  • ${file}:現在表示しているファイルへの絶対パス
  • ${fileDirname}:現在表示しているファイルが存在するフォルダへの絶対パス
  • ${fileBasenameNoExtension}:現在表示しているファイルの拡張子を除去した文字列
  • ${workspaceFolder}:ワークスペースへの絶対パス

例えば下のようなフォルダ構成で赤色のファイルを表示している場合、

フォルダ構成と変数

「デバッグ開始」「デバッグなしで開始」を実行した際には各変数に下記が格納されることになります。

  • ${file}:/Users/daeu/programming/calc/add.c
  • ${fileDirname}:/Users/daeu/programming/calc
  • ${fileBasenameNoExtension}:add
  • ${workspaceFolder}:/Users/daeu/programming/

ですので、上記の launch.json では、下記のパスのプログラムが実行されることになります。

/Users/daeu/programming/calc/add

また上の図の青色のファイルを表示して「デバッグ開始」「デバッグなしで開始」を実行した際には下記のパスのプログラムが実行されます。

/Users/daeu/programming/bit/not

こんな感じで変数をうまく設定してやれば、わざわざ実行するプログラム毎にパス変更しなくても、自動的に設定することができるようになります。

他にも、この launch.json を変更することで、プログラム実行時の設定を変えることができます。

例えば launch.json を変更することでプログラムに引数を渡すようなこともできます。具体的な方法はデバッグ・ビルドのカスタマイズで解説します。

tasks.json の設定の詳細

tasks.json は実は色々なことを設定できるファイルですが、C言語のデバッグにおいては、ビルドの実行の設定を行うために使用すると便利です。

基本的な書き方や使用できる変数は launch.json と同様です。

tasks.json
{
    // tasks.json 形式の詳細についての資料は、
    // https://go.microsoft.com/fwlink/?LinkId=733558 をご覧ください
    "version": "2.0.0",
    "tasks": [
        {
            "type": "shell",
            "label": "c_build",
            "command": "gcc",
            "args": [
                "-g",
                "${file}",
                "-o",
                "${fileDirname}/${fileBasenameNoExtension}"
            ],
            "group": "build"
        }
    ]
}

この tasks.json で登場した key は、それぞれ下記の設定を行うものになります。

  • “type”:タスクの種類(shell:コマンドの実行、process:シェルスクリプトやバッチファイルやプログラムの実行)
  • “label”:タスクの名前
  • “command”:実行するコマンド
  • “args”:↑ のコマンド実行時に渡す引数
  • “group”:タスクの種類

特に “type” が “shell” の場合、”args” で指定した配列を引数として “command” に指定したコマンドが実行されるようになると考えて良いです。

ですので、上述の tasks.json の場合は「タスクの実行」もしくは「ビルドタスクの実行」を行った際には下記のコマンドが実行されることになります。

gcc -g ${file} -o ${fileDirname}/${fileBasenameNoExtension}

ポイントは “args” に指定した “-g” オプションです。このコンパイルオプションはプログラムの「デバッグ情報」を生成するためのオプションです。

これを付けないと、上手くプログラムが止まらない等が起こるので “デバッグ時” は必ず付けておくようにしましょう。

また、-o オプションではビルドで生成するプログラムのファイル名を指定することになりますので、launch.json の “program” の設定値と同じものになるようにしましょう(名前が違うとビルドで生成されたプログラムと異なるプログラムが実行されてしまうようになります)。

他にも、この task.json を変更することで様々なビルド設定を行うことができます。例えば複数のソースコードで分割コンパイルしたり、ライブラリをリンクしたりすることも可能です。

これらの具体的な方法は次のデバッグ・ビルドのカスタマイズで解説します。

スポンサーリンク

デバッグ・ビルドのカスタマイズ

ここからは .json を変更してデバッグ実行やビルド実行のカスタマイズを行う例を紹介したいと思います。

引数を指定してデバッグを行う

引数を指定してデバッグを行うために変更するのは launch.json です。引数を指定するのはビルド実行時ではなく、プログラム実行時(デバッガー実行時)ですよね?

なので、プログラムに引数を指定するためには、プログラム実行の設定ファイルである launch.json を変更します。

引数は launch.json の “args” に設定を行うことで指定することができます。

例えば下記のように launch.json を指定すれば、

launch.json
{
    // IntelliSense を使用して利用可能な属性を学べます。
    // 既存の属性の説明をホバーして表示します。
    // 詳細情報は次を確認してください: https://go.microsoft.com/fwlink/?linkid=830387
    "version": "0.2.0",
    "configurations": [
        {
            "name": "c_debug",
            "type": "lldb",
            "request": "launch",
            "program": "${fileDirname}/${fileBasenameNoExtension}",
            "args": [
                "aiueo",
                "123"
            ],
            "cwd": "${fileDirname}",
            "preLaunchTask": "c_build"
        },
    ]
}

デバッグ時にプログラムの第1引数として「”aiueo”」、第2引数として「”123″」を指定できます。

分割コンパイルを行う

次は分割コンパイルを行う方法です。

分割コンパイルとは複数の C言語ソースコードをコンパイルし、その結果をリンクして実行可能ファイルを生成するコンパイル方法になります。

例えば下記コマンドを実行すれば、同じフォルダにある main.c と sub1.c と sub2.c を分割コンパイル(リンク)してプログラムファイル output.exe が生成されます。

gcc main.c sub1.c sub2.c -o output.exe

この分割コンパイルは tasks.json を変更することで行うことができます。

編集すべき箇所は “args” で、ここに同時にコンパイル(&リンク)したいファイルを並べる感じで指定します。

例えば tasks.json を下記のように記載して「タスクの実行」 or 「デバッグ開始」を行えば、main.c と sub1.c と sub2.c が分割コンパイルされ、その結果をリンクして一つの実行ファイルが生成されます。

tasks.json
{
    // tasks.json 形式の詳細についての資料は、
    // https://go.microsoft.com/fwlink/?LinkId=733558 をご覧ください
    "version": "2.0.0",
    "tasks": [
        {
            "type": "shell",
            "label": "c_build",
            "command": "gcc",
            "args": [
                "-g",
                "${fileDirname}/main.c",
                "${fileDirname}/sub1.c",
                "${fileDirname}/sub2.c",
                "-o",
                "${fileDirname}/${fileBasenameNoExtension}"
            ],
            "group": "build"
        }
    ]
}

いちいちファイル名を記述するのが面倒な場合は下記のようにワイルドカードを用いて「*.c」を使うことも可能です。

tasks.json
{
    // tasks.json 形式の詳細についての資料は、
    // https://go.microsoft.com/fwlink/?LinkId=733558 をご覧ください
    "version": "2.0.0",
    "tasks": [
        {
            "type": "shell",
            "label": "c_build",
            "command": "gcc",
            "args": [
                "-g",
                "${fileDirname}/*.c",
                "-o",
                "${fileDirname}/${fileBasenameNoExtension}"
            ],
            "group": "build"
        }
    ]
}

これにより、フォルダ内の全C言語ファイルがコンパイルされてリンクされるようになります。

いちいちファイル名を指定しなくても楽ですが、フォルダ内に不要なC言語ファイルがあるとリンクに失敗することもありますので注意しましょう。

スポンサーリンク

ライブラリをリンクする

ライブラリのリンクも tasks.json の “args” を変更することで VSCode から実行できるようになります。例えば libjpeg と libpng と libtiff をリンクする場合は下記のようになります。

tasks.json
{
    // tasks.json 形式の詳細についての資料は、
    // https://go.microsoft.com/fwlink/?LinkId=733558 をご覧ください
    "version": "2.0.0",
    "tasks": [
        {
            "type": "shell",
            "label": "c_build",
            "command": "gcc",
            "args": [
                "-g",
                "${fileDirname}/*.c",
                "-ljpeg",
                "-lpng",
                "-ltiff",
                "-o",
                "${fileDirname}/${fileBasenameNoExtension}"
            ],
            "group": "build"
        }
    ]
}

複数のデバッグ・ビルド設定を行う

launch.json や tasks.json では1つだけではなく、複数の構成を設定することが可能です。

プログラムやC言語ソースコードの構成(引数指定する必要がある or なし・分割コンパイルする or しない・ライブラリをリンクする or しない)に応じて launch.json や tasks.json を変更するのは面倒ですので、事前に複数の構成を記述しておくと便利です。

例えば下記のように launch.json と tasks.json を記述しておくと、「c_debug」の構成でデバッグを行った場合は事前に「c_build」でビルドが実行され、「c_divide_debug」の構成でデバッグを行った場合は事前に「c_divide_build」でビルドが実行されるようになります。

launch.json
{
    // IntelliSense を使用して利用可能な属性を学べます。
    // 既存の属性の説明をホバーして表示します。
    // 詳細情報は次を確認してください: https://go.microsoft.com/fwlink/?linkid=830387
    "version": "0.2.0",
    "configurations": [
        {
            "name": "c_debug",
            "type": "lldb",
            "request": "launch",
            "program": "${fileDirname}/${fileBasenameNoExtension}",
            "args": [],
            "cwd": "${fileDirname}",
            "preLaunchTask": "c_build"
        },
        {
            "name": "c_divide_debug",
            "type": "lldb",
            "request": "launch",
            "program": "${fileDirname}/${fileBasenameNoExtension}",
            "args": [],
            "cwd": "${fileDirname}",
            "preLaunchTask": "c_divide_build"
        },
    ]
}
tasks.json
{
    // tasks.json 形式の詳細についての資料は、
    // https://go.microsoft.com/fwlink/?LinkId=733558 をご覧ください
    "version": "2.0.0",
    "tasks": [
        {
            "type": "shell",
            "label": "c_build",
            "command": "gcc",
            "args": [
                "-g",
                "${file}",
                "-o",
                "${fileDirname}/${fileBasenameNoExtension}"
            ],
            "group": "build"
        },
        {
            "type": "shell",
            "label": "c_divide_build",
            "command": "gcc",
            "args": [
                "-g",
                "${fileDirname}/*.c",
                "-o",
                "${fileDirname}/${fileBasenameNoExtension}"
            ],
            "group": "build"
        }
    ]
}

分割コンパイルを行う or 行わないに応じて tasks.json を変更し直す必要がなく、構成の選択だけで切り替えることができるようになります。

こんな感じで複数の構成を launch.json や tasks.json に記述しておくと、デバッグやビルドがさらに楽になります。

デバッグの構成の切り替えはデバッグ画面の下図のオレンジ枠の部分で切り替えることができます。

デバッグの構成の切り替え

こんな感じで .json を変更することにより様々なデバッグやビルドが行えるようになります。

C/C++ プラグインでのデバッグ

ここまでは CodeLLDB プラグインでのデバッグ方法について解説してきましたが、最後に「C/C++」プラグインによるデバッグ方法について解説していきたいと思います。

C/C++ プラグインによるデバッグ環境の構築方法と CodeLLDB プラグインによるデバッグ環境の構築方法の大きな違いは下記の2つです。

  • インストールするプラグイン
  • launch.json の書き方

他に関してはおそらく同じです。デバッグ方法なども。

ですので、例えば tasks.json に関しては使用するプラグインがどちらであっても同じ内容で良いはずです。なので、ここまで解説してきた内容を参考にして作成していただければと思います。

ここからは上記の違いのある2点について解説していきます。

スポンサーリンク

C/C++ プラグインのインストール

まずはプラグインを検索してインストールします。

基本は CodeLLDB と同じ方法でインストールできますが、検索するときの文言が違う点だけ注意してください。

C/C++ プラグインは「C/C」などで検索するとすぐ見つけられると思います。

私の場合は特に設定変更は不要で、インストールした状態ですぐに利用可能でした。

launch.json の作成

次に launch.json を作成します。

で、この launch.json の作り方が CodeLLDB と若干違うので注意が必要です。

C/C++ プラグインを利用するときの launch.json の基本は下記のようになると思います。

launch.json
{
    // IntelliSense を使用して利用可能な属性を学べます。
    // 既存の属性の説明をホバーして表示します。
    // 詳細情報は次を確認してください: https://go.microsoft.com/fwlink/?linkid=830387
    "version": "0.2.0",
    "configurations": [
        {
            "name": "c_debug",
            "type": "cppdbg",
            "MIMode": "lldb"
            "request": "launch",
            "program": "${fileDirname}/${fileBasenameNoExtension}",
            "args": [],
            "cwd": "${fileDirname}",
            "preLaunchTask": "c_build"
        }
    ]
}

name が他の実行構成と重複してしまっている場合はてきとうに変更してください。

黄色背景の部分が CodeLLDB との違いになります。この2つについて解説していきます。

type

type は「構成の種類」を指定する設定のようです。

要はこの実行構成を用いてプログラム実行する場合に、どのプラグインを利用するかを指定する設定になると思います。

ですので、type に “lldb” を指定すると CodeLLDB プラグインが動作します。

一方、C/C++ プラグインを動作させたいのであれば、type には “cppdbg” を指定する必要があります。

MIMode

MIMode は C/C++ プラグインが使用するデバッガーの設定になります。

設定できるのは “gdb” もしくは “lldb” で、デバッガーとして GDB を使用したい場合は “gdb”、LLDB を使用したい場合は “lldb” を指定します。

つまり、先ほどの launch.json では C/C++ に LLDB デバッガーを使用するように設定していることになります。GDB を利用したい場合は MIMode を “gdb” に設定してください(私の環境だと上手く動いてくれなかったので私は “lldb” を設定しています)。

launc.json のその他の設定

デバッグ・ビルドのカスタマイズでも紹介しているように、launch.json を変更してデバッグ方法をカスタマイズすることが可能です。

で、CodeLLDB と C/C++ では launc.json で指定可能な key が異なるので注意してください。

ただ、デバッグ・ビルドのカスタマイズで使用している key は基本的なものばかりで、どれも C/C++ でも利用可能だと思います。

ですので、C/C++ でのデバッグのカスタマイズにおいても、デバッグ・ビルドのカスタマイズがそのまま参考になると思います。

ただし、前述の通り CodeLLDB とは下記が異なりますので、その点だけ注意して launch.json を編集するようにしてください。

  • type:C/C++ プラグインの場合は “cppdbg” を指定する
  • MIMode:C/C++ の場合は追加が必要。”gdb” もしくは “lldb” を指定する

まとめ

このページでは特に MacOS で VSCode を用いてC言語をデバッグする方法について解説しました。

基本的に VSCode では PC 内にインストールされている GCC や LLDB を利用しているだけなので、事前に GCC と LLDB をインストールし、PATH を通しておくことが上手くデバッグするためのポイントだと思います。

あとは .json をこのページに記載しているように作成すれば上手くデバッグできるはず…!

上手く動かないなどありましたら、協力できるかもしれませんので気軽にコメントをいただければと思います!

27 COMMENTS

Kちゃん

なるほどー。それぞれのjsonが何をしているのかよくわかっていなかったので勉強になりました。私は下記で設定していました。
ワークスペースでしか機能しなかったのですが、${workspaceFolder}を${fileDirname}に書き換えることで、どこでもデバッグできるようになりました。ありがとうございます。

launch.json
“`
{
“version”: “0.2.0”,
“configurations”: [
{
“name”: “clang build and debug active file”,
“type”: “lldb”,
“request”: “launch”,
“program”: “${fileDirname}/${fileBasenameNoExtension}.out”,
“args”: [],
“cwd”: “${workspaceFolder}”,
“preLaunchTask”: “clang build active file”
}
]
}
“`

tasks.json
“`
{
“version”: “2.0.0”,
“tasks”: [
{
“label”: “clang build active file”,
“type”: “shell”,
“command”: “clang”,
“args”: [
“${fileBasename}”,
“-o”,
“${fileBasenameNoExtension}.out”,
“-g”
],
“group”: {
“kind”: “build”,
“isDefault”: true
}
},
{
“type”: “shell”,
“label”: “gcc build active file”,
“command”: “/usr/bin/gcc”,
“args”: [
“-g”,
“${file}”,
“-o”,
“${fileDirname}/${fileBasenameNoExtension}”
],
“options”: {
“cwd”: “/usr/bin”
}
}
]
}
“`

daeu

Kちゃん

コメントありがとうございます!
そしてこのページのリクエスト、本当にありがとうございました!!

少しでも参考になったのであればこちらとしても嬉しいです。

.json がうまく使いこなせれば複雑なファイル構造のプロジェクトも簡単にビルドできるようになりそうな気がしています。

また有益な情報・役立ちそうな情報を発見したら記事アップしたいと思います。
暇な時にでもこのサイトに寄っていただければ幸いです。

いっとく

最新の環境下でのこのような記事,本当にありがたいです.
ところで,C言語ではなくC++の場合のlaunch.jsonやtasks.jsonの設定についても解説していただけると大変嬉しいのですが,どのあたりが差分になってくるのでしょうか.

daeu

いっとくさん

コメントありがとうございます!

正直言うと C++ に関してはあまり自信がないのですが、
基本は tasks.json の下記部分を、

"command": "gcc",

下記に変更すれば C++ のデバッグもできるようになるのではないかと思います(一応私の環境ではデバッグできることを確認しています)。

"command": "g++",

これによりビルド時に用いるコマンドが “gcc” から “g++” に変わり、.cpp などのソースコードファイルをコンパイルできるようになるはずです。

もし上手くデバッグできない、エラーが出る、こんなことができるように .json を変更したい、などがありましたら、
その内容を教えていただければ協力できるかもしれないです(力になれなかったら申し訳ないですが…)。
また気軽にコメントいただけると幸いです!

ryusei

デバッグを実行しようとしたところ、以下のエラーが出てしまいました。どのように対処すればよろしいでしょうか。

> Executing task in folder Work: g++ -g -o /Users/ryusei/Desktop/Work/20200511/B-3/b-3.cpp /Users/ryusei/Desktop/Work/20200511/B-3/b-3 <

clang: error: no such file or directory: '/Users/ryusei/Desktop/Work/20200511/B-3/b-3'
clang: error: no input files
ターミナルの処理が終了しました (終了コード: 1)

daeu

ryusei さん

コメントありがとうございます。

エラーの内容を見ての判断ですが、args の指定の順番に問題ありそうな気がします。

下記のように “-o” の直後に入力ファイル名(ソースコードファイル名)が指定されていないでしょうか?

"args": [
    "-g",
    "-o",
    "${file}",
    "${fileDirname}/${fileBasenameNoExtension}"
],

“-o” の直後にはコンパイルして生成されるファイルのパスを指定する必要があります。
下記のように “-o” の直後に生成されるファイルのパスを指定するように args の順番を変更すればビルドできるようにならないでしょうか?

"args": [
    "-g",
    "-o",
    "${fileDirname}/${fileBasenameNoExtension}",
    "${file}",
],

ちなみにビルドされた際に “-o” で指定したファイルは上書きされるので注意してください。

例えば入力ソースコードファイル名(${file})を指定したりすると、
ビルド終わったときに入力ソースコードファイルが上書きされてせっかく書いたソースコードが消えてしまいます…。

上記で問題解決しない場合、差し支えなければ tasks.json の内容をコメント欄もしくは問い合わせにコピペしていただければ、もう少し詳細な解析ができると思います。
(公開したくない部分は適当に文字列を置き換えていただいて大丈夫です)

ryusei

素早い回答ありがとうございます。正常に動作いたしました。
上書きされてしまうのですね…なるほど…

daeu

ryusei さん

正常に動作したようで良かったです!
また何かありましたら気軽にコメント等いただければと思います。
よろしくお願いいたします!

おきな

説明がとても分かりやすかったです。勉強になりました。ありがとうございます。

こちら1つの問題があります。私はbreak point(main関数のところに)を設定し、デバッグしようとしたら、プログラムは設定したbreak pointに飛ばずに、そのまま実行されてしまいました。これはどの辺の間違いでしょうか。

回答できれば、大変嬉しいです。

daeu

おきなさん

コメントありがとうございます!

break point で止まらない要因としては主に下記が挙げられると思います。
まずはこの辺りを見直してみるのが良いと思います。
・コンパイル時に “-g” オプションが付けられていない
・「デバッグなしで実行」を選択してプログラムを実行している
・コンパイル時からソースコードのファイルの場所が移動している
・LLDB が上手く動作できていない

差し支えなければ、tasks.json と launch.json をコメント欄にコピペしていただければ、もう少し具体的なアドバイスができるかもしれないです。

おきな

素早い回答ありがとうございます。正常に動作いたしました。

原因はdaeuさんおっしゃった通り「「デバッグなしで実行」を選択してプログラムを実行している」でした。誠にありがとうございます。

daeu

おきなさん

返信ありがとうございます!

正常に動作したみたいで、私としても大変嬉しいです。
ステップ実行はすごく便利ですので、是非どんどん活用してみてください!
また何か不明点などございましたら、気軽にコメントいただければと思います。

おきな

度々すみません。おきなです。
先ほどコメントしたんですが、記録が無くなったみたいで、もう一度コメントします。

こちらは2つの質問がありますが。

1つ目はlaunch.jsonにおけるrequestの役割について、

“request”:デバッグの仕方(”launch” だとプログラム実行してデバッグ、”attach” だと実行中のプログラムに対してデバッグ)

と書いていますが、そのattachにはどんな時に使うのはあまり理解していないです。もし具体的な例を頂けると嬉しいです。

2つ目はtask.jsonにおけるargsの書き方ですが。

【書き方1】
“args”: [
“-g”,
“-o”,
“${fileDirname}/${fileBasenameNoExtension}”,
“${file}”,
]

【書き方2】
“args”: [
“-g”,
“${file}”,
“-o”,
“${fileDirname}/${fileBasenameNoExtension}”,
]

【書き方1】と【書き方2】にはどっちでも正しいですか。

質問が多くて、すみません。どうぞ宜しくお願いします。

daeu

おきなさん

質問ありがとうございます!

まず質問の1点目について返答します。

具体的な例ですが、私は Python プログラムとC言語プログラムを一緒にステップ実行したい場合に使用しています。

Python では、例えば OpenCV などのC言語(正確にはC++)のライブラリが使用されます。

この時、Python に対するデバッガーを launch で仕掛けることで Python プログラム起動時に Python に対してデバッガーを動作させます。これで Python プログラムに対してブレークポイントを設定できるようになります。

一方で、Python で OpenCV を使用する場合、Python 起動時に OpenCV も起動してしまいます。

この状態だと Python のデバッガーしか起動させていないので、OpenCV に対してはデバッガーしか仕掛けられていないことになります。

そこで、C言語のデバッガーを attach で起動し、後から OpenCV にデバッガーを仕掛けるようにしています。

もしかしたら下記ページなどは参考になるかもしれません。

https://daeudaeu.com/opencv_debug/

とりあえずC言語プログラムのみをデバッグするのであれば、launch を使用するので良いと思います!

2点目の質問ですが、どちらの書き方でも問題ないです!

基本的にコンパイラに指定するオプション(”-g”)などは自由な順番で付加することができます。

ただし「”-o” の後に “${fileDirname}/${fileBasenameNoExtension}” を記述する」という順番は守る必要があります。

“-o” はコンパイラが生成する実行ファイルの出力ファイル名を指定するオプションです。
ですので、その後にはファイル名を指定する必要があります。

上記の例だと “${fileDirname}/${fileBasenameNoExtension}” がそのファイル名に相当しています。

ですので “-o” の後に “-g” を指定したりすると、出力するファイル名が指定されていないことになるのでおそらくコンパイルエラーになると思います。

おきなさんが提示された例だと両方とも “-o” でちゃんと出力するファイル名が指定されているのでどちらでも問題ないです。

おきな

素早い回答ありがとうございます。

文章を拝見しました。とりあえずattachの役割やオプション(-g & -o)について理解しました。とても丁寧な説明でありがとうございます。

Kazuma

この設定方法でデバックができるようになりました!
質問です。違うフォルダでCのデバックをしたい時も同じような設定をしなければいけないでしょうか?

daeu

Kazumaさん

コメントありがとうございます!
デバッグできるようになったのことで、お役に立てたのであれば嬉しいです。

異なるフォルダにあるソースコードをデバッグ実行したい場合は、基本的には同じような設定をする必要があります。

具体的にはワークスペースの設定と .json の設定(コピペで良いと思います)が必要です。

ただし、下記のようなフォルダ構成で、C言語のソースコードが同じ階層のフォルダ内に集められているのであれば、上位のフォルダをワークスペースに設定してやれば1回の設定で、全てのフォルダのC言語ソースコードをデバッグ実行することができるはずです。

c-program(上位フォルダ)
 hello_world
  hello_world.c
 list_struct
  list_struct.c

より具体的には、上記のフォルダ構成であれば、”c-program” フォルダをワークスペースに設定し、さらに .json の設定も行ってやれば、これだけで hello_world.c も list_struct.c のデバッグも行えます。

実際私も上記のようなフォルダ構成にしていますので、デバッグ用の設定は1回しか行っていないです。

参考になれば幸いです。

Kazuma

ご返信ありがとうございます!
なるほど、そうすればいいんですね!!詳しくありがとうございます!!!

daeu

Kazuma さん

コメントありがとうございます!
もしまた不明点などありましたら気軽に質問していただければと思います。
今後ともよろしくお願いいたします。

kose

わかりやすく解説いただきありがとうございます!
一点詰まっているところがありまして。。。

記事通りに進めていったのですが、デバッグができない状態で困っています。
実行ファイルとdSYMファイルは作成されていますが、
メニューバーから実行を行うと、VSCodeのポップアップにて、
process resume at entry point failed: Resume timed out.
と出ています。

CodeLLDB、jsonファイルなどは記事通りに設定しております。
お手数をおかけしますが、お知恵をお借りできますと幸いです。

daeu

kose さん

コメントありがとうございます!
エラーが出てしまいましたか…。

念のための確認ですが、lldb コマンドが実行可能であることは確認済みでしょうか?

詳細は下記に記載しています。

https://daeudaeu.com/vscose_debug_c/#i-3

確認済みであれば、CodeLLDB の設定か、この拡張機能自体に問題あるかもしれないですね…。
だとすると他の拡張機能で代替できるかもしれません。

とりあえず私の方でも環境合わせたりしてエラーが出る原因や代替案など調べてみますね!

ちょっと時間取れなくて今週いっぱいとか時間かかるかもしれませんが…。すみませんが返信までちょっとお待ちいただけるとありがたいです。

daeu

kose さん

すみません、私の方では同じ現象が再現できませんでした…。

もしかしたらプラグインが上手く動作させられていない可能性もあるので、下記で紹介している「C/C++」を利用してみてはいかがでしょうか?

https://daeudaeu.com/vscose_debug_c/#ccpp

もしこれでもダメな場合、launch.json に下記を追加して C/C++ プラグインでデバッグを実行し、その時に「デバッグコンソール」に表示されるログの内容を教えていただけると何かわかるかもしれません

            "logging": {
                "engineLogging": true
             }

それでも分からなかったらごめんなさいですが…。
ちなみにログには名前など入っている可能性もあるので、必要に応じて見せたくない部分は他の文字で置換するなどしていただいて大丈夫です。

上記を追加した launch.json の例は下記のようになります。

        {
            "name": "cppdebug",
            "type": "cppdbg",
            "MIMode": "lldb",
            "request": "launch",
            "program": "${fileDirname}/${fileBasenameNoExtension}",
            "cwd": "${fileDirname}",
            "preLaunchTask": "c_build",
            "logging": {
                "engineLogging": true
             }
        },
みお

上記の記事、拝見し、非常にわかりやすく、深いところまで理解できました。
有益な記事を作ってくださり、ありがとうございました。

ただ、今現在、記事の通りにやったのですが、
This platform (arm64-darwin) is not suported.
と画面下に表示が出てしまい、全く動かない状態です。

ちなみに環境は以下の通りです。
macos bigsur
バージョン 11.2.3
macbook air(m1,2020)

vscode(通常のとinsider、両方で試しました。)
通常版 1.55
insider 1.56

下記の記事を参考にして取り組もうとしたのですが、ファイル等のダウンロードに外国版のアプリが必要みたいで、解決できませんでした。
https://github.com/vadimcn/vscode-lldb/issues/397
https://github.com/microsoft/vscode-cpptools/issues/6839

どうかご教示いただけますでしょうか?

daeu

みおさん

コメントありがとうございます!

CPUアーキテクチャが変わったことが影響してるようですね…。
私のPC古いので、この件について気付けていませんでした。すみません…。

https://github.com/vadimcn/vscode-lldb/issues/397

↑ のコメントにもあるように、M1向けのパッケージを開発してくれているようです。下記からダウンロードできると思います。

https://github.com/vadimcn/vscode-lldb/releases/download/v1.6.2-dev.2103261710/codelldb-aarch64-darwin.vsix

こちらを利用しても同様のエラーになりますか?
VSIXファイルからの拡張機能のインストール方法は下記ページが参考になると思います。

https://mseeeen.msen.jp/how-to-install-extension-in-visual-studio-code-with-vsix/

もしかしたらまだ何かしら設定など必要あるのかもしれませんが…。

みお

ご返答ありがとうございます。
ダウンロードしたvsixファイルを参考webの通りにインストールしたら、無事、デバッグできました!
vsixファイルって、インストールに一手間いるんですね。参考になりました。

また、この記事のおかげで複数のファイルをデバッグすることもでき、私のc言語開発が大きく進展しそうです。
本当に感謝しております。
ありがとうございました。

daeu

みおさん

ご返信ありがとうございます!

自身の環境で試せなかったので上手くいくかどうか心配だったのですが、無事動作するようになってよかったです!

そのうち M1 に対応した安定版もおそらくリリースされると思いますので、その際に安定版にアップデートしてやれば良いと思います。

記事が役に立って私としてもたいへん嬉しいです!
また何か疑問点などありましたら、気軽に質問などいただければ幸いです。

#間違って本名を入力されていた可能性があったので、私の方で名前欄を修正させていただきました
 不要な対応であったなら申し訳ございません…

みお

名前、本名書いてましたね。
訂正して下さり、ありがとうございます。

今後ともよろしくお願いいたします!

現在コメントは受け付けておりません。