Политики компилятора по уничтожению временных файлов

#c #visual-studio-2008 #compiler-construction #intel

#c #visual-studio-2008 #компилятор-конструирование #intel

Вопрос:

Я играл со следующим фрагментом кода. file_string возвращает временную строку, которая должна «жить» только до конца инструкции. В Visual Studio 2008, когда вы используете pTempFolder , он содержит мусор, как и ожидалось. Однако в Linux, с компилятором Intel 11.0, pTempFolder все еще указывает на допустимую строку. Есть ли у компиляторов разные политики в отношении уничтожения временных файлов, своего рода нетерпеливый (Visual) или ленивый (Intel)? Или, может быть, это просто совпадение?

 boost::filesystem wpathTempFolder("/tmp");
const wchar_t* const pTempFolder = wpathTempFolder.file_string().c_str();
// use pTempFolder
  

Кстати, это файловая система boost версии 2. Я также видел, что file_string это не рекомендуется в файловой системе boost версии 3. И что существует новый c_str метод, который работает над строкойamp; , а не над временной строкой.

 /*filesystem 2*/
const string_type file_string() const;
/*filesystem 3*/
const string_typeamp;  native() const;  // native format, encoding
const value_type*   c_str() const;   // native().c_str()
  

Ответ №1:

Вероятно, строка по-прежнему недопустима, просто так получилось, что этот раздел памяти еще не был выделен на уровне операционной системы, и это «случается», чтобы работать. Эта программа демонстрирует неопределенное поведение, которое всегда включает в себя «может продолжать работать, как будто ничего не пошло не так». Visual Studio здесь абсолютно корректен, чтобы привести к сбою вашу программу или практически все, что угодно.

Комментарии:

1. Просто мелочь, но она должна быть «освобождена или перезаписана». Доступ к данным после окончания срока их службы не определен, поэтому может случиться все, что угодно.

2. @James: Если бы это не было перезаписано, он бы не получил мусор, он получил бы совершенно хорошую строку.

3. Если память действительно возвращена операционной системе, он может получить сбой при попытке получить к ней доступ. (На самом деле это не сбой, но Purify или Valgrind также будут жаловаться. Даже если прочитанные данные кажутся правильными.)

4. @James, возможен фактический сбой, если страница, на которой находится память, фактически освобождена операционной системой. Тогда даже чтение приведет к недопустимому доступу (ошибка segfault в Linux). Хотя я думаю, что обычная память кучи в Linux на самом деле никогда не возвращается ядру, но в Windows я думаю, что malloc выделяет на основе страниц, поэтому более вероятно, что в Windows произойдет сбой.

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

Ответ №2:

Время жизни временного файла (за несколькими исключениями) длится до конца полного выражения. Время жизни объекта array, на которое указывает возвращаемое значение std::string::c_str() , не превышает время жизни самого объекта string (и может быть короче, если для строки вызываются какие-либо неконстантные функции). Обращение к объекту после окончания срока его службы является неопределенным поведением, поэтому вы не можете делать какие-либо выводы из того, что делает компилятор.

Комментарии:

1. теперь любопытно узнать о «нескольких исключениях».

2. @rturrando Есть несколько «синглтонов», роль которых включает очистку — Я использую синглтон, который управляет временными файлами, например, удаляя их (или нет) в конце программы. Такой синглтон нельзя использовать в деструкторах (поскольку тогда они могут не существовать), но он также полезен (и если вам нужно создать временный файл в деструкторе, вы делаете слишком много в деструкторе).

3. Почему бы просто не разместить такие объекты в стеке main ? Нет необходимости прибегать к синглетонам.

4. @DeadMG Я не уверен, о каких объектах мы говорим. Каким-то образом здесь появляются некоторые комментарии, которые имеют отношение к другому потоку. Однако, если речь идет об синглетонах, обычная причина использования синглтона в C заключается в том, что он может понадобиться в конструкторах статических объектов — обычная идиома singleton в C чаще используется для решения проблемы порядка инициализации, чем для чего-либо еще.