2010-04-04 2 views
19

Я использую fopen в C для записи вывода в текстовый файл. Функция декларации (где ARRAY_SIZE было определено ранее):fopen/fopen_s и запись в файлы

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_s. Я не вижу много информации о fopen_s, чтобы изменить свой код. Какие-либо предложения?

  2. Можно ли указать fprintf для ввода чисел с требуемой числовой точностью в файл? Если я использую long double, то я предполагаю, что мои ответы хороши до 15 цифр после десятичной точки. Я прав?

+16

В fopen() нет ничего опасного, но некоторые люди в MS, похоже, потеряли коллективные мраморные функции над функциями, которые принимают строки с нулевым символом в качестве параметров. – 2010-04-04 17:04:02

+0

Я считаю, что это все заговор Microsoft, чтобы заблокировать людей в программировании только для Windows. – stackptr

ответ

16

fopen_s представляет собой вариант fopen, который содержит проверку параметров и руки код ошибки, а не указатель на случай, если что-то пойдет не так во время открытого процесса. Он более безопасен, чем базовый вариант, потому что он учитывает больше краевых условий. Компилятор предупреждает вас использовать его, потому что fopen представляет потенциальный вектор разработки в вашем приложении.

Вы можете указать цифры точности к printf семейства функций, используя спецификатор %.xg, где х это цифры точности, которые вы хотите на выходе. A long double отличается точностью от платформы к платформе, но обычно вы можете сделать ставку на то, что она составляет не менее 16 цифр десятичной точности.

Edit: В то время как я не совсем на борту с другими людьми, предполагающими, что fopen_s является полной тратой времени, она представляет собой довольно низкий шанс эксплуатации и не имеет широкую поддержку. Однако некоторые из других функций, о которых предупреждают о C4996, являются гораздо более серьезными уязвимостями, однако использование _CRT_SECURE_NO_WARNINGS эквивалентно отключению сигнала тревоги как «вы оставили дверь вашей спальни разблокированным», так и «вы оставили ядерную бомбу на кухне».

Пока вы не ограничены использованием «чистого C» для вашего проекта (например,для школьного задания или встроенного микроконтроллера), вам следовало бы воспользоваться тем фактом, что почти все современные компиляторы C также являются компиляторами C++ и используют варианты C++ iostream всех этих функций ввода-вывода, чтобы получить как улучшенную безопасность и совместимость в то же время.

+0

Спасибо. У меня есть fprintf (out, "% .16Le \ n", z1 [i]) в моем коде и да, я получаю 16 цифр точности после d.p. – yCalleecharan

+0

Еще раз спасибо. Я использую C, потому что это то, что я знаю лучше. Я пишу код для исследовательских целей, который должен дать точный результат. Я должен был безразмерять мои уравнения, формирующие код С, чтобы иметь хороший диапазон значений, которые предотвратили бы слишком большие значения или слишком низкие значения, чтобы ползать в симуляцию и, следовательно, в решении. Я мало знаю о C++, и я не знаю, могу ли я просто сохранить свой файл в cpp и безопасно использовать C++ iostream без других частей моего кода, что дало мне ошибки компиляции. На данный момент я ограничусь до C до тех пор, пока не узнаю, как сделать переход на C++. – yCalleecharan

1

Просто определить _CRT_SECURE_NO_WARNINGS, прежде чем включить любой файл, чтобы избавиться от этого предупреждения, и остановить поверить, что MS говорит о fopen

+0

Спасибо. Это просто добавить #define _CRT_SECURE_NO_WARNINGS вверху? – yCalleecharan

6
  1. fopen_s и все остальные _s функции MS-специфические " безопасных "вариантов стандартных функций. Если ваш код не должен быть кросс-платформенным, вы можете просто переключиться и сделать компилятор счастливым. В противном случае просто добавьте предпроцессорную директиву _CRT_SECURE_NO_WARNINGS в свои настройки проекта, и она перестанет предупреждать вас об этом.

  2. Да, длинный двойной легко подходит для 15 цифр точности; на самом деле даже регулярные двойники достаточно хороши для этого (но не более).

+0

Спасибо. На моей 32-битной машине двойной и длинный двойной дает мне 16 цифр точности, а 16-я цифра не является точной. – yCalleecharan

+0

Да, размер 'long double' зависит от платформы; К сожалению, MSVC++ делает его таким же, как «double», поэтому его не используют. 64-битный double имеет 53-битную точность в мантиссе, которая составляет около 15,95 десятичных цифр (log10 (53)). – tzaman

+0

Спасибо за информацию. – yCalleecharan

4

Другие плакаты указали, что fopen на самом деле не очень опасен. Если вы не хотите этого предупреждения, но вы хотите, чтобы другие, предупреждающие о реальных уязвимостях, не указали #define _CRT_SECURE_NO_WARNINGS.

Вместо этого, в следующий раз, когда вы получите предупреждение fopen, щелкните по строке, которая гласит: «см. Объявление« fopen »». Это приведет вас к строке в stdio.h, которая вводит предупреждение. Удалите текст _CRT_INSECURE_DEPRECATE(fopen_s) из этой строки, и вы больше не получите предупреждение о безопасности при использовании fopen, но оно останется для strcpy, strdup и других опасных.

+1

Фактически на окнах «стандартная» реализация open имеет некоторые уязвимости из-за 14, 125, 16-летних братов, которые не имеют ничего общего с их временем, чем найти способы взломать программы и испортить компьютеры других людей, поэтому они придумал другой способ передать файловый дескриптор, затрудняющий для подростков – BrierMay

8

Я столкнулся с аналогичной проблемой, связанной с Visual Studio 2012, но там, где моя проблема была расширена, я создавал программу, в которой я хочу использовать колокола и свистки Visual Studio для тестирования и, в конечном итоге, смогу скомпилировать и запустить такое же приложение на моем Linux-сервере (я делаю бота)

так вот, что я придумал после некоторых Google-событий, и подумал, что отправлю его на случай, если это может помочь кому-то еще.

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); 
    } 

это успокоит Visual Studio, и он не будет жаловаться, и это также позволит тот же код для компиляции на GCC или любые другие стандарты совместимые C/C++ компилятор

4

Переход от Еореп к fopen_s отключена возможность открыть файл в блокноте (только чтение), пока файл открыт и записывается. Возвращаясь к fopen, и я могу прочитать wile, моя программа записывает файл.

+0

Из [ссылки] (http://en.cppreference.com/w/c/io/fopen): при использовании fopen_s или freopen_s, файл разрешения доступа для любого файла, созданного с помощью «w» или «a», запрещают другим пользователям доступ к нему.Флаг режима доступа к файлам «u» необязательно может быть добавлен к любому спецификатору, который начинается с «w» или «a», чтобы разрешить разрешения fopen по умолчанию. (С11) –