If you look at the description of ctime you will note:
This function returns a pointer to static data and is not thread-safe. In addition, it modifies the static tm object which may be shared with gmtime and localtime. POSIX marks this function obsolete and recommends strftime instead.
The behavior may be undefined for the values of time_t that result in the string longer than 25 characters (e.g. year 10000)
… that’s a lot of things to worry about.
On the other hand, if you look at strftime:
size_t strftime( char* str, size_t count, const char* format, tm* time );
Return value
number of bytes written into the character array pointed to by str not including the terminating ‘\0’ on success. If count was reached before the entire string could be stored, 0 is returned and the contents are undefined.
All the parameters are explicit, so that you fully control the possible data races, and there is no risk of overflowing the buffer provided as well.
This is the C-way though, and C++ introduces the <chrono>
in which a specific function std::put_time
can also be used to output time to a stream:
#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';
}
which is even better since you no longer have to worry about the possible buffer overflow.
If you look at the description of ctime you will note:
This function returns a pointer to static data and is not thread-safe. In addition, it modifies the static tm object which may be shared with gmtime and localtime. POSIX marks this function obsolete and recommends strftime instead.
The behavior may be undefined for the values of time_t that result in the string longer than 25 characters (e.g. year 10000)
… that’s a lot of things to worry about.
On the other hand, if you look at strftime:
size_t strftime( char* str, size_t count, const char* format, tm* time );
Return value
number of bytes written into the character array pointed to by str not including the terminating ‘\0’ on success. If count was reached before the entire string could be stored, 0 is returned and the contents are undefined.
All the parameters are explicit, so that you fully control the possible data races, and there is no risk of overflowing the buffer provided as well.
This is the C-way though, and C++ introduces the <chrono>
in which a specific function std::put_time
can also be used to output time to a stream:
#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';
}
which is even better since you no longer have to worry about the possible buffer overflow.
У меня большой проект по статическому анализу исходного кода, и все успешно компилируется, кроме одного. Я предоставил сообщение об ошибке в заголовке. Меня смущает то, что выдает сообщение об ошибке «небезопасно». Я думал, что это должно быть просто предупреждение, а не ошибка. Кстати, я использую 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());
}
}
5
Решение
Если вы посмотрите на описание CTime вы заметите:
Эта функция возвращает указатель на статические данные и не является потокобезопасным. Кроме того, он изменяет статический тм объект которым можно поделиться с gmtime и localtime. POSIX помечает эту функцию как устаревшую и рекомендует вместо нее strftime.
поведение может быть неопределенным для значений time_t, результатом которых является строка длиной более 25 символов (например, год 10000)
… это много вещей для беспокойства.
С другой стороны, если вы посмотрите на STRFTIME:
size_t strftime (char * str, size_t count, const char * format, tm * time);
Возвращаемое значение
количество байтов, записанных в массив символов, на которые указывает str, не включая завершающий ‘\ 0’ в случае успеха. Если число было достигнуто до того, как вся строка может быть сохранена, возвращается 0 и содержимое не определено.
Все параметры являются явными, так что вы полностью контролируете возможные гонки данных, и также нет риска переполнения предоставленного буфера.
Это C-way, а 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';
}
что даже лучше, так как вам больше не нужно беспокоиться о возможном переполнении буфера.
5
Другие решения
Если вы уверены, что в вашем коде нет проблем с безопасностью, вы можете отключить #pragma warning(disable : 4996)
,
5
Да, это должно быть просто предупреждение, а не ошибка.
Чтобы получить простое предупреждение вместо ошибки, отключите проверку SDL в проекте VS (в Свойствах конфигурации -> C / C ++ -> вкладка Общие).
5
std::ctime
не является потокобезопасным по двум причинам:
- Это может изменить глобальный объект типа
std::tm
это разделяется несколькими функциями. - Это изменяет глобальный
char
массив и возвращает указатель на этот массив.
Существует вероятность столкновения, если у вас есть другие потоки, которые вызывают std::gmtime
, std::localtime
, или же std::ctime
,
Лучше всего преобразовать этот вызов в std::ctime
на звонок в std::strftime
, Это согласуется с POSIX, который считает ctime
устареть и рекомендует использовать strftime
вместо него.
2
против 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_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 … по-старому ..
0
Whenever I call ctime, I get the following error
|
|
.
I looked around the web and found the chrono library, problem with the following library is, (well at least with the tutorials that I found), it still uses ctime to get the current calender date.
Does anyone know of an alternative to the ctime library that I can use to get the current calender date and time.
I use Visual Studio 2012, in case anybody needs the info. Below is the code that I used to get the error.
|
|
TDM-GCC 4.9.2 doesn’t have a problem with ctime()
.
Alternatives:
http://www.cplusplus.com/reference/ctime/asctime/
http://www.cplusplus.com/reference/ctime/strftime/
Why don’t you disable deprecation like the bogus error message mentions?
@FurryGuy, thanks for the links. I still get the same error though from the tutorial from the links for using the localtime.
@jlb, Because it says its unsafe…
I don’t know what behavior will result if I disable the message and use it anyway. Unless you know something I don’t?
Why is it bogus?
Last edited on
@Student555, it could be directly related to using VS. MS had a habit of not completely following earlier C/C++ standards, looks like they are doing it still.
I don’t use VS, even the «free» editions.
@FurryGuy, is ctime still part of the C++ standard or has it been deprecated like the VS message claims. Because I’m getting the feeling it is only the VS compiler that won’t accept its use? Other compilers accept it.
jlb claimed the message was bogus, does that mean the error has no merit?
What would the consequence be if I completely ignored the message and disabled it.
> is ctime still part of the C++ standard or has it been deprecated like the VS message claims.
std::ctime()
is part of standard C++.
You may safely ignore the warning: ‘ctime’: This function or variable may be unsafe. Consider using ctime_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS.
Build with _CRT_SECURE_NO_WARNINGS defined and these irritating warnings will go away.
|
|
> MS had a habit of not completely following earlier C/C++ standards
This is palpably untrue. MS has a habit of not following later/current C standards. They strive very hard to conform to the C++ standard.
http://www.cplusplus.com/forum/general/145334/#msg765455
Visual Studio 2015 is an excellent C++ implementation; but it is a poor C implementation.
Our immediate and long-term goal is to fully support the C subsets of ISO C++.
If you really need either of the following:
features in C95/C99/C11 that are not part of ISO C++; or
features in C that are in the C++ subset but without also enabling the writing of C++ code;
then we recommend that you consider using a different compiler
Many old functions are deprecated by Microsoft, and often rightly so.
The
ctime()
function is not reentrant, which is why MS created a version that is.
Well, I was going to suggest you use the put_time manipulator, which is really just a wrapper for strftime(), but neither seem to work in GCC. (Madness!)
I don’t know what else to suggest ATM, besides doing it yourself.
Thanks JLborges.
Is there a difference between adding to the cpp file as
|
|
or placing it in
Project -> Properties -> C/C++ -> Preprocessor -> Preprocessor Definitions
@Duoas, are you aware of any consequences that occur if ctime is used in VS 2012? Despite the warning.
Last edited on
> neither seem to work in GCC. (Madness!)
Most (if not all) of the C++11 format specifiers don’t work in any of the MinGW or CygWin builds of libstdc++.
The pre-C++11 format specifiers do appear to work as expected with MinGW, GCC 5.1.
Most (may be all) of the C++11 format specifiers do work with libstdc++, GCC 5.1 on other platforms,
and with the Microsoft library on Windows.
|
|
http://coliru.stacked-crooked.com/a/3b580777af5b2155
Last edited on
> Is there a difference between adding to the cpp file as #define _CRT_SECURE_NO_WARNINGS
> or placing it in Project -> Properties -> C/C++ -> Preprocessor -> Preprocessor Definitions
Placing a
#define _CRT_SECURE_NO_WARNINGS
before any other
#include
directives in the cpp file affects only that one translation unit. (Assuming that pre-compiled headers are not being used).
Placing it in
Project -> Properties -> C/C++ -> Preprocessor -> Preprocessor Definitions
would make
_CRT_SECURE_NO_WARNINGS
effective for every translation unit (even if pre-compiled headers are used.)
This is the recommended procedure.
> any consequences that occur if ctime is used in VS 2012? Despite the warning.
The behavior may be undefined for the values of time_t that result in the string longer than 25 characters (e.g. year 10000) http://en.cppreference.com/w/cpp/chrono/c/ctime
http://en.cppreference.com/w/cpp/chrono/c/strftime
The Microsoft warning would have been considered reasonable, had they recommended using another standard C++ function, instead of peddling the non-standard alternative
ctime_s().
strftime() is as broken as put_time() — the latter is a manipulator version of the former.
And, AFAICK, there aren’t any complete implementations of the standard.
I’m not a fan of Microsoft’s playing their own C standards, but they were right.
ctime_s()
is superior to
ctime()
for the simple fact that it is reentrant. The C11 version muddles it some, but if used properly, is also reentrant. And since it is C11, everyone should have it.
Meaning there is no good reason not to use it.
strftime() is as broken as put_time()
strftime works on MinGW GCC 4.9 if you will stay away from format specificators added in C++11
Following should work:
|
|
"%F %T"
does not.
And since it is C11, everyone should have it.
Only if the compiler vendors support this optional feature. Can you tell me of a C11 standard compliant compiler that supports these optional constructs?
But since we’re talking about C++ are those optional C11 features even part of the C++ standard? I don’t see them in the table of Standard C functions included in the C++ standard (table 153 in annex C).
> are those optional C11 features even part of the C++ standard?
> I don’t see them in the table of Standard C functions included in the C++ standard (table 153 in annex C).
ctime_s()
is not standard C++. It is also not there in the current working draft for C++17.
1.2 Normative references makes it clear that the C part of the C++ standard is based on (a subset of) C99 (plus Technical Corrigenda for C99, the last of which was in 2007).
ctime_s()
is not even required to be there in a fully conforming C11 implementation.
Thank you for the confirmation.
The fact that these functions are optional in C11, non-existant in C++ (any version) is one of the reasons why I consider the warning/error message being generated by the Microsoft compiler to be bogus. These non-safe functions, with the exception of gets(), are not depreciated in any version of the C or C++ standards.
|
|
Thu Aug 06 15:02:02 2015 |
Tested with
— GCC 5.1.0
— Microsoft C/C++ 2012
ISO/IEC 9899:2011 K.2/1 states:
This annex specifies a series of optional extensions that can be useful in the mitigation of security vulnerabilities in programs, and comprise new functions, macros, and types declared or defined in existing standard headers.
ISO/IEC 9899:2011 K.3.8.2.2/1 states:
|
|
Optional or not, the two major players have it. There is no excuse.
|
|
C++ (g++), strict C++ conformance
g++ --version | grep GCC && g++ -std=c++14 -O3 -Wall -Wextra -pedantic-errors -c main.cpp g++ (GCC) 5.2.0 main.cpp: In function 'int main()': main.cpp:12:28: error: 'ctime_s' was not declared in this scope e = ctime_s( s, 50, &t ); // *** error: 'ctime_s' was not declared in this scope
http://coliru.stacked-crooked.com/a/04d36baddc3446be
C++ (g++), GNU dialect of C++14, no strict C++ conformance
g++ --version | grep GCC && g++ -std=gnu++14 -Wall -Wextra -c main.cpp g++ (GCC) 5.2.0 main.cpp: In function 'int main()': main.cpp:12:28: error: 'ctime_s' was not declared in this scope e = ctime_s( s, 50, &t ); // *** error: 'ctime_s' was not declared in this scope
http://coliru.stacked-crooked.com/a/4fa620aba6532043
C++ (g++), GNU default, no strict C++ conformance
g++ --version | grep GCC && g++ -O3 -Wall -Wextra -c main.cpp g++ (GCC) 5.2.0 main.cpp: In function 'int main()': main.cpp:12:28: error: 'ctime_s' was not declared in this scope e = ctime_s( s, 50, &t ); // *** error: 'ctime_s' was not declared in this scope
http://coliru.stacked-crooked.com/a/085f7aff559ad4b9
GCC 5.1 (g++) issues the same errors
http://coliru.stacked-crooked.com/a/fce8993f6cffd3ca
http://coliru.stacked-crooked.com/a/27bf6b53d6385f00
http://coliru.stacked-crooked.com/a/a0ca709586b57318
C (gcc) std=c11
|
|
gcc --version | grep GCC && gcc -std=c11 -O3 -Wall -Wextra -x c main.cpp && ./a.out gcc (GCC) 5.2.0 main.cpp: In function 'main': main.cpp:12:9: warning: implicit declaration of function 'ctime_s' [-Wimplicit-function-declaration] e = ctime_s( s, 50, &t ); // ^ /tmp/ccqJAS5o.o: In function `main': main.cpp:(.text.startup+0x22): undefined reference to `ctime_s' collect2: error: ld returned 1 exit status
http://coliru.stacked-crooked.com/a/5dfead606590baeb
There is no excuse for using
::ctime_s()
in C++;
when std::strftime() with a format specifier of
«%c»
is part of standard C++ (and it is available everywhere.)
I yield.
[I was wrong.]
Topic archived. No new replies allowed.
Please Sign up or sign in
to vote.
1.00/5 (2 votes)
See more:
C++
errors
OOP
code give following error.
Error C4996 ‘ctime’: This function or variable may be unsafe. Consider using ctime_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
What I have tried:
Code:
NOTE: it is not warning it is error
#include<iostream> #include<ctime> using namespace std; int main() { time_t now = time(0); char *time = ctime(&now); cout << "Time of System is: " << time << endl; system("pause"); return 0; }
Posted
Member 13817351
Updated 13-May-18 21:43pm
Add a Solution