11

静的ソースコード分析に関する大規模なプロジェクトがあり、1つを除いて、すべてが正常にコンパイルされます。タイトルにエラーメッセージを記載しました。私を混乱させるポイントは、安全ではないというエラーメッセージが表示されることです。エラーではなく、単なる警告だと思いました。ちなみに、私はVisual Studio 2012を使用しています。これは、ctimeでエラーが発生するコードの一部です。誰かが私がこのエラーを克服するのを手伝ってくれるなら、私はうれしいです。

void CppCheckExecutor::reportProgress(const std::string &filename, const char stage[], const std::size_t value)
{
     (void)filename;

     if (!time1)
         return;

     // Report progress messages every 10 seconds
     const std::time_t time2 = std::time(NULL);
     if (time2 >= (time1 + 10)) {
         time1 = time2;

         // current time in the format "Www Mmm dd hh:mm:ss yyyy"
         const std::string str(std::ctime(&time2));

         // format a progress message
         std::ostringstream ostr;
         ostr << "progress: "
              << stage
              << ' ' << value << '%';
         if (_settings->_verbose)
             ostr << " time=" << str.substr(11, 8);

         // Report progress message
         reportOut(ostr.str());
     }
}
4

5 に答える 5

11

コードに安全上の問題がないことが確実な場合は、でこれを無効にできます#pragma warning(disable : 4996)

于 2012-11-25T12:21:23.680 に答える
11

ctimeの説明を見ると、次のことに気付くでしょう。

この関数は静的データへのポインタを返し、スレッドセーフではありません。さらに、gmtimeおよびlocaltimeと共有される可能性のある静的tmオブジェクトを変更します。POSIXはこの関数を廃止とマークし、代わりにstrftimeを推奨します。

文字列が25文字より長くなるtime_tの値については、動作が定義されていない可能性があります(例:10000年

...それは心配することがたくさんあります。

一方、strftimeを見ると:

size_t strftime(char * str、size_t count、const char * format、tm * time);

戻り値

strが指す文字配列に書き込まれたバイト数。成功時に終了する「\0」は含まれません。文字列全体を保存する前にカウントに達した場合、0が返され、内容は未定義です。

すべてのパラメーターは明示的であるため、可能なデータ競合を完全に制御でき、提供されたバッファーがオーバーフローするリスクもありません。

ただし、これはCウェイであり、C ++では<chrono>、特定の関数std::put_timeを使用してストリームに時間を出力することもできます。

#include <iostream>
#include <iomanip>
#include <ctime>
#include <chrono>

int main() {
    std::time_t const now_c = std::time();
    std::cout << "One day ago, the time was "
              << std::put_time(std::localtime(&now_c), "%F %T") << '\n';
}

これは、バッファオーバーフローの可能性について心配する必要がなくなるため、さらに優れています。

于 2012-11-25T14:36:39.137 に答える
5

はい、エラーではなく、単なる警告である必要があります。エラーの代わりに簡単な警告を受け取るには、VSプロジェクトでSDLチェックを無効にします([構成のプロパティ]-> [C / C ++]-> [全般]タブ)。

于 2013-08-01T08:51:11.317 に答える
4

std::ctime次の2つの理由により、スレッドセーフではありません。

  • std::tm複数の関数で共有されるタイプのグローバルオブジェクトを変更できます。
  • グローバルchar配列を変更し、その配列へのポインタを返します。

std::gmtime、、、std::localtimeまたはを呼び出す他のスレッドがある場合、衝突の可能性がありますstd::ctime

std::ctime最善の方法は、その呼び出しをへの呼び出しに変換することstd::strftimeです。これは、廃止されたと見なされ、代わりにctimeの使用を推奨するPOSIXと一致しています。strftime

于 2012-11-25T14:00:29.560 に答える
1

vs 2017:

#include "stdafx.h"


#include <iostream>
#include <iomanip>
#include <ctime>
#include <chrono>

int main() {
    std::time_t const now_c = std::time(NULL);
    auto s = std::put_time(std::localtime(&now_c), "%F %T");
    std::cout << s << std::endl;
}

しかし、とにかく受け取るでしょう:

.... cpp(31):警告C4996:'localtime':この関数または変数は安全でない可能性があります。代わりにlocaltime_sの使用を検討してください。非推奨を無効にするには、_CRT_SECURE_NO_WARNINGSを使用します。詳細については、オンラインヘルプを参照してください。

使用できないようにするには:

errno_t err;
struct tm time_info;
time_t time_create = time(NULL);
localtime_s(&time_info, &time_create);
char timebuf[26];
err = asctime_s(timebuf, 26, &time_info);

プレーンCはMSDNから部分的に取得されました...古い方法です。

于 2017-08-04T11:33:01.203 に答える