Pull to refresh

Comments 17

Судя по std:: это С++ (а на Си), в таких случаях нужно писать абстракцию для буффера, который может быть аллоцирован на стеке или куче. Тогда не надо думать об освобождении памяти при написании логики, потомучто об этом позаботиться RAII. Уверен в бусте уже есть что-то готовое.

Интересно, чем стандартный vector не подошёл.

он будет инициализировать всё нулями

Нет, не будет. Есть конструктор без инициализации. Ну или можно конструктор по умолчанию использовать.

Нету конструктора без инициализации, есть конструктор с инициализацией-по-умолчанию n элементов, что для char инициализирует нулём. Но можно сделать свою обёртку для char (или опять же взять из буста).

На самом деле я немного смешал разные проблемы, как избежать забиванием нулей это один вопрос. Брать std::vector и std::array вместо си ужасов это другой вопрос, и третий вопрос это взять готовую абстракцию для помеси array и vector.

апд. как раз вектор делает value инициализацию, а не default - запутался в этой идиотской терминологии

Даже самый банальный std::string имеет такую оптимизацию: небольшие строки размещаются на стеке, а большие - в куче. Можно было бы это использовать ну или скопипастить код и поправить под свои задачи.

В std:string на порядок меньше (чем 512 в примере) елементов на стеке. Зависит от реализации, но std::string использует управляющий блок (ptr + size + capacity) чтобы хранить в нём котроткие строки. Это даёт грубо говоря максимум 3 * 8 байт, но посколько что-то всё таки надо хранить для управления, то в gcc выходит 15 байт.
Поэтому копировать оттуда реализацию нету никакого смысла.

Вспомнилась статья о том, как отличить сишника от плюсовика :)

в куске кода как минимум 2 потенциальные утечки

на 512 и более байт:

//...
message_buf = std::malloc
message_len = FormatLogMessageForDisplay
//...
if (message_len <= 0)
    return;

и 2048 и более байт:

//...
wmessage_buf = std::malloc
wmessage_buflen = MultiByteToWideChar
//...
if (wmessage_buflen <= 0)
    return;

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

Ручное управление памятью + несколько return. (Жаль что goto отменили). Что может пойти не так?

В первом случае утечки не будет: если if ((message_len = FormatLogMessageForDisplay( ... вернет значение <= 0, то malloc не отработает и освобождать ничего не нужно.


Во втором случае — да, действительно может быть утечка, если wmessage_buflen = MultiByteToWideChar( вернет 0. Кстати, MultiByteToWideChar(...) по документации не может вернуть отрицательное число.

message_len = FormatLogMessageForDisplay вызывается дважды в коде до malloc и после.

wmessage_buflenтам 3 присваивания :
1)int wmessage_buflen = countof(wbuf) - 1; // wmessage_buflen==511
2)wmessage_buflen = message_len; //если message_len<=0 то сюда точно не дойдёт
3)wmessage_buflen = MultiByteToWideChar

так зачем нужна проверка после MultiByteToWideChar , если по документации не может вернуть отрицательное число или 0?

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


MultiByteToWideChar может вернуть 0, я говорил только, что не может вернуть отрицательное число.


Хотя согласен — это опасный стиль программирования, и потенциально приводит к ошибкам.

Там в середине под условием есть динамическое выделение памяти под сообщение функцией malloc.
Вам, наверное, интересно, что это за malloc и откуда он взялся.

Не интересно, совсем. Если в коде есть

wchar_t wbuf[512];
...
std::free(wbuf);

то это баг, независимо от того, что там за malloc и что там за условия.
Sign up to leave a comment.