24

いわゆる安全なライブラリの deprecations について尋ねた以前の質問の型では、なぜfopen()deprecated にする必要があるのか​​ について同様に困惑しています。

この関数は 2 つの C 文字列を取り、FILE* ptr を返すか、失敗すると NULL を返します。スレッドセーフの問題/文字列オーバーランの問題はどこにありますか? それとも別のものですか?

前もって感謝します

4

6 に答える 6

46

使用できますfopen()。まじめな話、ここで Microsoft に注意しないでください。Microsoft は、ISO 標準から逸脱することで、プログラマーに真の不利益をもたらしています。彼らは、コードを書いている人はどういうわけか頭が死んでいて、ライブラリ関数を呼び出す前にパラメーターをチェックする方法を知らないと考えているようです.

C プログラミングの複雑さを学ぼうとしない人は、実際にそれを行う必要はありません。彼らはより安全な言語に移行する必要があります。

これは、Microsoft による開発者のベンダー ロックインのもう 1 つの試みのようです (ただし、それを試みているのは彼らだけではないので、特に彼らを非難しているわけではありません)。私は通常追加します:

#define _CRT_SECURE_NO_WARNINGS

(または"-D"コマンドラインのバリアント)をほとんどのプロジェクトに追加して、完全に有効で合法的なCコードを作成するときにコンパイラーに煩わされないようにします。

Microsoft は、関数に追加機能fopen_s()(ファイル エンコーディングなど) を提供し、返される方法を変更しました。これにより、Windows プログラマーにとっては改善されるかもしれませんが、コードは本質的に移植できなくなります。

Windows 用のコードだけを作成する場合は、ぜひ使用してください。私自身は、自分のコードをどこでもコンパイルして実行できることを好みます (できるだけ変更を加えずに)。


C11 の時点で、これらのセーフ関数は標準の一部になりましたが、オプションです。詳細については、附属書 K を参照してください。

于 2009-05-25T13:06:10.040 に答える
20

公式のISO/IEC JTC1 / SC22 / WG14(C言語)テクニカルレポートTR24731-1(境界チェックインターフェイス)とその理論的根拠は次の場所で入手できます。

TR24731-2(動的割り当て機能)に向けた作業もあります。

述べられている理論的根拠fopen_s()は次のとおりです。

6.5.2ファイルアクセス機能

ファイルを作成するとき、fopen_sandfreopen_s関数は、ファイル保護を設定し、排他的アクセスでファイルを開くことにより、不正アクセスからファイルを保護することにより、セキュリティを向上させます。

仕様によると:

6.5.2.1fopen_s関数

あらすじ

#define __STDC_WANT_LIB_EXT1__ 1
#include <stdio.h>
errno_t fopen_s(FILE * restrict * restrict streamptr,
                const char * restrict filename,
                const char * restrict mode);

実行時の制約

、、、またはstreamptrのいずれもnullポインタにはなりません。filenamemode

実行時制約違反がある場合はfopen_s、ファイルを開こうとしないでください。さらに、streamptrがnullポインタでない場合は、nullポインタにfopen_s設定*streamptrします。

説明

このfopen_s関数は、が指す文字列を名前とするファイルを開き、 filenameストリームを関連付けます。

モード文字列は、の説明どおりである必要がfopenあります。さらに、文字「w」または「a」で始まるモードの前に文字「u」を付けることができます。以下を参照してください。

  • uw長さをゼロに切り捨てるか、書き込み用のテキストファイルを作成します。デフォルトの権限
  • ua追加; ファイルの終わりに書き込むためのテキストファイルを開くか作成します。デフォルトの権限
  • uwb長さをゼロに切り捨てるか、書き込み用のバイナリファイルを作成します。デフォルトの権限
  • uab追加; ファイルの終わりに書き込むためのバイナリファイルを開くか作成します。デフォルトの権限
  • uw+長さをゼロに切り捨てるか、更新用のテキストファイルを作成します。デフォルトの権限
  • ua+追加; 更新用のテキストファイルを開くか作成し、ファイルの終わりに書き込み、デフォルトの権限
  • uw+bまたはuwb+長さをゼロに切り捨てるか、更新用のバイナリファイルを作成します。デフォルトの権限
  • ua+bまたはuab+追加; 更新用のバイナリファイルを開くか作成し、ファイルの終わりに書き込み、デフォルトの権限

基盤となるシステムが概念をサポートしている限り、書き込み用に開かれたファイルは、排他的(非共有とも呼ばれる)アクセスで開かれるものとします。ファイルが作成されていて、モード文字列の最初の文字が「u」でない場合、基盤となるシステムがサポートしている範囲で、ファイルには、システム上の他のユーザーがファイルにアクセスできないようにするファイル権限が必要です。ファイルが作成されていて、モード文字列の最初の文字が「u」の場合、ファイルが閉じられるまでに、システムのデフォルトのファイルアクセス許可が付与されます10)

ファイルが正常に開かれた場合、が指すポインタFILEstreamptr 、開かれたファイルを制御するオブジェクトへのポインタに設定されます。それ以外の場合、が指すポインタはnullポインタに設定されますFILEstreamptr

戻り値

fopen_sファイルを開いた場合、関数はゼロを返します。ファイルを開かなかった場合、または実行時制約違反があった場合は、fopen_sゼロ以外の値を返します。

10)これらは、ファイルがfopenによって作成された場合と同じ権限です。

于 2009-05-25T17:54:42.193 に答える
8

このfopen_s()関数は Microsoft によって C ランタイムに追加されましたが、次の基本的な違いがありますfopen()

  • ファイルが書き込み用に開かれている場合 (モードで "w" または "a" が指定されている)、ファイルは排他的 (非共有) アクセス用に開かれます (プラットフォームがサポートしている場合)。
  • モード引数で「u」指定子が「w」または「a」指定子とともに使用されている場合、ファイルが閉じられるまでに、他のユーザーがファイルにアクセスするためのシステムの既定のアクセス許可が設定されます (アクセス権がない場合があります)。システムのデフォルトの場合はアクセスできません)。
  • これらの場合に指定された「u」が使用されない場合、ファイルが閉じられるとき (またはその前) に、他のユーザーがファイルにアクセスできないように、ファイルのアクセス許可が設定されます。

基本的に、アプリケーションが書き込むファイルはデフォルトで他のユーザーから保護されていることを意味します。

fopen()既存のコードが壊れる可能性があるため、彼らはこれをしませんでした。

Microsoft はfopen()、Windows の開発者に、アプリケーションが使用するファイルのアクセス許可が緩くなるかどうかについて意識的な決定を下すことを奨励するために、非推奨にすることを選択しました。

Jonathan Leffler の回答は、提案された標準化言語を提供しますfopen_s()。根拠を明確にするために、この回答を追加しました。

于 2009-07-09T23:50:25.937 に答える
2

それとも別のものですか?

「fopen」で使用される FILE 構造の一部の実装では、「unsigned short」として定義されたファイル記述子があります。これにより、stdin、stdout、および stderr を除いて、最大 255 の同時オープン ファイルが残ります。

もちろん、255 個のオープン ファイルを持つことができることの価値については議論の余地がありますが、この実装の詳細は、Solaris 8 プラットフォームで252個を超えるソケット接続がある場合に具体化されます。私のアプリケーションで libcurl を使用して SSL 接続を確立する際にランダムに失敗したように最初に見えたのは、これが原因であることが判明しました。

'fopen' のすべてが悪いわけではありませんが、古いインターフェイスの束縛を捨てることの美徳を見ることができます。非推奨の選択は、時代遅れの実装とのバイナリ互換性を維持するという苦痛に基づいている可能性があります。

于 2009-05-25T16:25:17.833 に答える
1

スレッドセーフ。fopen()はグローバル変数 を使用しますがerrnofopen_s()置換は を返し、ファイル ポインタを格納errno_tする引数を取ります。FILE**

于 2009-05-25T12:56:30.527 に答える
1

新しいバージョンはパラメーターの検証を行いますが、古いバージョンはそうではありませんでした。

詳細については、この SO スレッドを参照してください。

于 2009-05-25T12:52:57.400 に答える