Подавить предупреждение: использование `mktemp'опасно

Как я могу подавить следующее предупреждение от компоновщика gcc:

предупреждение: использование 'mktemp' опасно, лучше используйте 'mkstemp'

Я знаю, что лучше использовать mkstemp() но по какой-то причине я должен использовать mktemp() функция.

6 ответов

Решение

Я думаю, что вам нужен путь, потому что вы передаете его в библиотеку, которая принимает только пути в качестве аргумента, а не файловые дескрипторы или FILE указатели. Если это так, вы можете создать временный каталог с помощью mkdtemp и поместите туда свой файл, тогда фактическое имя не имеет значения, потому что путь уже уникален из-за каталога.

Две вещи:

  • mktemp не является стандартной функцией
  • предупреждение является специальным, реализованным в компоновщике как .gnu.warning.mktemp раздел

Используйте родной OS API, если вам действительно нужно записать на диск. Или же mkstemp() как предложено.

Если вы должны использовать mktemp тогда нет ничего, что вы можете сделать, чтобы подавить это предупреждение, кроме удаления раздела, который использует mktemp из libc.so.6.

Почему вы должны использовать mktemp?

Использование mkstemp:

int fd = mkstemp(template);

После этого звонка template будет заменено фактическим именем файла. У вас будет дескриптор файла и путь к файлу.

Если вы статически связываете среду выполнения, тогда другой вариант - написать свою собственную версию mktemp в объектном файле. Компоновщик должен предпочесть вашу версию версии исполнения.

Изменить: Спасибо Джейсон Коко за указание на серьезное недоразумение, которое я имел в mktemp и его родственники. Это немного легче решить сейчас. Поскольку компоновщик предпочтет версию в объектном файле, вам просто нужно написать mktemp с точки зрения mkstemp,

Единственными трудностями являются очистка файловых дескрипторов, которые mkstemp вернусь к вам и сделаю все безопасным. Вы можете использовать статический массив дескрипторов и atexit-зарегистрированная функция для очистки, если вы можете поставить ограничение на сколько временных файлов вам нужно. Если нет, просто используйте связанный список.

часто используется неправильно, когда нужно создать временное имя без фактического создания файла tmp, напримерmkstempсделал бы. Возможно, вы хотите передать такое имяsem_openилиshm_open, и вы хорошо знаете о флаге O_EXCL. Существует много возможных вариантов использования, когда вы хотите создать какой-либо объект со случайным именем, и этот объект не является tmp-файлом.

Однако на самом деле его не следует использовать даже в этом случае. Это связано с тем, что он проверяет сгенерированное имя по существующему файлу, и если такой файл существует, он генерирует другое имя и так далее в цикле. Это действительно не то, что вам нужно, особенно если вы не собираетесь в конце создавать такой файл.

Поэтому было бы лучше просто написать свою собственную реализацию, ориентированную на ваши конкретные потребности, а не пытаться отключить предупреждение. Я просто извлек код генератора из исходников glibc и добавил%Pобработка модификатора, которая добавляет pid в шаблон:https://github.com/dosemu2/dosemu2/blob/devel/src/base/misc/utilities.c#L1103 . Вы можете использовать этот код в качестве примера или просто написать твой собственный.

Есть лишь основные правила осторожности при выполнении подобных трюков:

  • Добавьте pid к имени объекта в дополнение к случайным символам. Таким образом, вы избегаете возможности конфликта с другим экземпляром вашей собственной программы, имеющим ту же фиксированную часть шаблона.
  • Используйте O_EXCL при создании объекта, чтобы избежать любых возможных злонамеренных попыток заставить вашу программу открыть то, что она не должна открывать.
  • Если эксклюзивное создание не удалось с помощью EEXIST, объект может быть остановлен (у вас есть pid в имени, и вы знаете, что ваш pid еще не создал его), поэтому вы можете отменить связь с ним и повторить попытку эксклюзивного создания. Если создание снова завершится неудачно, возможно, происходит что-то вредоносное, поэтому вы можете просто выйти.
  • Отвязывайте объект как можно скорее, а не при выходе из программы. После открытия таких объектов (семафоров, разделяемой памяти и т.п.) отвязка не мешает использовать их через уже полученные fds. Если вы хотите разветвить дочерний процесс, использующий эти объекты, в большинстве случаев достаточно открыть их только в родителе и сразу же отключить связь. Ребенок может использовать их через унаследованные fds, а не открывать заново.

Я считаю, что приведенных выше рекомендаций достаточно для использования собственныхmktemp- Аналогичная функция безопасна и надежна. Но это всего лишь мое собственное мнение.

Другие вопросы по тегам