@mtbforq (たくみ 宮迫)

Are you sure you want to delete the question?

If your question is resolved, you may close it.

Leaving a resolved question undeleted may help others!

We hope you find it useful!

C言語、fopen実行時のエラー

解決したいこと

fopen実行時にファイルが作成されません。
fopen実行時にファイルが作成されるようにしたいです。

実行環境: windows10, VSCode

発生している問題・エラー

デバッグ時にエラーは表示されておりません。

該当するソースコード

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

int main(void)
{
    FILE *file;
    file = fopen("test.txt", "w");
    fprintf(file, "Hello World");
    fclose(file);

    return 0;
}

自分で試したこと

モードはr, r+, w, w+, a, a+で試しましたが結果はどれもファイル作成には結びつきませんでした。
また、if (file == NULL) {printf("エラー");} を追記し試してみたところ、「エラー」と表示されたので、
そもそもfopenの時点で成功していないと思われます。

一体どういった原因なのでしょうか・・・?

0 likes

1Answer

以前の回答 (2月6~9日)
ファイルを探す場所が間違っている可能性はないでしょうか? なお、以下のようにすれば、オープンに失敗したかどうか確認できます。 追加1: エラーの原因を探れるように、エラーコードが分かるようにしました。 追加2: カレントディレクトリを表示するようにしました。 追加3: コメントを付けました。
code
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
#include <sys/param.h>

int main(void) {
    char buff[MAXPATHLEN]; // 読み出しバッファ
    if (getcwd(buff, MAXPATHLEN) == NULL) { // カレントディレクトリの取得、できなかったら
        printf("getcwd() failed"); // 失敗の報告
        exit(EXIT_FAILURE); // エラー終了
    }
    printf("current dir: '%s'\n", buff); // カレントディレクトリの表示
    FILE *file = fopen("test.txt", "w"); // ファイルを開く
    if (file == NULL) { // 開けなかった
        printf("fopen() failed error #%d", errno); // エラー番号の表示
        exit(EXIT_FAILURE); // エラー終了
    }
    printf("opened"); // 開けた
    fprintf(file, "Hello World"); // ファイルに書き込む
    fclose(file); // ファイルを閉じる
    return EXIT_SUCCESS; // 正常終了
}

エラーコード
errno 定数 (Microsoft)
ERRNO (JM Project)

新しい回答 (2月10日)

コメントのやりとりを経て行き詰まったので、実際に環境を構築して確認してみました。

環境

質問者様との環境の相違によって以降の記述通りにはならないと思いますので、あらかじめご承知おきください。

  • Windows 10 Pro 20H2 (x64)
  • Visual Studio Code 1.53.0
    • C/C++ 1.2.0
  • gcc (x86_64-posix-seh-rev0, Built by MinGW-W64 project) 8.1.0

確認用コード

環境に合わせて新しい確認用コードを用意しました。

code
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <io.h>

int main(void) {
    char buff[_MAX_PATH]; // 読み出しバッファ
    if (getcwd(buff, _MAX_PATH) == NULL) { // カレントディレクトリの取得、できなかったら
        printf("getcwd() failed"); // 失敗の報告
        exit(EXIT_FAILURE); // エラー終了
    }
    printf("current dir: '%s'\n", buff); // カレントディレクトリの表示
    FILE *file = fopen("test.txt", "w"); // ファイルを開く
    if (file == NULL) { // 開けなかった
        printf("fopen() failed error #%d", errno); // エラー番号の表示
        exit(EXIT_FAILURE); // エラー終了
    }
    printf("opened"); // 開けた
    fprintf(file, "Hello World"); // ファイルに書き込む
    fclose(file); // ファイルを閉じる
    return EXIT_SUCCESS; // 正常終了
}

試行 1

確認コードを開いて「F5」キーを押し、プルダウンメニューからgccを選ぶと、実行とともにlaunch.jsonが勝手に開きました。

初期の起動構成

launch.json
{
    // IntelliSense を使用して利用可能な属性を学べます。
    // 既存の属性の説明をホバーして表示します。
    // 詳細情報は次を確認してください: https://go.microsoft.com/fwlink/?linkid=830387
    "version": "0.2.0",
    "configurations": [
        {
            "name": "gcc.exe - アクティブ ファイルのビルドとデバッグ",
            "type": "cppdbg",
            "request": "launch",
            "program": "${fileDirname}\\${fileBasenameNoExtension}.exe",
            "args": [],
            "stopAtEntry": false,
            "cwd": "C:\\Program Files\\mingw-w64\\x86_64-8.1.0-posix-seh-rt_v6-rev0\\mingw64\\bin",
            "environment": [],
            "console": "externalTerminal",
            "MIMode": "gdb",
            "miDebuggerPath": "C:\\Program Files\\mingw-w64\\x86_64-8.1.0-posix-seh-rt_v6-rev0\\mingw64\\bin\\gdb.exe",
            "setupCommands": [
                {
                    "description": "gdb の再フォーマットを有効にする",
                    "text": "-enable-pretty-printing",
                    "ignoreFailures": true
                }
            ],
            "preLaunchTask": "C/C++: gcc.exe アクティブなファイルのビルド"
        }
    ]
}
  • 実行ファイルは、以下のように表現されています。
    • "program": "${fileDirname}\\${fileBasenameNoExtension}.exe"
    • ${fileDirname}がフォルダで、${fileBasenameNoExtension}.exeがファイル名ですね。
  • カレントディレクトリは以下です。
    • "cwd": "C:\\Program Files\\mingw-w64\\x86_64-8.1.0-posix-seh-rt_v6-rev0\\mingw64\\bin"
    • これは、gnuコンパイラのパスですね。
    • 当然、Program Filesに対する書き込み権限はないので、エラーになります。

実行結果

result
current dir: 'C:\Program Files\mingw-w64\x86_64-8.1.0-posix-seh-rt_v6-rev0\mingw64\bin'
fopen() failed error #13
  • カレントディレクトリとしてgnuコンパイラのパスが表示されています。
  • fopen()で権限エラー(13)が報告されています。

試行 2

起動構成の改修

「実行」メニューから「構成を開く」を選択してlaunch.jsonを編集しました。

launch.json
{
    // IntelliSense を使用して利用可能な属性を学べます。
    // 既存の属性の説明をホバーして表示します。
    // 詳細情報は次を確認してください: https://go.microsoft.com/fwlink/?linkid=830387
    "version": "0.2.0",
    "configurations": [
        {
            "name": "gcc.exe - アクティブ ファイルのビルドとデバッグ",
            "type": "cppdbg",
            "request": "launch",
            "program": "${fileDirname}\\${fileBasenameNoExtension}.exe",
            "args": [],
            "stopAtEntry": false,
            "cwd": "${fileDirname}", // 変更箇所
            "environment": [],
            "console": "externalTerminal",
            "MIMode": "gdb",
            "miDebuggerPath": "C:\\Program Files\\mingw-w64\\x86_64-8.1.0-posix-seh-rt_v6-rev0\\mingw64\\bin\\gdb.exe",
            "setupCommands": [
                {
                    "description": "gdb の再フォーマットを有効にする",
                    "text": "-enable-pretty-printing",
                    "ignoreFailures": true
                }
            ],
            "preLaunchTask": "C/C++: gcc.exe アクティブなファイルのビルド"
        }
    ]
}
  • 実行ファイルのフォルダ${fileDirname}をカレントディレクトリに指定しています。

実行結果

再度「F5」キーを押しました。

result
current dir: 'd:\development\VSCodeTest'
opened

問題なくファイルが作られました。

0Like

Comments

  1. @mtbforq

    Questioner

    ご回答いただきありがとうございます。
    上記のコードにてデバッグしたところ、やはり「fopen() failed」が返ってきました・・・。
    この場合はfopen()に失敗しているわけなので、そもそもtest.txtファイルは作られていないという認識でよろしいでしょうか?
    また、その場合の原因もご存じでしたら教えていただきたいです・・・。
  2. はい、そうですね。
    エラーコードが取得できるようにコードを修正しましたので、再度お試しください。
  3. @mtbforq

    Questioner

    ありがとうございます。
    修正していただきましたコードにて試してみましたが、
    「error #13」と表示されます。
    (パーミッションに関するエラーでしょうか・・・)
    実行するexeファイルのプロパティでパーミッションを確認してみたところ、SYSTEM、ユーザー名ともにアクセス許可の欄は「フルコントロール」、「変更」、「読み取りと実行」、「読み取り」、「書き込み」、が許可されています。

    また、GetLastError()を実行してみたところ、
    こちらは「err=5」と返してきます。
    以下に実行コードを貼らせていただきます。

    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    #include <errno.h>
    // #include "stdafx.h"
    #include "windows.h"


    void dspErrorInfo ( void );

    int main(void) {
    FILE *file;
    file = fopen("kani.txt", "w");
    if (file == NULL) {
    printf("fopen() failed error #%d", errno);
    dspErrorInfo();
    exit(EXIT_FAILURE);

    }

    printf("opened");
    fprintf(file, "Hello World");
    fclose(file);

    return EXIT_SUCCESS;
    }

    void dspErrorInfo()
    {
    DWORD err = GetLastError();
    printf( "err=%d\n", err );

    LPTSTR msg = NULL;
    FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER
    | FORMAT_MESSAGE_FROM_SYSTEM
    , NULL
    , err
    , MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US)
    , ( LPTSTR )&msg
    , 0
    , NULL
    );
    printf( "msg=%S\n", msg );

    // FormatMessage内部で確保した領域を解放
    LocalFree( msg );
    }


    (ちなみにmsgは何も取得しておらず、「msg=」と表示されます。)

  4. ファイルを作ろうとしているフォルダに対して、そのプログラムは、どのような権限を持っているのでしょうか?
    (そもそも、何処にファイルを作ろうとしているのでしょうか?)
  5. @mtbforq

    Questioner

    VSCodeで作業フォルダAがあり、A内にファイルB.cとファイルB.exeが存在する状況です。ファイルB.exeを実行(デバッグ)することで作業フォルダA内に.txtファイルを作ろうとしております。
    知識不足で大変恐縮ですがこの場合作業フォルダAに対してファイルB.exeが持つ権限とはどういったものでしょうか?
  6. OSにもよりますが、一般に、ファイルやフォルダには、ユーザー毎に権限が与えられます。
    ログオンしているユーザが、`B.exe`に対する実行権限を有していれば、それを実行することができます。
    実行された`B.exe`は、実行したユーザの権限でファイルにアクセスしようとします。
    ユーザが`A`フォルダに対する書き込み権限を有していれば、ユーザにより実行された`B.exe`は、フォルダ内にファイルを作ることが可能です。
    その状況でも、"test.txt"が既存で、ユーザがそのファイルに対して書き込み権限を有していない場合は、ファイルを作り直すための権限不足でエラーになります。
  7. @mtbforq

    Questioner

    フォルダA、ファイルB.exe、ともにそれぞれのファイルの「プロパティ」よりアクセス権を「フルコントロール」に設定して再度実行しましたが、結果は変わらず、エラーコードも同じでした・・・。
  8. 本当にフォルダAにファイルを作ろうとしているのでしょうか?
    カレントディレクトリを表示するようにコードを改修したので、再度お試しください。
  9. @mtbforq

    Questioner

    すみません・・・。
    なぜかはわかりませんが問題なく動いてファイルも作成できるようになりました。
    今までデバッグはF5キーで実行していたのですが、
    「gcc ファイル名.c -o ファイル名」を実行してからexeファイルを作り、
    その後「./ファイル名」を実行すると問題なく動き、ファイルも作成できました。
    これらはF5キーでのデバッグが邪道であるということを示しているのでしょうか?
    自分の認識違いで恐縮ですが、デバッグをする際はF5キーではなく、
    「gcc ファイル名.c -o ファイル名」をした後、「./ファイル名」とするのが正しいデバッグの方法なのでしょうか?
  10. 質問者様の環境については存じませんで、正道/邪道については判別がつかないのですが、選択できる以上は間違いではないのだと思います。
    そして、今回のエラーの原因は、先に述べた「カレントディレクトリ」にあると考えています。

    新たに「『./ファイル名』を実行」されたとのことですが、それは実行ファイルのフォルダがカレントディレクトリになっていることを表します。

    エラーする場合は、カレントディレクトリが異なるフォルダになっているのでしょう。
    それは、更新されたコードで確認可能です。(是非とも、ご確認ください。)

    一般に、カレントディレクトリは、実行ファイルの所在とは異なる、ユーザーのドキュメントが置かれるフォルダになっていることが多いのではないでしょうか。
  11. @mtbforq

    Questioner

    何度も教えていただきありがとうございます・・・。
    お時間を使わせてしまい大変恐縮です・・・。
    「./ファイル名(.exeファイル)」を実行できることから、
    カレントディレクトリが「ファイル名.c」、「ファイル名.exe」、「自作ヘッダーファイル」等が入っている、元となるフォルダであることがわかります。
    また、その状態でF5キーでデバッグをしてデバッグが実行できないので、
    カレントディレクトリが「実行ファイル等が入っているフォルダ」であるにも関わらず
    デバッグできない状態にある、と言えると思うのですが、一体どういうことなんでしょうか・・・。(この時、runnerでのファイルの実行もエラーが発生し、実行できません。)
    ご紹介いただきましたファイルの通りにlaunch.jsonの"cwd"を"${fileDirname}"に変更しましたが、同じエラーが発生します。
    どうやってもf5キー、runnerでのデバッグができない場合は、OSの問題の可能性もあると思うので、仕方なく直接VSCodeのコンソールに「gcc ファイル名A.c ファイル名B.c -o ファイル名a(.exe)」 → 「./ファイル名A(.exe)」を打ち込んでデバッグするようにするしかなさそうですね・・・。
  12. 実行ファイル名を入力する場合と、F5キーでは、カレントディレクトリが異なるのだろうと思います。
    更新されたコードをF5キーで実行した際に、カレントディレクトリが何処と表示されるかご確認いただけると助かります。
  13. @mtbforq

    Questioner

    カレントディレクトリは「ファイル名.c」、「ファイル名.exe」、「自作ヘッダーファイル」等が入っている、元となるフォルダが表示されました。
    "cwd":"${workspaceFolder}"でも同じ結果でした。
    "cwd":""ではエラーが発生し、実行できませんでした。
    (各gcc → ./ファイル名、 で実行)
    F5キーを押した際にだけエラーが起きるので、gcc → ./ファイル名、 でデバッグしていこうと思います。
  14. @mtbforq

    Questioner

    質問しておいて誠に勝手なんですが、数日間連絡が取れなくなるので、ご返信いただいても返信できない可能性があります・・・。
  15. つまり、「F5キーを使った場合」でも「"./ファイル名"の場合」でも、カレントディレクトリは同じになるにもかかわらず、前者は書き込みアクセス権がなく、後者は書き込みアクセス権があるというわけですね?
    VS Codeのデバッガの仕様ということならどうしようもないのかも知れませんね。
    何度もお試しいただいたのに、さっぱりお力になれず申し訳ございません。

    通信事情のお知らせありがとうございます。
    お互いに、いつ応えられるかどころか、そもそも応答できるるかどうかも解らないものでしょうから、どうぞお気になさらず。
  16. 実際に環境を構築して確認した上で、回答を全面的に書き直しました。

Your answer might help someone💌