一時的にデータを置いておきたいけれど、ファイル名の衝突や片付け忘れの心配をしたくない。
このような時に便利なのがC言語のtmpfile
です。
実行中だけ読み書きでき、閉じると自動削除されるため、安全な一時保存に向いています。
初心者の方にもわかりやすく、基本からサンプルまで丁寧に解説します。
tmpfileとは?安全な一時ファイルの基本
tmpfileのメリット
tmpfile
は、一時的に使うファイルを作成し読み書き可能なFILE*
ストリームを返します。
作成されるのはバイナリ更新モード(読み書き両用)で、実行中に自由に書き込みと読み出しを行えます。
最大の利点は以下の2点です。
1つ目は自動削除です。
閉じるとファイルが消えるため、クリーンアップ漏れを防げます。
2つ目は競合や盗み見のリスクが低いことです。
特にPOSIX系(OS XやLinux)ではファイル名が他プロセスから見えない挙動が一般的で、他プロセスが誤って開く危険が大きく減ります。
自動削除の仕組み
C標準規格ではtmpfile
は閉じる時(fclose
)、またはプログラムの正常終了時に自動削除されると定められています。
POSIX系では内部的に「作ってすぐリンクを外す(無名化する)」か、OSの匿名一時ファイル機能を使う実装が多く、そもそもファイル名が存在しないため、他プロセスから参照しにくくなります。
Windowsでは削除予約(削除フラグ)を付けた命名ファイルとして作られ、クローズ時に確実に消えるのが一般的です。
使いどころ
tmpfile
は次のような場面に向いています。
- 計算途中の中間データを一時退避したい場合
- メモリに収まらないデータを一時的にディスクへ溢れさせたい場合(スプール)
- センシティブなデータを短時間だけ保管したい場合
ファイル名の管理が不要で、片付けも自動なので、実装や運用の手間を抑えられます。
tmpfileの使い方
FILE*を作成する
基本の呼び出しはとてもシンプルです。
FILE*
を受け取り、失敗時はNULL
が返ります。
戻り値のNULL
チェックは必須です。
ディスク容量不足や権限不足で作れない可能性があります。
FILE* fp = tmpfile();
if (!fp) { /* エラー処理 */ }
書き込み→読み出し→閉じる
tmpfile
は読み書き両用のストリームです。
書いた後に読む(またはその逆)を行う時は、fseek
かrewind
で位置を動かす必要があります。
これはC標準のルールで、書き込み直後に位置移動せずに読み出すのは未定義動作となるため注意してください。
- 書き込み:
fprintf
、fputs
、fwrite
など - 読み出し:
fscanf
、fgets
、fread
など - 位置移動:
rewind(fp)
またはfseek(fp, 0, SEEK_SET)
以下は、tmpfile
で一時ファイルを作成し、テキストを書き込んでから読み出す基本例です。
実際に戻り値チェックと位置移動も行っています。
#include <stdio.h>
#include <stdlib.h> // EXIT_SUCCESS, EXIT_FAILURE
int main(void) {
// 一時ファイルを作成 (読み書き両用のバイナリ更新モードで開かれる)
FILE *fp = tmpfile();
if (fp == NULL) {
// 失敗した場合は標準エラーにメッセージを出して終了
perror("tmpfile");
return EXIT_FAILURE;
}
// いくつかのデータを書き込む (ここではテキスト)
// fprintfやfputsなど、通常のファイルと同じ要領で使えます
fprintf(fp, "user=%s\n", "alice");
fprintf(fp, "score=%d\n", 42);
fputs("hello, tmpfile\n", fp);
// 書き込みから読み出しに切り替える前に、ファイル位置を先頭へ戻す
// 書き→読みの切り替えでは、rewindやfseek(またはfflush)が必須
rewind(fp);
// 1行ずつ読み出して標準出力に表示
char buf[128];
puts("=== read back ===");
while (fgets(buf, sizeof buf, fp) != NULL) {
fputs(buf, stdout);
}
// 使い終わったら必ず閉じる (この時点で一時ファイルは自動削除されます)
if (fclose(fp) == EOF) {
perror("fclose");
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
=== read back ===
user=alice
score=42
hello, tmpfile
- 書き→読みの切り替えで
rewind
を必ず呼ぶ(またはfseek
/fsetpos
/fflush
) - 最後に
fclose
を確実に呼ぶ(自動削除が働きます) - 書式化入出力(
fprintf
/fscanf
)や行入出力(fgets
)、1文字単位(fgetc
/fputc
)、バイナリ(fwrite
/fread
)も、通常のファイルと同様に使えます
エラー時はNULLを確認
tmpfile
がNULL
を返した場合は、以下のような可能性が考えられます。
- 一時ディレクトリが存在しない、または書き込み権限がない
- ディスク容量不足(クォータ超過を含む)
- OSの制限によりファイル数上限に達している
エラー時のフェイルセーフとして、メモリに切り替える、処理をスキップするなどの代替策を検討してください。
読み書き位置を戻す場合
読み→書き、または書き→読みへ切り替えるたびに、rewind(fp)
かfseek(fp, 0, SEEK_SET)
のような「位置操作」を挟みます。
細かな違いは次のとおりです。
rewind(fp)
: 先頭へ移動し、エラー/EOF状態もクリアしますfseek(fp, 0, SEEK_SET)
: 先頭へ移動します(エラー状態はクリアされません)
詳しい位置制御(fseek
やftell
など)の解説は別記事に譲りますが、切り替え時に位置操作を忘れないことだけは覚えておきましょう。
安全に使うための注意点
ファイル名が無い利点と制限
POSIX系では多くの実装で無名の一時ファイルとして扱われ、他のプロセスからファイル名で開けないのが大きな利点です。
一方で、自分でファイル名を知る手段が無いため、別プロセスへ引き渡す用途には向きません。
Windowsでは内部的に名前を持つ実装が多いですが、自動削除フラグが付くため片付けは同様に安全です。
機密データの一時保存に向く理由
tmpfile
は寿命が短く、他プロセスからの参照が困難なため、パスワードのハッシュ計算や鍵素材の一時保存などに適しています。
さらに、バイナリI/O(fwrite
/fread
)を使えば、テキスト化によるフォーマット漏れや改行混入を避けられます。
ただし機密性はOS・権限・ディスクの暗号化状況に依存します。
システム全体のセキュリティ方針も合わせて検討してください。
ディスク容量と寿命に注意
一時ファイルといえど物理的にはディスクを使うため、大量データの一時退避では容量不足に注意が必要です。
SSDでは大量の書き込みが寿命に影響する場合もあります。
メモリで十分足りるなら、メモリバッファやメモリマップなども選択肢です。
逆に、メモリに載らない場合にはtmpfile
で安全にスワップするのが有効です。
使い終わったらfclose
必ずfclose(fp)
で閉じることで自動削除が確実に行われます。
例外が発生しうる言語バインディングや複数returnのある関数では、早期returnでもfclose
されるよう整理しましょう。
Cならgoto cleanup
やスコープ管理の工夫で漏れを防げます。
プロセスが異常終了すると削除が保証されない実装もあるため、クリティカルな用途では終了パスの堅牢化も重要です。
OS別の挙動とポータビリティ
Windows/Linux/macOSの違い
実装はOSと標準ライブラリに依存しますが、共通して「読み書き可能な一時ファイルを作り、クローズ時に削除」という契約は守られます。
- Linux(glibcなど): 無名化(リンク削除)や
O_TMPFILE
で、他プロセスから開けない挙動が一般的 - macOS: POSIX系挙動で、無名化する実装が主流
- Windows(MSVCランタイム): 一時ディレクトリに削除予約された一時ファイルを生成し、クローズ時に確実に削除
細部のアクセス権や共有モードは実装依存です。
特に高いセキュリティ要件がある場合は、対象プラットフォームのドキュメントを確認してください。
一時ディレクトリの場所
一時ファイルの置き場所は環境や実装により異なります。
代表的な既定値をまとめます。
OS | 主な一時ディレクトリの例 | 備考 |
---|---|---|
Linux | /tmp または TMPDIR環境変数 | 多くの実装でTMPDIRを優先 |
macOS | /var/folders/… のユーザ固有TMPDIR | システムがユニークなパスを割り当て |
Windows | %TEMP% または %TMP% | GetTempPathの結果が使われるのが一般的 |
配置先を自分で選べないのがtmpfile
の特徴です。
場所を明示したい場合は、別の安全なAPI(例えばPOSIXのmkstemp
やWindowsの専用API)の検討が必要です。
危険なtmpnam
の使用は推奨されません(詳細は別記事で解説します)。
他プロセスとの共有は基本不可
他プロセスとファイルを共有する用途には向きません。
- POSIX系ではファイル名が存在しない(無名)ため、パスで引き渡すことが不可能です。
- Windowsでは内部的な名前がある場合でも、削除予約や共有モードの制約により、実用的な共有は期待できないと考えるのが無難です。
プロセス間で共有したいなら、mkstemp
等で「自分で安全に一時ファイルを作る」手段を検討してください。
まとめ
tmpfile
は「安全で片付け不要」な一時ファイルを簡単に扱える、C言語の実用的な標準関数です。
ファイル名の競合や削除漏れを避けられ、特にPOSIX系では無名化により他プロセスからのアクセスを抑止できます。
使い方の要点は、戻り値のNULL
チェック、書き⇄読み切り替え時の位置操作(rewind
やfseek
)、そしてfclose
で確実に閉じることです。
OSごとの違いはあるものの、「実行中だけ安全に一時保管したい」というニーズには十分に応えてくれます。
センシティブなデータの短期保管や中間結果の退避など、場面に応じて賢く活用してください。