23

Cでfopenを使用して、出力をテキストファイルに書き込みます。関数宣言は次のとおりです(ARRAY_SIZE以前に定義されている場合):

void create_out_file(char file_name[],long double *z1){  
  FILE *out;  
  int i;  

  if((out = fopen(file_name, "w+")) == NULL){  
    fprintf(stderr, "***> Open error on output file %s", file_name);  
    exit(-1);  
  }  

  for(i = 0; i < ARRAY_SIZE; i++)  
    fprintf(out, "%.16Le\n", z1[i]);  
  fclose(out);  
}  

私の質問:

  1. MVS2008でコンパイルすると、警告が表示されます。警告C4996:'fopen':この関数または変数は安全でない可能性があります。代わりにfopen_sの使用を検討してください。fopen_sコードを変更できるように、情報があまり表示されていません。助言がありますか?

  2. fprintf希望する数値精度でファイルに数値を書き込むように指示できますか?私が使用している場合long double、私の答えは小数点以下15桁までは良いと思います。私は正しいですか?

4

6 に答える 6

21

fopen_sfopenは、パラメータ検証を含み、オープンプロセス中に問題が発生した場合に備えて、ポインタの代わりにエラーコードを返すバリアントです。より多くのエッジ条件を考慮するため、ベースバリアントよりも安全です。コンパイラはfopen、アプリケーションでの潜在的な悪用ベクトルを表すため、これを使用するように警告しています。

printf指定子を使用して、関数ファミリーに精度の桁を指定できます%.xg。ここで、xは出力に必要な精度の桁です。Aのlong double精度はプラットフォームごとに異なりますが、通常、少なくとも16桁の10進数の精度であることに賭けることができます。

編集:私はそれfopen_s完全に時間の無駄であると示唆している他の人たちと完全に協力しているわけではありませんが、それは悪用される可能性がかなり低く、広くサポートされていません。C4996で警告されている他の機能のいくつかは、はるかに深刻な脆弱性です。ただし、使用する_CRT_SECURE_NO_WARNINGSことは、「寝室のドアのロックを解除したまま」と「キッチンに核爆弾を残した」の両方のアラームをオフにすることと同じです。

プロジェクトに「純粋なC」を使用することに制限されていない限り(たとえば、学校の課題や組み込みマイクロコントローラーなど)、ほとんどすべての最新のCコンパイラーもC ++コンパイラーであり、セキュリティ互換性の両方を同時に向上させるための、これらすべてのI/O関数のC++iostreamバリアント。

于 2010-04-04T17:09:32.300 に答える
11

Visual Studio 2012で同様の問題が発生しましたが、問題が拡大したのは、Visual Studioのベルとホイッスルをテストに使用し、最終的に同じアプリケーションをコンパイルして実行できるようにするプログラムを構築していることでした。 Linuxサーバー(ボットを作成しています)

だからこれは私がグーグルをした後に思いついたもので、他の誰かに役立つかもしれない場合に備えて投稿したいと思いました。

FILE *fp_config;
const char *configfile ;
configfile = "bot.conf";
#ifdef WIN32
    errno_t err;
    if( (err  = fopen_s( &fp_config, configfile, "r" )) !=0 ) {
#else
    if ((fp_config = fopen(configfile, "r")) == NULL) {
#endif
        fprintf(stderr, "Cannot open config file %s!\n", configfile);
    }

これはVisualStudioをなだめ、文句を言わず、同じコードをgccまたは他の標準に準拠したc /c++コンパイラでコンパイルすることもできます。

于 2013-02-19T20:21:09.090 に答える
8
  1. fopen_s他のすべての_s関数は、標準関数のMS固有の「安全な」バリアントです。コードをクロスプラットフォームにする必要がない場合は、切り替えてコンパイラーを満足させることができます。_CRT_SECURE_NO_WARNINGSそれ以外の場合は、プリプロセッサディレクティブをプロジェクト設定に追加するだけで、警告が停止します。

  2. ええ、longdoubleは15桁の精度に簡単に適しています。実際には、通常のダブルスでさえ、それだけで十分です(しかしそれ以上はありません)。

于 2010-04-04T17:06:30.447 に答える
5

fopenからfopen_sに移動すると、ファイルを開いて書き込んでいるときにメモ帳(読み取り専用)でファイルを開く機能が無効になります。fopenに戻ると、プログラムがファイルを書き込んでいる間、読み取ることができます。

于 2013-10-27T13:15:52.690 に答える
4

他のポスターは、fopenはそれほど安全ではないと指摘しています。この警告は必要ないが、実際の脆弱性を警告する他の警告は必要な場合は、しないでください #define _CRT_SECURE_NO_WARNINGS

代わりに、次にfopen警告が表示されたときに、「'fopen'の宣言を参照してください」という行をクリックします。これにより、警告を挿入しているstdio.hの行に移動します。その行からテキストを削除する_CRT_INSECURE_DEPRECATE(fopen_s)と、fopenを使用したときにセキュリティ警告が表示されなくなりますが、strcpy、strdup、およびその他の危険な可能性のあるものには残ります。

于 2011-04-15T14:24:40.500 に答える
0

_CRT_SECURE_NO_WARNINGSこの警告を取り除くためにファイルを含める前に定義し、MSの言うことを信じないでくださいfopen

于 2010-04-04T17:03:08.457 に答える