チラシの裏からうっすら見える外枠の外のメモ書き

新聞に挟まってる硬い紙のチラシの裏からうっすら見える外枠の外に走り書きされたようなものです。思いついたときにふらふらと。

Visual Studio Codeで簡易的なC/C++のデバッグ(2017年4月版)

最近花粉症で鼻が辛い。

新年度が始まり、環境もやや変化したためその移行作業を行っている。変化したと言っても大幅に変化したわけではなく、ちょっとしたことなのだがそれが多いと面倒事も増える。今日はその面倒事の一つだった、Visual Studio Codeで簡単なC/C++ファイルのデバッグを行う方法について解説したい。

 

既にほぼ同じ内容の記事がたくさん公開されているので一見準備に困りそうにないのだが、地味に痛い点があったのでそこを中心に解説する。ただし、この記事はWindows向けの内容であり、macLinuxなどの別OSに関しては対象としていない。また、既にある記事を元に書いているため、以下リンクと合わせて読んでいただければ幸いである。

gabekore.org

 

 

早速必要なソフトウェアを紹介しよう。

Visual Studio Code ... Visual Studio Codeは、軽快に動作するテキストエディタ。今回はこのテキストエディタC/C++デバッグ環境を導入する。

Visual Studio Code - Code Editing. Redefined

 

MinGW ... 今回使用するC/C++コンパイラをインストールするソフトウェア。MinGWLinuxに含まれる様々なツールをWindows向けに提供している。このソフトウェアか以下に挙げるVisual Studioをインストールすればコンパイラは問題ない。もし、MinGWよりCygwinのほうがいいというのであればそちらを利用しても問題ないが、詳しくは解説しない。

MinGW | Minimalist GNU for Windows

Visual Studio ... Microsoft謹製の統合開発環境(IDE)。これにはC/C++コンパイラが含まれるためMinGWのどちらかをインストールすれば問題ない。ただし、Visual Studioはそれだけでテキストエディタデバッグ環境を持つため、この記事で解説するデバッグ環境を作成する必要はない。ただし、Visual Studioは非常に重いため、貧弱なノートパソコンなどではVisual Studio Code + MinGWをおすすめする。

Visual Studio | Developer Tools and Services | Microsoft IDE

 

これらをダウンロードしたら、早速作業開始だ。

 

Visual Studio Code編

Visual Studio Codeのインストール

まずはVisual Studio Codeをインストールしよう。上のURLからダウンロードしてきたインストーラーを実行し、インストール作業を進めてほしい。特に障害となるような点はないはずなので、ここでは詳しくは解説しない。

インストールが終わったら、次のステップだ。

拡張機能のインストール

Visual Studio Codeには拡張機能と呼ばれる有志が開発した機能を自由に追加することができる。C/C++デバッグのために必要となる機能もこの中に含まれている。インストールには、まずVisual Studio Codeを起動しよう。

f:id:k-hyoda:20170415004505p:plain

この画面の左には様々なアイコンが並んでいるのが確認できる。この中の一番下のアイコンをクリックしよう。

f:id:k-hyoda:20170415004708p:plain

アイコンのすぐ右横に「拡張機能」と書かれたタブが表示された。参考画像には既に拡張機能が幾つかインストールされているが、Visual Studio Codeをインストールした直後であれば何も並んでいないはずだ。すぐ近くに「Marketplace で拡張機能を検索」と書かれたテキストエリアがあるので、ここに次のように入力してほしい。

C/C++

Enterを押さなくても自動で検索が始まるはずだ。検索結果の中の「C/C++」をクリックし、右側に大きく表示された中の「インストール」を押そう。自動で拡張機能のインストールが始まり、完了するとインストールと書かれていた場所が「再度読み込む」になったはずだ。それをクリックしてVisual Studio Codeを再度読み込もう。

次も同じように拡張機能をインストールしてほしい。次に必要な拡張機能は以下の内容で検索すれば表示されるはずだ。

Runner

この拡張機能のインストールが成功すれば、Visual Studio Codeのインストール作業は終了だ。

 

コンパイラ

コンパイラのインストール

次に、コンパイラをインストールしよう。コンパイラMinGW(かCygwin)/Visual Studioのどちらかを使用してインストールすれば問題ない。インストール方法については上で挙げた記事で解説されているので、そちらを参考にしてほしい。

 

面倒になった 

この先の設定については面倒になったので、解説を省く。上の記事で解説がされているので、それの通りに進めれば問題ない。重要な点に関しては下で説明する。

 

今回のキモ

今回の記事で最も重要な点について触れていなかったので説明しよう。

まず、Visual Studioコンパイラを使用する人向けに1点。

上の記事で紹介していたcrun_vst.batのコンパイラの位置は、Visual Studio 2016のものだ。Visual Studio 2017を使用している場合はコンパイラの位置が違うので十分に注意してほしい。

そして次はどちらの環境でも発生するはずだが、上の記事を参考にVisual Studio Codeでデバッグする環境を準備しても、残念なことに幾つか問題が発生する。

まず、コンパイルが上手くいかない場合がある。

コンパイル時に発生するエラーの内容を掻い摘んで書くと、「Permission denied」ではないだろうか。これはその通りファイルを実行できていないということだ。なぜ発生するのかというと、コンパイル時にディレクトリ(コンパイラが起動するフォルダ)を適切に設定していないからだ。解決方法として、プログラムを開く際は「フォルダを開く」からそのプログラムがあるフォルダを開いてから、プログラムをコンパイルすればよい。

そして最も致命的な問題点、それは、標準入力がないということだ。

標準入力とは、ターミナルからユーザーの入力を受けるもので、Visual Studio Codeではその入力を待機することができないため、弊害が発生する。

簡単な例をご紹介しよう。

以下のコードは、ユーザーが入力した値を2倍にして出力するものだ。

    #include <stdio.h>
    
    int main(void){
        int in = 0;
        printf("値を入力してください。\n");
        scanf("%d", &in);
        printf("値は%dです。\n", in * 2);
        
        return 0;
    }    

 このプログラムをコンパイル(Shift + Ctrl + R)すると、次のようになる。

f:id:k-hyoda:20170415011053p:plain

画像のように、入力を待機している様子はない。また、それだけでなく、やや文字化けも発生している。

では、何が問題なのか考えてみよう。

まず、Visual Studio Codeは問題、出力、デバッグコンソール、端末の4つは標準で搭載している機能だ。しかし、この中に「入力」がない。これがまず1つ目の問題の原因である「Visual Studio Codeには標準入力がない」という点だ。

次に、Visual Studio CodeはUTF-8でプログラミングされているが、コンパイラWindowsの環境などの要因によって、Shift-JISなど別の文字コードが利用されている部分がある。これが2つ目の問題の原因である「文字コードの違いによって文字化けを発生させている」という点だ。

後者に関してはVisual Studio Code側で対応される可能性があるが、前者については対応されるかは未定である。

ではどう解決するのか。

 

コマンドプロンプトに表示してしまう

これらの問題の原因は結局「Visual Studio Codeが悪い」ということで片付けられてしまう。よって、この実行の部分だけをVisual Studio Codeから取り出してコマンドプロンプトで実行させれば良いのだ。ということで、早速プログラムを改変しよう。

crun_gcc.bat

    @echo off

    REM --------------------------------------------
    REM 引数が必要
    REM 引数が相対パスでもフルパスに変換
    REM %~d1 - %1 をドライブ文字だけに展開
    REM %~p1 - %1 をパスだけに展開
    REM %~n1 - %1 をファイル名だけに展開
    REM %~x1 - %1 をファイル拡張子だけに展開
    REM --------------------------------------------
    if "%~dpnx1" equ "" goto :eof

    REM --------------------------------------------
    REM 環境変数のローカル化開始
    REM --------------------------------------------
    setlocal

    REM --------------------------------------------
    REM 一時的に使うexeのファイル名を作る
    REM --------------------------------------------
    REM 日付と時間を使う、dateの前4桁(YYYY)を削除、timeの:を削除
    set tempfile=%date:~4%%time::=%
    REM / を削除
    set tempfile=%tempfile:/=%
    REM . を削除
    set tempfile=%tempfile:.=%
    REM 空白を削除
    set tempfile=%tempfile: =%


    REM --------------------------------------------
    REM コンパイル実行(gcc)
    REM --------------------------------------------
    gcc -o %tempfile%.exe "%~dpnx1"

    REM --------------------------------------------
    REM EXEファイル実行
    REM --------------------------------------------
    start /w run.bat %tempfile%.exe

    REM --------------------------------------------
    REM EXEファイル削除
    REM --------------------------------------------
    del %tempfile%.exe

    REM --------------------------------------------
    REM 環境変数のローカル化終了
    REM --------------------------------------------
    endlocal

crun_vst.bat

    @echo off

    REM --------------------------------------------
    REM 引数が必要
    REM 引数が相対パスでもフルパスに変換
    REM %~d1 - %1 をドライブ文字だけに展開
    REM %~p1 - %1 をパスだけに展開
    REM %~n1 - %1 をファイル名だけに展開
    REM %~x1 - %1 をファイル拡張子だけに展開
    REM --------------------------------------------
    if "%~dpnx1" equ "" goto :eof

    REM --------------------------------------------
    REM 環境変数のローカル化開始
    REM --------------------------------------------
    setlocal
    
    REM --------------------------------------------
    REM 一時的に使うexeのファイル名を作る
    REM --------------------------------------------
    REM 日付と時間を使う、dateの前4桁(YYYY)を削除、timeの:を削除
    set tempfile=%date:~4%%time::=%
    REM / を削除
    set tempfile=%tempfile:/=%
    REM . を削除
    set tempfile=%tempfile:.=%
    REM 空白を削除
    set tempfile=%tempfile: =%


    REM --------------------------------------------
    REM 開発者コマンド プロンプト for VS2015を実行
    REM 必要な環境変数を設定
    REM パスは「開発者コマンド プロンプト for VS2015」のプロパティ参照
    REM --------------------------------------------
    call "C:/Program Files (x86)/Microsoft Visual Studio 14.0/Common7/Tools/VsDevCmd.bat"

    REM --------------------------------------------
    REM コンパイル実行(gcc)
    REM --------------------------------------------
    cl /Fe%tempfile%.exe "%~dpnx1"

    REM --------------------------------------------
    REM EXEファイル実行
    REM --------------------------------------------
    start /w run.bat %tempfile%.exe

    REM --------------------------------------------
    REM EXEファイル削除
    REM --------------------------------------------
    del %tempfile%.exe

    REM --------------------------------------------
    REM 環境変数のローカル化終了
    REM --------------------------------------------
    endlocal

 このように書き換えたら、次はコンパイルするプログラムがある同じフォルダに、run.batというファイルを作成して、以下の内容を記述してほしい。

    %~dpnx1
    pause
    exit

こうすることで、このフォルダにあるプログラムをコンパイルしたときはコマンドプロンプトが表示されて、そこでプログラムが実行されるはずだ。また、pauseコマンドが挿入されているため、画面が表示されてすぐ消えるといった問題に遭遇することも減る。

f:id:k-hyoda:20170415020053p:plain

 

 

このように、Visual Studio Codeにはまだ不便な面が多いため、そういった問題に遭遇した際はぜひ自分でうまく解決する方法を探ってほしい。

私はこれで、非力なノートパソコンでVisual Studio CodeのC言語プログラミングを行おうと思う。