Comments 26
Автор кода хотел поумничать, и нагородил лажу вместо того, чтобы идиоматично написать +1 в аргументе malloc'а. Что тут красивого?
Притаившаяся ошибка. :)
много ли ума надо чтобы считать длинну однобайтовой строки?)
Да ладно если бы это была строка! Но объевлен-то char! Внимание вопрос - сколько же char-ов влезет в один char? Не отвечайте сразу дети, подумайте!!!
Я уж молчу что зачем-то копируют символы в цикле вместо пары memcpy, мы же здесь про ошибки, а не про оптимизацию... но блин.
Ну, вообще-то, всё правильно, если терминатор будет из двух char-ов, этот код (с sizeof) сработает верно
А заранее предусмотреть возможность не исследовать и переписывать код, просто поменяв константу -- очень правильное решение.
А что такое char? Вот в Rust - я знаю. А в Си - я, наверное, не буду умничать. Потому что мы не знаем какой именно char, и 8 там бит, или 6, или там, кто-то прихерачил половинку юникода в 16 битах...
So подсказывает:
char is always a byte , but it's not always an octet. A byte is the smallest addressable unit of memory (in most definitions), an octet is 8-bit unit of memory.
а копирование данных лучше делать memcpy(), часто это существенно эффективнее
Думаю в библиотечной функции добавленные "улучшающие" проверки неуместны, так как теперь они будут выполняться даже тогда, когда они не нужны (а чаще всего они действительно не нужны). Разве что проверку результата malloc'а можно оставить, хотя и она в обычной ситуации никогда не сработает.
Во-вторых, анализатор выдаёт несколько предупреждений на тему 64-битных ошибок.
Ну по-хорошему, надо еще детектить целочисленное переполнение, в результате которого, теоретически, будет выдан буфер меньшего размера со всеми вытекающими.char* dest_char = (char*)malloc(s1_len+s2_len+trmn_size);
Когда-то в Android было много багов при вызовах вида new T[count], где count контролировался извне. Местечковый урезанный libc (bionic) честно вызывал malloc(sizeof(T)*count), умножение переполнялась, на выходе красивое переполнение кучи.
del
Меня другое смущает: если мы делаем +sizeof('\0') вместо +1, то значит мы не уверены, что у нас sizeof(char) == 1, а если мы в этом не уверены, то маллок нам выделит недостаточно памяти даже в «исправленном» случае. Верно было бы писать что-то вроде malloc((len1+len2+1)*sizeof(char))
sizeof(char)==1
на любой архитектуре, независимо от числа битов в char
.Согласен. Поменял в статье.
Пункт 6.5.3.4 стандарта Си:
4. Whensizeof
is applied to an operand that has typechar
,unsigned char
, orsigned char
, (or a qualified version thereof) the result is 1.
Почему зря? Мне кажется, такой вариант смотрится лучше: (len1+len2+1)*sizeof(char)
. А до этого смешивалось понятие длины строк и размера терминально символа.
А зачем считать размер нуль терминатора?
Типо если подсунут жирный char?
Очень коварная ошибка.
Учитывая что malloc выровнен блоками по 8 байт, вероятность что вылезут из блока лишь 1/8. Но поскольку память распределяется страницами по 4КБ, ошибка доступа будет лишь при выходе из последнего блока страницы, вероятность что блок последний 1/512.
Итого у пользователя в среднем вылетит одна ошибка на 4096 вызовов и то лишь при условии что следующая страница всегда закрыта. Но каждые 8 вызовов может сломаться что-то другое, не столь заметное.
Красивая ошибка в реализации функции конкатенации строк