if (!appConfig.outputFilename.empty())
{
std::string openMode = "w";
if (!appConfig.getOptOverwrite())
openMode.append("x"); // This flag forces the function to fail if the file exists, instead of overwriting it.
cout<<"try to create file '" << appConfig.outputFilename << "', open mode: '" << openMode << "'" << endl;
errno = 0;
std::FILE* pFile = std::fopen( appConfig.outputFilename.c_str(), openMode.c_str() );
//...
}
В ouput отладчика прилетает:
try to create file 'test.txt', open mode: 'wx'
The thread 0x4730 has exited with code -1073740777 (0xc0000417).
// Тут ёще куча потоков с тем же кодом завершается
std::fopen принимает в обоих параметрах const char* — вроде всё легально. Значения я печатаю до вызова — и имя файла и openMode — валидные строки.
В Debug сборке всё работает без нареканий. Я видимо, где-то протупил, но не пойму где.
ЗЫ std::fopen нужна вообще только с одной целью — обломаться, если файл существует. Почему-то стандартные потоки не имеют такого флага
Re: std::fopen падает в релизе с ошибкой 0xc0000417
Здравствуйте, удусекшл, Вы писали:
У> openMode.append("x"); // This flag forces the function to fail if the file exists, instead of overwriting it.
Какая версия C++ ? Выделено мной — PD
File access mode flag "x" can optionally be appended to "w" or "w+" specifiers. This flag forces the function to fail if the file exists, instead of overwriting it. (C++17)
Здравствуйте, Pavel Dvorkin, Вы писали:
PD>Какая версия C++ ? Выделено мной — PD
PD>File access mode flag "x" can optionally be appended to "w" or "w+" specifiers. This flag forces the function to fail if the file exists, instead of overwriting it. (C++17)
PD>https://en.cppreference.com/w/cpp/io/c/fopen
MSVC с ключиком "ISO C++17 Standard (/std:c++17)"
Re: std::fopen падает в релизе с ошибкой 0xc0000417
Здравствуйте, LaptevVV, Вы писали:
LVV>1. Явно падает по неправильному указателю. Скорее всего нулевой.
С чего такой вывод? Ну, и код я привел, можно пальцем ткнуть, где там получается неправильный указатель?
LVV>2. В С++17 есть уже файловая система, и там уже есть что-то вроде exist() для файла.
Угу, только между тем моментом, когда я проверил существование файла, и тем моментом, когда я его создал — кто-то другой может захотеть сделать тоже самое, и никто ему и слова не скажет
Re[3]: std::fopen падает в релизе с ошибкой 0xc0000417
Здравствуйте, удусекшл, Вы писали:
У>The thread 0x4730 has exited with code -1073740777 (0xc0000417). У>// Тут ёще куча потоков с тем же кодом завершается
Это STATUS_INVALID_CRUNTIME_PARAMETER, по идее:
* Должно быть видно под отладчиком как Win32 Exception с таким кодом.
* Должно ловиться через обработчик _set_invalid_parameter_handler.
Если несвязанные потоки завершаются так, это может быть порча памяти, если есть возможность запустить с Address Sanitizer, я бы его попробовал. Если нет — AppVerifier с Heaps с меньшей, но ненулевой вероятностью может что-то поймать.
Русский военный корабль идёт ко дну!
Re[3]: std::fopen падает в релизе с ошибкой 0xc0000417
Здравствуйте, удусекшл, Вы писали:
PD>>File access mode flag "x" can optionally be appended to "w" or "w+" specifiers. This flag forces the function to fail if the file exists, instead of overwriting it. (C++17)
PD>>https://en.cppreference.com/w/cpp/io/c/fopen
У>MSVC с ключиком "ISO C++17 Standard (/std:c++17)"
Для функций C runtime на самом деле имеет значение не ключик, а версия рантайма.
При сборке с /MD берётся системный рантайм, который может быть слишком старый.
VS 2015, 2017, 2019, 2022 используют те же самые DLL, т.е. програма может взять версию от 2015.
Здравствуйте, Alexander G, Вы писали:
AG>Для функций C runtime на самом деле имеет значение не ключик, а версия рантайма. AG>При сборке с /MD берётся системный рантайм, который может быть слишком старый. AG>VS 2015, 2017, 2019, 2022 используют те же самые DLL, т.е. програма может взять версию от 2015.
Я тоже об этом подумал, но ТС ведь делает в среде VS, а в этом случае должен браться рантайм от нее. А поскольку он явно с рантаймами не колдовал, то должен браться 17.
With best regards
Pavel Dvorkin
Re: std::fopen падает в релизе с ошибкой 0xc0000417
Здравствуйте, удусекшл, Вы писали:
У>Такой код: У>
if (!appConfig.outputFilename.empty())
У> {
У> std::string openMode = "w";
У> if (!appConfig.getOptOverwrite())
У> openMode.append("x"); // This flag forces the function to fail if the file exists, instead of overwriting it.
У> cout<<"try to create file '" << appConfig.outputFilename << "', open mode: '" << openMode << "'" << endl;
У> errno = 0;
У> std::FILE* pFile = std::fopen( appConfig.outputFilename.c_str(), openMode.c_str() );
У> //...
У> }
У>
В этом коде меня смущает только errno:
On some ancient systems, <errno.h> was not present or did not
declare errno, so that it was necessary to declare errno manually
(i.e., extern int errno). Do not do this. It long ago ceased to
be necessary, and it will cause problems with modern versions of
the C library.
Следует проверить её декларацию. Зачем, кстати, её занулять?
У>// Тут ёще куча потоков с тем же кодом завершается
Раз приложение многопоточное, то следует убедиться, что appConfig никто не меняет.
Раз приложение многопоточное, то место падения может не соответствовать причине падения.
У>В Debug сборке всё работает без нареканий. Я видимо, где-то протупил, но не пойму где.
Скорее всего ошибка вне этого куска кода.
И каждый день — без права на ошибку...
Re[5]: std::fopen падает в релизе с ошибкой 0xc0000417
Здравствуйте, Pavel Dvorkin, Вы писали:
PD>Я тоже об этом подумал, но ТС ведь делает в среде VS, а в этом случае должен браться рантайм от нее. А поскольку он явно с рантаймами не колдовал, то должен браться 17.
Не обязательно. Можно установить более старый рантайм после установки VS 2017+ например, удалив рантайм, и установив старый vcredist, какой-либо инсталлер в принципе на такое способен без ведома пользователя. Отладочные DLLки более защищены от такого, т.к. официально не являются redistributable и не входят ни в какой vcredist.
Русский военный корабль идёт ко дну!
Re[3]: std::fopen падает в релизе с ошибкой 0xc0000417
LVV>>1. Явно падает по неправильному указателю. Скорее всего нулевой. У>С чего такой вывод? Ну, и код я привел, можно пальцем ткнуть, где там получается неправильный указатель?
Вывод из опыта.
Каким компилятором компилил?
LVV>>2. В С++17 есть уже файловая система, и там уже есть что-то вроде exist() для файла. У>Угу, только между тем моментом, когда я проверил существование файла, и тем моментом, когда я его создал — кто-то другой может захотеть сделать тоже самое, и никто ему и слова не скажет
Дык в твоем коде это может случится в любом месте между любых двух строк кода.
И с чего там у тебя "wx" ? https://ru.cppreference.com/w/c/io/fopen
тут икса нет ни разу.
Хочешь быть счастливым — будь им!
Без булдырабыз!!!
Re: std::fopen падает в релизе с ошибкой 0xc0000417
Здравствуйте, удусекшл, Вы писали:
У>Здравствуйте!
Я конечно может туплю, но если воспроизводится в отладчике, в чём проблема посмотреть где именно вылетает и какая причина вылета потока? Callstack и значения аргументов функций в точке падения должны же быть видны, а отладчик должен встать на место падения, (если не настроен пропуск таких исключений)
File access mode flag "x" can optionally be appended to "w" or "w+" specifiers. This flag forces the function to fail if the file exists, instead of overwriting it. (C++17)
Re[2]: std::fopen падает в релизе с ошибкой 0xc0000417
Здравствуйте, Alexander G, Вы писали: AG>Для функций C runtime на самом деле имеет значение не ключик, а версия рантайма. AG>При сборке с /MD берётся системный рантайм, который может быть слишком старый. AG>VS 2015, 2017, 2019, 2022 используют те же самые DLL, т.е. програма может взять версию от 2015. AG>свежий vcredist может в этом случае помочь
У меня вот такой
Скрытый текст
Предлагает "исправить"
ЗЫ Не помогло
Re[2]: std::fopen падает в релизе с ошибкой 0xc0000417
Здравствуйте, B0FEE664, Вы писали:
BFE>Следует проверить её декларацию. Зачем, кстати, её занулять?
На всякий случай
Впрочем, я убрал эту строчку, ничего не изменилось
У>>// Тут ёще куча потоков с тем же кодом завершается BFE>Раз приложение многопоточное, то следует убедиться, что appConfig никто не меняет. BFE>Раз приложение многопоточное, то место падения может не соответствовать причине падения.
Приложение однопоточное, мелкая тулза, весь main на 100 строчек. Я хз, почему в MSVCшный output выводится инфа о куче потоков. Думаю, это а) рантайм чего-то делате хз зачем, б) отладчик студийный тоже чего-то запускает
У>>В Debug сборке всё работает без нареканий. Я видимо, где-то протупил, но не пойму где. BFE>Скорее всего ошибка вне этого куска кода.
Вероятно. Но мне как-то легче не стало
Re[5]: std::fopen падает в релизе с ошибкой 0xc0000417
Здравствуйте, LaptevVV, Вы писали:
LVV>>>1. Явно падает по неправильному указателю. Скорее всего нулевой. У>>С чего такой вывод? Ну, и код я привел, можно пальцем ткнуть, где там получается неправильный указатель? LVV>Вывод из опыта.
Ну, вообще-то, когда падает по нулевому указателю, там SEH исключение кидается, которое студия (или система, если не из под студии) ловит и вполне внятно показывает
LVV>Каким компилятором компилил?
MSVC2019/C++17
LVV>>>2. В С++17 есть уже файловая система, и там уже есть что-то вроде exist() для файла. У>>Угу, только между тем моментом, когда я проверил существование файла, и тем моментом, когда я его создал — кто-то другой может захотеть сделать тоже самое, и никто ему и слова не скажет LVV>Дык в твоем коде это может случится в любом месте между любых двух строк кода.
Это как? Так-то fopen должна, как я понимаю, атомарно это делать
У>Invalid parameter detected in function (null). File: (null) Line: 0
У>Expression: (null)
У>Что-то не особо понятнее стало
Да, в релизном рантайме нет этой информации.
Но можно ведь посмотреть колл стэк откуда туда попали.
Точку останова поставить и отдалчиком посмотреть.
(Без отладчика -- напечатать через какой-нибудь boost::stacktrace или аналог, но продуктивнее таки с отладчиком)
Русский военный корабль идёт ко дну!
Re[2]: std::fopen падает в релизе с ошибкой 0xc0000417
Здравствуйте, ArtDenis, Вы писали:
AD>Я конечно может туплю, но если воспроизводится в отладчике, в чём проблема посмотреть где именно вылетает и какая причина вылета потока? Callstack и значения аргументов функций в точке падения должны же быть видны, а отладчик должен встать на место падения, (если не настроен пропуск таких исключений)
Я наверно тоже туплю, но попытка пройти эту строчку по F10/F11 молча завершает программу.
Уже подсказали — вызывается _invalid_parameter_handler, который, скорее всего, вызывает abort. Так что исключений никаких нет. А при запуске из системы (без студии) — винда выдаёт окошко с сообщением об ошибке. Или это делает рантайм, я хз
Re[4]: std::fopen падает в релизе с ошибкой 0xc0000417
Здравствуйте, Alexander G, Вы писали: AG>Да, в релизном рантайме нет этой информации. AG>Но можно ведь посмотреть колл стэк откуда туда попали. AG>Точку останова поставить и отдалчиком посмотреть. AG>(Без отладчика -- напечатать через какой-нибудь boost::stacktrace или аналог, но продуктивнее таки с отладчиком)
Там очень информативно
Ну, показывает либо на строчку в main, где fopen вызывается, либо на мой обработчик
Re[5]: std::fopen падает в релизе с ошибкой 0xc0000417
Надо выключить Options > Debugging > General > [ ] Enable Just My Code.
Ещё могут исходинки не подхватываться, стандартная проблема из-за того, что DLLки рантайма обновляются, если есть возможность, лучше всего изучить проблему с /MT, а не /MD; иначе — насильно загружать исходники, даже если чексумма не совпадает, расхождения обычно небольшие.
Русский военный корабль идёт ко дну!
Re[6]: std::fopen падает в релизе с ошибкой 0xc0000417
Здравствуйте, Alexander G, Вы писали:
У>>http://files.rsdn.org/138407/2022_01_05_13_40_03_image.png]Image: 2022_01_05_13_40_03_image.png У>>Ну, показывает либо на строчку в main, где fopen вызывается, либо на мой обработчик
AG>Надо выключить Options > Debugging > General > [ ] Enable Just My Code.
Да, спасибо, стало поподробнее
AG>Ещё могут исходинки не подхватываться, стандартная проблема из-за того, что DLLки рантайма обновляются, если есть возможность, лучше всего изучить проблему с /MT, а не /MD; иначе — насильно загружать исходники, даже если чексумма не совпадает, расхождения обычно небольшие.
Я ручками открыл файл, в котором нашел __acrt_stdio_parse_mode — C:\Program Files (x86)\Windows Kits\10\Source\10.0.19041.0\ucrt\inc\corecrt_internal_stdio.h — но студия всё равно только дизасм показывает
Пересобрал с /MT — не падает, работает как надо. Это конечно здорово, но таки хочется понять, где был косяк. Без опции "x" — работает и с /MD, видимо, MSVCшный dll рантайм косячный
Re[3]: std::fopen падает в релизе с ошибкой 0xc0000417
Здравствуйте, удусекшл, Вы писали:
У>Я наверно тоже туплю, но попытка пройти эту строчку по F10/F11 молча завершает программу. У>Уже подсказали — вызывается _invalid_parameter_handler, который, скорее всего, вызывает abort. Так что исключений никаких нет. А при запуске из системы (без студии) — винда выдаёт окошко с сообщением об ошибке. Или это делает рантайм, я хз
int main()
{
abort();
}
Прекрасно отлаживается в релизе. А иначе нафига нужен такой отладчик, который такие вещи не ловит?
У>>Уже подсказали — вызывается _invalid_parameter_handler, который, скорее всего, вызывает abort. Так что исключений никаких нет. А при запуске из системы (без студии) — винда выдаёт окошко с сообщением об ошибке. Или это делает рантайм, я хз
AD>
AD>int main()
AD>{
AD> abort();
AD>}
AD>
AD>Прекрасно отлаживается в релизе. А иначе нафига нужен такой отладчик, который такие вещи не ловит?
Ну, когда я подменил _invalid_parameter_handler и поставил там бряк, то да, он там останавливается
Re[5]: std::fopen падает в релизе с ошибкой 0xc0000417
Здравствуйте, удусекшл, Вы писали:
У>Ну, когда я подменил _invalid_parameter_handler и поставил там бряк, то да, он там останавливается
Ну понятно, что он там остановится, если ты его переопределишь. Лучше разберись с отладчиком. С ним гораздо проще будет такие вещи и отлавливать и отлаживать. Где-то у тебя запрет стоит на останов в отладчике по таким событиям
Здравствуйте, ArtDenis, Вы писали:
У>>Ну, когда я подменил _invalid_parameter_handler и поставил там бряк, то да, он там останавливается
AD>Ну понятно, что он там остановится, если ты его переопределишь. Лучше разберись с отладчиком. С ним гораздо проще будет такие вещи и отлавливать и отлаживать. Где-то у тебя запрет стоит на останов в отладчике по таким событиям
По каким событиям? Это не SEH исключение, это не плюсовое исключение, это вызов функции рантайма, которая просто завершает процесс
Re[7]: std::fopen падает в релизе с ошибкой 0xc0000417
Здравствуйте, удусекшл, Вы писали:
У>По каким событиям? Это не SEH исключение, это не плюсовое исключение, это вызов функции рантайма, которая просто завершает процесс
Ну так у тебя просто на abort() в main отладчик реагирует при отладке релизного билда?
Здравствуйте, ArtDenis, Вы писали:
У>>По каким событиям? Это не SEH исключение, это не плюсовое исключение, это вызов функции рантайма, которая просто завершает процесс
AD>Ну так у тебя просто на abort() в main отладчик реагирует при отладке релизного билда?
Реагирует.
Видимо, там не abort, а что-то другое вызывается
Re[7]: std::fopen падает в релизе с ошибкой 0xc0000417
Здравствуйте, удусекшл, Вы писали:
У> __acrt_stdio_parse_mode — C:\Program Files (x86)\Windows Kits\10\Source\10.0.19041.0\ucrt\inc\corecrt_internal_stdio.h
У>Пересобрал с /MT — не падает, работает как надо. Это конечно здорово, но таки хочется понять, где был косяк. Без опции "x" — работает и с /MD, видимо, MSVCшный dll рантайм косячный
Это интересная подробность. Похоже, что откуда-то взялась таки старая DLLка, в которой ещё не было "x"
Глянуть в окне call stack, в какой именно DLLке падающая __acrt_stdio_parse_mode, и в окне modules -- полную версию и полный путь.
Попробовать подложить рядом с приложением правильные DLLки из
C:\Program Files (x86)\Microsoft Visual Studio\2019\Professional\VC\Redist\MSVC\14.29.30133\x64\Microsoft.VC142.CRT
(путь может отличаться в зависимости от версии студии и архитектуры процессора/разрядности)
Здравствуйте, удусекшл, Вы писали:
У>Я ручками открыл файл, в котором нашел __acrt_stdio_parse_mode — C:\Program Files (x86)\Windows Kits\10\Source\10.0.19041.0\ucrt\inc\corecrt_internal_stdio.h — но студия всё равно только дизасм показывает
Ага, похоже, что оно внутри universal CRT, а не VC runtime. Которая ucrtbase.dll. (Да, сейчас рантайм из двух частей состоит)
Здравствуйте, Alexander G, Вы писали:
AG>Это интересная подробность. Похоже, что откуда-то взялась таки старая DLLка, в которой ещё не было "x" AG>Глянуть в окне call stack, в какой именно DLLке падающая __acrt_stdio_parse_mode, и в окне modules -- полную версию и полный путь.
Функция лежит в C:\Windows\System32\ucrtbase.dll
Я так понимаю, что это просто какой-то прокси, не?
А само всё лежит в C:\Windows\System32\api-ms-win-crt-stdio-l1-1-0.dll
AG>Попробовать подложить рядом с приложением правильные DLLки из AG>C:\Program Files (x86)\Microsoft Visual Studio\2019\Professional\VC\Redist\MSVC\14.29.30133\x64\Microsoft.VC142.CRT AG>(путь может отличаться в зависимости от версии студии и архитектуры процессора/разрядности)
Примерно там и лежит, с учётом того, что у меня Community
Не помогло
Ну, и там, кстати, никакой ucrtbase.dll нет
Re[8]: std::fopen падает в релизе с ошибкой 0xc0000417
Здравствуйте, Alexander G, Вы писали:
У>>Я ручками открыл файл, в котором нашел __acrt_stdio_parse_mode — C:\Program Files (x86)\Windows Kits\10\Source\10.0.19041.0\ucrt\inc\corecrt_internal_stdio.h — но студия всё равно только дизасм показывает
AG>Ага, похоже, что оно внутри universal CRT, а не VC runtime. Которая ucrtbase.dll. (Да, сейчас рантайм из двух частей состоит)
AG>См тут инструкции по обновлению https://docs.microsoft.com/en-us/cpp/windows/universal-crt-deployment?view=msvc-170
Спс, гляну.
ЗЫ А как таки заставить отладчик видеть сорцы? На странице "No source available" предлагается только дизасм, а вроде раньше было, что можно было ручками промотать до исходника в диалоге "Open file"
Re[9]: std::fopen падает в релизе с ошибкой 0xc0000417
Здравствуйте, удусекшл, Вы писали:
У>ЗЫ А как таки заставить отладчик видеть сорцы? На странице "No source available" предлагается только дизасм, а вроде раньше было, что можно было ручками промотать до исходника в диалоге "Open file"
Может даже так быть, что и никак . Т.к. universal CRT как бы компонент ОС, а не Студии, .pdb может быть stripped, как обычно для компонентов Windows, т.е. без ссылок на исходник.
Приходится использовать /MT или дебаг для нормальной отладки (в случае проблем не вызванных именно /MD).
Ну а с этой проблемой исходники всё равно вряд ли полезны, раз проблема именно в том, что DLL не та.
Русский военный корабль идёт ко дну!
Re[10]: std::fopen падает в релизе с ошибкой 0xc0000417
Здравствуйте, Alexander G, Вы писали:
AG>Может даже так быть, что и никак . Т.к. universal CRT как бы компонент ОС, а не Студии, .pdb может быть stripped, как обычно для компонентов Windows, т.е. без ссылок на исходник. AG>Приходится использовать /MT или дебаг для нормальной отладки (в случае проблем не вызванных именно /MD).
AG>Ну а с этой проблемой исходники всё равно вряд ли полезны, раз проблема именно в том, что DLL не та.
Да, винда у меня 7ка, и исходно там скорее всего C++17 не поддерживается. Но вообще имхо так себе поведение. Можно же вернуть 0 и установить errno во что-то типа EINVALIDPARAM
Re[11]: std::fopen падает в релизе с ошибкой 0xc0000417
Ага. Штатно это лечится позволением Windows обновляться
Ну или новой версией Windows, если обновления на данную уже не приходят.
Если не зависеть от обновлённости Windows, то такие пути:
* Всё же устанавливать конкретное обновление Windows, которое обновляет ucrtbase.dll
* Таскать с собой DLLки (это легально, они в папке с именем redist именно поэтому)
* Собирать c /MT
Здравствуйте, удусекшл, Вы писали:
У>Здравствуйте!
У>Такой код: У>
if (!appConfig.outputFilename.empty())
У> {
У> std::string openMode = "w";
У> if (!appConfig.getOptOverwrite())
У> openMode.append("x"); // This flag forces the function to fail if the file exists, instead of overwriting it.
У> }
У>
Ох. Вот по-этому я говорю, что программы на C++ имеют тенденцию без нужды аллоцировать память на куче мелкими кусочками. Но мне никто не верит. Можно ведь так, например, сделать:
{
char mode[8] = "w";
if (!appConfig.getOptOverwrite())
strcat(mode, "x");
}
Можно и без strcat'а обойтись, не теряя особенно в выразительности. Но это упражнение я оставлю пытливому читателю.
У>std::fopen принимает в обоих параметрах const char* — вроде всё легально. Значения я печатаю до вызова — и имя файла и openMode — валидные строки.
У>В Debug сборке всё работает без нареканий. Я видимо, где-то протупил, но не пойму где.
На вид все ОК. Наверное где-то протупил, но не таким очевидным образом. Например, fclose() два раза позвал, или как-то по-другому кучу разнес. fopen() не должен кидать исключений, аварийно завершать поток и т.п. ни при каких обстоятельствах.
Re[2]: std::fopen падает в релизе с ошибкой 0xc0000417
Здравствуйте, Pzz, Вы писали:
Pzz>Ох. Вот по-этому я говорю, что программы на C++ имеют тенденцию без нужды аллоцировать память на куче мелкими кусочками. Но мне никто не верит. Можно ведь так, например, сделать:
Pzz>
small string optimization хотя бы на три буквы, а то и на семь или больше — де факто стандарт.
И лишние аллокации выоптимизировать компиляторы учатся во всё большем числе случаев.
Завезли constexpr строки в C++20.
Сейчас они должны умереть на этапе компиляции, но это ограничение могут в будущем отменить, и тогда компиляторам придётся уметь делать глубокие оптимизации, т.к. всё равно пропагейтить аллокации нужно будет уметь.
Ныне не справилась бы в данном случае, но вообще для std::string clang уже что-то умеет https://godbolt.org/z/f1jfP4537
Pzz>На вид все ОК. Наверное где-то протупил, но не таким очевидным образом. Например, fclose() два раза позвал, или как-то по-другому кучу разнес. fopen() не должен кидать исключений, аварийно завершать поток и т.п. ни при каких обстоятельствах.
if (!appConfig.outputFilename.empty())
У>> {
У>> std::string openMode = "w";
У>> if (!appConfig.getOptOverwrite())
У>> openMode.append("x"); // This flag forces the function to fail if the file exists, instead of overwriting it.
У>> }
У>>
Pzz>Ох. Вот по-этому я говорю, что программы на C++ имеют тенденцию без нужды аллоцировать память на куче мелкими кусочками. Но мне никто не верит. Можно ведь так, например, сделать:
Сэр не слышал про small string optimization?
А твой подход сишечкой попахивает
Кстати, а в других языках (на чем ты сейчас пишешь?) будет как-то по-другому? Думаю, скорее всего будет ещё веселее, так как строки скорее всего иммутабельны, и там будет две строки в куче вместо одной
Pzz>На вид все ОК. Наверное где-то протупил, но не таким очевидным образом. Например, fclose() два раза позвал, или как-то по-другому кучу разнес. fopen() не должен кидать исключений, аварийно завершать поток и т.п. ни при каких обстоятельствах.
Разобрались уже, рантайм старый оказался, который не поддерживает опцию "x". Но ты прав, очень кривое поведение для fopen
Re[3]: std::fopen падает в релизе с ошибкой 0xc0000417
Здравствуйте, удусекшл, Вы писали:
Pzz>>Ох. Вот по-этому я говорю, что программы на C++ имеют тенденцию без нужды аллоцировать память на куче мелкими кусочками. Но мне никто не верит. Можно ведь так, например, сделать:
У>Сэр не слышал про small string optimization?
Слышал, но доверием не проникся. Ну и подумай, даже в случае оптимизации, насколько больше исполняемого кода породит std::string, чем если все сделать по-сишному?
Не то, чтобы на фоне fopen'а это было бы так уж важно, но сам подход...
У>А твой подход сишечкой попахивает
Сишечка и есть, что в этом постыдного?
У>Кстати, а в других языках (на чем ты сейчас пишешь?) будет как-то по-другому? Думаю, скорее всего будет ещё веселее, так как строки скорее всего иммутабельны, и там будет две строки в куче вместо одной
От других языков другие ожидания.
Но в принципе, рантайм языков со сборкой мусора ожидает, что изрядная часть аллокаций делаются на очень незначительное время, и оптимизирован так, чтобы их быстро найти и освободить, если они больше не нужны. А вот с аллокациями-долгожителями разбираются отдельно.
У>Разобрались уже, рантайм старый оказался, который не поддерживает опцию "x". Но ты прав, очень кривое поведение для fopen
Как-то все равно не повод нитку убивать. Стандарт, насколько я его помню, требует, чтобы fopen игнорировал буковки, которые он не может понять.
Я б скорее предположил, что структура FILE со своим описанием в заголовке не совпадает. Ну или что там сразу два рантайма к процессу подцепилось (косвенно, через другие DLL), и не смогли ужиться вместе.
А что, без буковки "x" все работало?
Re[4]: std::fopen падает в релизе с ошибкой 0xc0000417
Здравствуйте, Pzz, Вы писали:
Pzz>Как-то все равно не повод нитку убивать. Стандарт, насколько я его помню, требует, чтобы fopen игнорировал буковки, которые он не может понять.
UB, увы (привет сишечке). Поэтому с точки зрения реализации abort адекватен (лучше же, чем замалчивать UB).
Русский военный корабль идёт ко дну!
Re[5]: std::fopen падает в релизе с ошибкой 0xc0000417
Здравствуйте, Pzz, Вы писали: Pzz>>>Ох. Вот по-этому я говорю, что программы на C++ имеют тенденцию без нужды аллоцировать память на куче мелкими кусочками. Но мне никто не верит. Можно ведь так, например, сделать: У>>Сэр не слышал про small string optimization? Pzz>Слышал, но доверием не проникся. Ну и подумай, даже в случае оптимизации, насколько больше исполняемого кода породит std::string, чем если все сделать по-сишному?
Здравствуйте, Pzz, Вы писали:
AG>>UB, увы (привет сишечке). Поэтому с точки зрения реализации abort адекватен (лучше же, чем замалчивать UB).
Pzz>Дебилы.
С точки зрения стандарта — пожалуй.
С точки зрения реализации — не согласен; если уж решено, что UB при невалидной строке, то валидная строка — предусловие.
Нарушения предусловий — не обрабатываемые рантайм ошибки, а а логические ошбики в программе, поэтому abort — самое верное решение.
Pzz>Можно же по-юниксовски вернуть EINVAL, если уж неймется...
Можно получить такое поведение, установив через _set_invalid_parameter_handler обработчик, который возвращает управление, но лучше не замалчивать нарушения предусловий.
Русский военный корабль идёт ко дну!
Re[7]: std::fopen падает в релизе с ошибкой 0xc0000417
Здравствуйте, Alexander G, Вы писали:
Pzz>>Можно же по-юниксовски вернуть EINVAL, если уж неймется...
AG>Можно получить такое поведение, установив через _set_invalid_parameter_handler обработчик, который возвращает управление, но лучше не замалчивать нарушения предусловий.
Ну просто, набор буковок, который понимает fopen в параметре mode, не всегда был таким, как сейчас, и не навсегда таким останется. Некоторый разумный либерализм в плане отношения к незнакомым буквам позволяет иметь разумную степень совместимости между версиями пользовательского кода и версиями системной библиотеки.
В конце концов, я уверен, в древнем юниксе, в котором fopen впервые появился, именно с такой задумкой этот параметр и сделали строкой.
Re[8]: std::fopen падает в релизе с ошибкой 0xc0000417
Здравствуйте, Pzz, Вы писали:
Pzz>Ну просто, набор буковок, который понимает fopen в параметре mode, не всегда был таким, как сейчас, и не навсегда таким останется. Некоторый разумный либерализм в плане отношения к незнакомым буквам позволяет иметь разумную степень совместимости между версиями пользовательского кода и версиями системной библиотеки.
Pzz>В конце концов, я уверен, в древнем юниксе, в котором fopen впервые появился, именно с такой задумкой этот параметр и сделали строкой.
Скорее всего, оно так задумывалось в POSIX, но в C стандарте явно написали undefined (хотя из сноски следует, что вернее было бы оставить implementation-defined):
7.19.5.3 The fopen function
The argument mode points to a string. If the string is one of the following, the file is
open in the indicated mode. Otherwise, the behavior is undefined.237)
237) If the string begins with one of the above sequences, the implementation might choose to ignore the
remaining characters, or it might use them to select different kinds of a file (some of which might not
conform to the properties in 7.19.2).
Раз уж получилось UB, то было бы неконсистентно при других декектируемых UB вызывать _invalid_parameter_handler с дефолтом abort, а при этом — нет.
Русский военный корабль идёт ко дну!
Re[8]: std::fopen падает в релизе с ошибкой 0xc0000417
Здравствуйте, Pzz, Вы писали:
Pzz>В конце концов, я уверен, в древнем юниксе, в котором fopen впервые появился, именно с такой задумкой этот параметр и сделали строкой.
А что мешает игнорировать неизвестные целочисленные флаги?
Меня, как раз, удивляет, что этот параметр задаётся строкой. Тут, скорее, подразумевалось, что этот параметр можно, не парся самому, прямо из пользовательского ввода передавать. Но это такое себе
Re[9]: std::fopen падает в релизе с ошибкой 0xc0000417
AG>Скорее всего, оно так задумывалось в POSIX, но в C стандарте явно написали undefined (хотя из сноски следует, что вернее было бы оставить implementation-defined):
ЕМНИП, fopen — это не POSIX функция. POSIX — это open
Re[9]: std::fopen падает в релизе с ошибкой 0xc0000417
Здравствуйте, удусекшл, Вы писали:
У>Тут, скорее, подразумевалось, что этот параметр можно, не парся самому, прямо из пользовательского ввода передавать. Но это такое себе
Программа открывает файл на чтение или на запись, передавая пользовательский ввод напрямую, и не анализируя его? Да не, бред какой-то.
Мои догадки:
* Заложились на будущее, чтобы передавать туда больше параметров, вроде октрыть COM порт и передать туда baud rate в строке.
* Хотели сделать "красивое" апи, типа "a+" изящнее O_RDWR | O_CREAT | O_APPEND. Примерно как к теми же C++ iostreams вышло, "красиво" != хорошо.
Русский военный корабль идёт ко дну!
Re[10]: std::fopen падает в релизе с ошибкой 0xc0000417
Здравствуйте, Alexander G, Вы писали:
У>>Тут, скорее, подразумевалось, что этот параметр можно, не парся самому, прямо из пользовательского ввода передавать. Но это такое себе
AG>Программа открывает файл на чтение или на запись, передавая пользовательский ввод напрямую, и не анализируя его? Да не, бред какой-то.
Это сейчас кажется бредом, а тогда, когда создавалось это АПИ — пользовательскому вводу доверяли больше
AG>Мои догадки: AG> * Заложились на будущее, чтобы передавать туда больше параметров, вроде октрыть COM порт и передать туда baud rate в строке.
Это тоже вполне вероятно. Кстати, у MS в этом параметре можно задать кодировку:
Здравствуйте, удусекшл, Вы писали:
У>А в чем, кстати, проблема с C++ iostreams? Только тормоза? Или какие-то ещё фатальные недостатки есть?
Торзмоза для I/O это важный недостаток.
Непредоставление важных системных механизмов -- тоже.
Кроме отсуствия всех флагов CreateFile (как этого же "x", так и некоторых других) я бы ещё припомнил отсутствие memory-mapped files.
Здравствуйте, Alexander G, Вы писали:
У>>А в чем, кстати, проблема с C++ iostreams? Только тормоза? Или какие-то ещё фатальные недостатки есть?
AG>Торзмоза для I/O это важный недостаток.
Это недостаток реализации. Я написал свой поток вывода, его можно прибиндить к чему угодно, вполне совместим со стандартными, весит мало, работает быстро. Мне в iostreams концепция инсертеров и манипуляторов вполне нравится.
AG>Непредоставление важных системных механизмов -- тоже. AG>Кроме отсуствия всех флагов CreateFile (как этого же "x", так и некоторых других) я бы ещё припомнил отсутствие memory-mapped files.
AG>? AG>(std::format уже в C++20, std::print ожидается в C++23, ну и всё это можно взять для C++11 тут https://github.com/fmtlib/fmt)
Да не особо и лучше, не спорю. Особенно, если там свои типы выводить также просто, как и в iostreams. Но тут надо учитывать, когда iostreams родился, а когда std::format стало возможно реализовать
Re[4]: std::fopen падает в релизе с ошибкой 0xc0000417
Pzz>Слышал, но доверием не проникся.
Вот реальное исследование https://shaharmike.com/cpp/std-string/ — фактически строки до полтора десятка символов аллокацию не делают от слова совсем.
Pzz>Ну и подумай, даже в случае оптимизации, насколько больше исполняемого кода породит std::string, чем если все сделать по-сишному?
По сишному — это каждый раз искать где там у этой строки нулевой байт? Плюсы хранят конец, почти как Паскаль, кстати (и го).
А еще помнится я сравнивал скорость работы bsearch и std::binary_search — разница была в разы, в пользу последнего.
Как много веселых ребят, и все делают велосипед...
Re[5]: std::fopen падает в релизе с ошибкой 0xc0000417
Здравствуйте, ononim, Вы писали:
Pzz>>Ну и подумай, даже в случае оптимизации, насколько больше исполняемого кода породит std::string, чем если все сделать по-сишному? O>По сишному — это каждый раз искать где там у этой строки нулевой байт? Плюсы хранят конец, почти как Паскаль, кстати (и го).
Ну, я думаю, он имел в виду данный конкретный кейс