Re[11]: std::fopen падает в релизе с ошибкой 0xc0000417
От: Alexander G Украина  
Дата: 04.02.22 13:20
Оценка:
Здравствуйте, удусекшл, Вы писали:

У> Системная нерабочая ucrtbase.dll

У> http://files.rsdn.org/138407/2022_01_05_16_11_34_image.png
У> Рабочая
У> http://files.rsdn.org/138407/2022_01_05_16_12_35_image.png

Ага. Штатно это лечится позволением Windows обновляться
Ну или новой версией Windows, если обновления на данную уже не приходят.

Если не зависеть от обновлённости Windows, то такие пути:
* Всё же устанавливать конкретное обновление Windows, которое обновляет ucrtbase.dll
* Таскать с собой DLLки (это легально, они в папке с именем redist именно поэтому)
* Собирать c /MT
Русский военный корабль идёт ко дну!
Отредактировано 04.02.2022 13:21 Alexander G . Предыдущая версия .
Re[11]: std::fopen падает в релизе с ошибкой 0xc0000417
От: Alexander G Украина  
Дата: 04.02.22 13:36
Оценка:
Здравствуйте, удусекшл, Вы писали:

У>Да, винда у меня 7ка, и исходно там скорее всего C++17 не поддерживается.


Ха, ну да, похоже на то, что последняя версия вот https://support.microsoft.com/en-us/topic/update-for-universal-c-runtime-in-windows-c0514201-7fe6-95a3-b0a5-287930f3560c

Ucrtbase.dll

10.0.10240.16390

901,264

22-Aug-2015


У> Но вообще имхо так себе поведение. Можно же вернуть 0 и установить errno во что-то типа EINVALIDPARAM


По идее так и будет, если поставить _set_invalid_parameter_handler, который вовзращает управление.
Русский военный корабль идёт ко дну!
Re: std::fopen падает в релизе с ошибкой 0xc0000417
От: Pzz Россия https://github.com/alexpevzner
Дата: 04.02.22 13:42
Оценка: -1
Здравствуйте, удусекшл, Вы писали:

У>Здравствуйте!


У>Такой код:

У>
    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
От: Alexander G Украина  
Дата: 04.02.22 13:52
Оценка:
Здравствуйте, Pzz, Вы писали:

Pzz>Ох. Вот по-этому я говорю, что программы на C++ имеют тенденцию без нужды аллоцировать память на куче мелкими кусочками. Но мне никто не верит. Можно ведь так, например, сделать:


Pzz>
Pzz>{
Pzz>    char mode[8] = "w";
Pzz>    if (!appConfig.getOptOverwrite())
Pzz>        strcat(mode, "x");
Pzz>}
Pzz>


А можно и не делать.

small string optimization хотя бы на три буквы, а то и на семь или больше — де факто стандарт.

И лишние аллокации выоптимизировать компиляторы учатся во всё большем числе случаев.

Завезли constexpr строки в C++20.
Сейчас они должны умереть на этапе компиляции, но это ограничение могут в будущем отменить, и тогда компиляторам придётся уметь делать глубокие оптимизации, т.к. всё равно пропагейтить аллокации нужно будет уметь.

Ныне не справилась бы в данном случае, но вообще для std::string clang уже что-то умеет https://godbolt.org/z/f1jfP4537

Pzz>На вид все ОК. Наверное где-то протупил, но не таким очевидным образом. Например, fclose() два раза позвал, или как-то по-другому кучу разнес. fopen() не должен кидать исключений, аварийно завершать поток и т.п. ни при каких обстоятельствах.


Всё хуже https://rsdn.org/forum/cpp.applied/8187612.1
Автор: удусекшл
Дата: 04.02.22
Русский военный корабль идёт ко дну!
Отредактировано 04.02.2022 14:22 Alexander G . Предыдущая версия . Еще …
Отредактировано 04.02.2022 14:02 Alexander G . Предыдущая версия .
Re[2]: std::fopen падает в релизе с ошибкой 0xc0000417
От: удусекшл  
Дата: 04.02.22 13:52
Оценка:
Здравствуйте, Pzz, Вы писали:

У>>Такой код:

У>>
    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 Россия https://github.com/alexpevzner
Дата: 04.02.22 14:30
Оценка:
Здравствуйте, удусекшл, Вы писали:

Pzz>>Ох. Вот по-этому я говорю, что программы на C++ имеют тенденцию без нужды аллоцировать память на куче мелкими кусочками. Но мне никто не верит. Можно ведь так, например, сделать:


У>Сэр не слышал про small string optimization?


Слышал, но доверием не проникся. Ну и подумай, даже в случае оптимизации, насколько больше исполняемого кода породит std::string, чем если все сделать по-сишному?

Не то, чтобы на фоне fopen'а это было бы так уж важно, но сам подход...

У>А твой подход сишечкой попахивает


Сишечка и есть, что в этом постыдного?

У>Кстати, а в других языках (на чем ты сейчас пишешь?) будет как-то по-другому? Думаю, скорее всего будет ещё веселее, так как строки скорее всего иммутабельны, и там будет две строки в куче вместо одной


От других языков другие ожидания.

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

У>Разобрались уже, рантайм старый оказался, который не поддерживает опцию "x". Но ты прав, очень кривое поведение для fopen


Как-то все равно не повод нитку убивать. Стандарт, насколько я его помню, требует, чтобы fopen игнорировал буковки, которые он не может понять.

Я б скорее предположил, что структура FILE со своим описанием в заголовке не совпадает. Ну или что там сразу два рантайма к процессу подцепилось (косвенно, через другие DLL), и не смогли ужиться вместе.

А что, без буковки "x" все работало?
Re[4]: std::fopen падает в релизе с ошибкой 0xc0000417
От: Alexander G Украина  
Дата: 04.02.22 14:47
Оценка:
Здравствуйте, Pzz, Вы писали:

Pzz>Как-то все равно не повод нитку убивать. Стандарт, насколько я его помню, требует, чтобы fopen игнорировал буковки, которые он не может понять.


UB, увы (привет сишечке). Поэтому с точки зрения реализации abort адекватен (лучше же, чем замалчивать UB).
Русский военный корабль идёт ко дну!
Re[5]: std::fopen падает в релизе с ошибкой 0xc0000417
От: Pzz Россия https://github.com/alexpevzner
Дата: 04.02.22 14:53
Оценка:
Здравствуйте, Alexander G, Вы писали:

AG>UB, увы (привет сишечке). Поэтому с точки зрения реализации abort адекватен (лучше же, чем замалчивать UB).


Дебилы.

Можно же по-юниксовски вернуть EINVAL, если уж неймется...
Re[4]: std::fopen падает в релизе с ошибкой 0xc0000417
От: удусекшл  
Дата: 04.02.22 15:04
Оценка:
Здравствуйте, Pzz, Вы писали:

Pzz>>>Ох. Вот по-этому я говорю, что программы на C++ имеют тенденцию без нужды аллоцировать память на куче мелкими кусочками. Но мне никто не верит. Можно ведь так, например, сделать:


У>>Сэр не слышал про small string optimization?


Pzz>Слышал, но доверием не проникся. Ну и подумай, даже в случае оптимизации, насколько больше исполняемого кода породит std::string, чем если все сделать по-сишному?


https://gcc.godbolt.org/

  strcat C++
#include <string.h>
#include <iostream>

int main(int argc, char* argv[])
{
    char mode[8] = "w";
    if (argc>1)
        strcat(mode, "x");
    std::cout << &mode[0] <<"\n";
}

  strcat Asm
main:
        sub     rsp, 24
        mov     QWORD PTR [rsp+8], 119
        cmp     edi, 1
        jle     .L2
        mov     WORD PTR [rsp+9], 120
.L2:
        lea     rdi, [rsp+8]
        call    strlen
        lea     rsi, [rsp+8]
        mov     edi, OFFSET FLAT:_ZSt4cout
        mov     rdx, rax
        call    std::basic_ostream<char, std::char_traits<char> >& std::__ostream_insert<char, std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*, long)
        mov     edx, 1
        mov     esi, OFFSET FLAT:.LC0
        mov     edi, OFFSET FLAT:_ZSt4cout
        call    std::basic_ostream<char, std::char_traits<char> >& std::__ostream_insert<char, std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*, long)
        xor     eax, eax
        add     rsp, 24
        ret


  string C++
#include <string>
#include <iostream>

int main(int argc, char* argv[])
{
    std::string mode = "w";
    if (argc>1)
        mode.append("x");

    std::cout << mode <<"\n";
}

  string Asm
main:
        push    rbp
        mov     eax, 119
        push    rbx
        sub     rsp, 40
        lea     rbx, [rsp+16]
        mov     WORD PTR [rsp+16], ax
        mov     QWORD PTR [rsp], rbx
        mov     QWORD PTR [rsp+8], 1
        cmp     edi, 1
        jle     .L4
        mov     edx, 1
        mov     esi, OFFSET FLAT:.LC0
        mov     rdi, rsp
        call    std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::_M_append(char const*, unsigned long)
.L4:
        mov     rdx, QWORD PTR [rsp+8]
        mov     rsi, QWORD PTR [rsp]
        mov     edi, OFFSET FLAT:_ZSt4cout
        call    std::basic_ostream<char, std::char_traits<char> >& std::__ostream_insert<char, std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*, long)
        mov     rdi, rax
        mov     edx, 1
        mov     esi, OFFSET FLAT:.LC1
        call    std::basic_ostream<char, std::char_traits<char> >& std::__ostream_insert<char, std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*, long)
        mov     rdi, QWORD PTR [rsp]
        cmp     rdi, rbx
        je      .L9
        mov     rax, QWORD PTR [rsp+16]
        lea     rsi, [rax+1]
        call    operator delete(void*, unsigned long)
.L9:
        add     rsp, 40
        xor     eax, eax
        pop     rbx
        pop     rbp
        ret


Не так уж, чтобы совсем уж сильно больше


У>>А твой подход сишечкой попахивает


Pzz>Сишечка и есть, что в этом постыдного?





Pzz>Я б скорее предположил, что структура FILE со своим описанием в заголовке не совпадает.


А какая разница? Возвращается указатель, а по этому указателю я даже обратится никуда не успел


Pzz>А что, без буковки "x" все работало?


Угу
Re[6]: std::fopen падает в релизе с ошибкой 0xc0000417
От: Alexander G Украина  
Дата: 04.02.22 15:07
Оценка:
Здравствуйте, Pzz, Вы писали:

AG>>UB, увы (привет сишечке). Поэтому с точки зрения реализации abort адекватен (лучше же, чем замалчивать UB).


Pzz>Дебилы.


С точки зрения стандарта — пожалуй.

С точки зрения реализации — не согласен; если уж решено, что UB при невалидной строке, то валидная строка — предусловие.
Нарушения предусловий — не обрабатываемые рантайм ошибки, а а логические ошбики в программе, поэтому abort — самое верное решение.

Pzz>Можно же по-юниксовски вернуть EINVAL, если уж неймется...


Можно получить такое поведение, установив через _set_invalid_parameter_handler обработчик, который возвращает управление, но лучше не замалчивать нарушения предусловий.
Русский военный корабль идёт ко дну!
Re[7]: std::fopen падает в релизе с ошибкой 0xc0000417
От: Pzz Россия https://github.com/alexpevzner
Дата: 04.02.22 15:14
Оценка:
Здравствуйте, Alexander G, Вы писали:

Pzz>>Можно же по-юниксовски вернуть EINVAL, если уж неймется...


AG>Можно получить такое поведение, установив через _set_invalid_parameter_handler обработчик, который возвращает управление, но лучше не замалчивать нарушения предусловий.


Ну просто, набор буковок, который понимает fopen в параметре mode, не всегда был таким, как сейчас, и не навсегда таким останется. Некоторый разумный либерализм в плане отношения к незнакомым буквам позволяет иметь разумную степень совместимости между версиями пользовательского кода и версиями системной библиотеки.

В конце концов, я уверен, в древнем юниксе, в котором fopen впервые появился, именно с такой задумкой этот параметр и сделали строкой.
Re[8]: std::fopen падает в релизе с ошибкой 0xc0000417
От: Alexander G Украина  
Дата: 04.02.22 15:24
Оценка:
Здравствуйте, 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
От: удусекшл  
Дата: 04.02.22 15:29
Оценка:
Здравствуйте, Pzz, Вы писали:

Pzz>В конце концов, я уверен, в древнем юниксе, в котором fopen впервые появился, именно с такой задумкой этот параметр и сделали строкой.


А что мешает игнорировать неизвестные целочисленные флаги?
Меня, как раз, удивляет, что этот параметр задаётся строкой. Тут, скорее, подразумевалось, что этот параметр можно, не парся самому, прямо из пользовательского ввода передавать. Но это такое себе
Re[9]: std::fopen падает в релизе с ошибкой 0xc0000417
От: удусекшл  
Дата: 04.02.22 15:31
Оценка:
Здравствуйте, Alexander G, Вы писали:


AG>Скорее всего, оно так задумывалось в POSIX, но в C стандарте явно написали undefined (хотя из сноски следует, что вернее было бы оставить implementation-defined):


ЕМНИП, fopen — это не POSIX функция. POSIX — это open
Re[9]: std::fopen падает в релизе с ошибкой 0xc0000417
От: Alexander G Украина  
Дата: 04.02.22 15:48
Оценка:
Здравствуйте, удусекшл, Вы писали:

У>Тут, скорее, подразумевалось, что этот параметр можно, не парся самому, прямо из пользовательского ввода передавать. Но это такое себе


Программа открывает файл на чтение или на запись, передавая пользовательский ввод напрямую, и не анализируя его? Да не, бред какой-то.

Мои догадки:
* Заложились на будущее, чтобы передавать туда больше параметров, вроде октрыть COM порт и передать туда baud rate в строке.
* Хотели сделать "красивое" апи, типа "a+" изящнее O_RDWR | O_CREAT | O_APPEND. Примерно как к теми же C++ iostreams вышло, "красиво" != хорошо.
Русский военный корабль идёт ко дну!
Re[10]: std::fopen падает в релизе с ошибкой 0xc0000417
От: удусекшл  
Дата: 07.02.22 10:59
Оценка:
Здравствуйте, Alexander G, Вы писали:

У>>Тут, скорее, подразумевалось, что этот параметр можно, не парся самому, прямо из пользовательского ввода передавать. Но это такое себе


AG>Программа открывает файл на чтение или на запись, передавая пользовательский ввод напрямую, и не анализируя его? Да не, бред какой-то.


Это сейчас кажется бредом, а тогда, когда создавалось это АПИ — пользовательскому вводу доверяли больше


AG>Мои догадки:

AG> * Заложились на будущее, чтобы передавать туда больше параметров, вроде октрыть COM порт и передать туда baud rate в строке.

Это тоже вполне вероятно. Кстати, у MS в этом параметре можно задать кодировку:
FILE *fp = fopen("newfile.txt", "rt+, ccs=encoding");


Правда, выбор только из UTF16LE/UTF8 (без указания кодировка — ANSI)


AG> * Хотели сделать "красивое" апи, типа "a+" изящнее O_RDWR | O_CREAT | O_APPEND. Примерно как к теми же C++ iostreams вышло, "красиво" != хорошо.


А в чем, кстати, проблема с C++ iostreams? Только тормоза? Или какие-то ещё фатальные недостатки есть?
Re[11]: std::fopen падает в релизе с ошибкой 0xc0000417
От: Alexander G Украина  
Дата: 07.02.22 11:12
Оценка:
Здравствуйте, удусекшл, Вы писали:

У>А в чем, кстати, проблема с C++ iostreams? Только тормоза? Или какие-то ещё фатальные недостатки есть?


Торзмоза для I/O это важный недостаток.

Непредоставление важных системных механизмов -- тоже.
Кроме отсуствия всех флагов CreateFile (как этого же "x", так и некоторых других) я бы ещё припомнил отсутствие memory-mapped files.

Для текстовых потоков вывода. Ну разве это:
std::cout << filename << "(" << std::dec << line << "): " << func_name << "+0x" << std::hex << offset;

лучше этого:
std::print("{}({}): {}+{:#x}", filename, line, func_name, offset);

?
(std::format уже в C++20, std::print ожидается в C++23, ну и всё это можно взять для C++11 тут https://github.com/fmtlib/fmt)
Русский военный корабль идёт ко дну!
Re[12]: std::fopen падает в релизе с ошибкой 0xc0000417
От: удусекшл  
Дата: 07.02.22 11:22
Оценка:
Здравствуйте, Alexander G, Вы писали:

У>>А в чем, кстати, проблема с C++ iostreams? Только тормоза? Или какие-то ещё фатальные недостатки есть?


AG>Торзмоза для I/O это важный недостаток.


Это недостаток реализации. Я написал свой поток вывода, его можно прибиндить к чему угодно, вполне совместим со стандартными, весит мало, работает быстро. Мне в iostreams концепция инсертеров и манипуляторов вполне нравится.


AG>Непредоставление важных системных механизмов -- тоже.

AG>Кроме отсуствия всех флагов CreateFile (как этого же "x", так и некоторых других) я бы ещё припомнил отсутствие memory-mapped files.

Это да


AG>Для текстовых потоков вывода. Ну разве это:

AG>
AG>std::cout << filename << "(" << std::dec << line << "): " << func_name << "+0x" << std::hex << offset;
AG>

AG>лучше этого:
AG>
AG>std::print("{}({}): {}+{:#x}", filename, line, func_name, offset);
AG>

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
От: ononim  
Дата: 07.02.22 13:17
Оценка: 7 (1)
Pzz>Слышал, но доверием не проникся.
Вот реальное исследование https://shaharmike.com/cpp/std-string/ — фактически строки до полтора десятка символов аллокацию не делают от слова совсем.

Pzz>Ну и подумай, даже в случае оптимизации, насколько больше исполняемого кода породит std::string, чем если все сделать по-сишному?

По сишному — это каждый раз искать где там у этой строки нулевой байт? Плюсы хранят конец, почти как Паскаль, кстати (и го).

А еще помнится я сравнивал скорость работы bsearch и std::binary_search — разница была в разы, в пользу последнего.
Как много веселых ребят, и все делают велосипед...
Re[5]: std::fopen падает в релизе с ошибкой 0xc0000417
От: удусекшл  
Дата: 07.02.22 15:20
Оценка:
Здравствуйте, ononim, Вы писали:

Pzz>>Ну и подумай, даже в случае оптимизации, насколько больше исполняемого кода породит std::string, чем если все сделать по-сишному?

O>По сишному — это каждый раз искать где там у этой строки нулевой байт? Плюсы хранят конец, почти как Паскаль, кстати (и го).

Ну, я думаю, он имел в виду данный конкретный кейс
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.