Opened 5 years ago
Closed 4 years ago
#498 closed ожидается проверка (задача сдана)
HW #1
Reported by: | lopatin.mikhail | Owned by: | Sokolov Viacheslav |
---|---|---|---|
Component: | HW #1 (BMP) | Version: | 2.0 |
Keywords: | Cc: |
Description
Change History (8)
comment:1 Changed 5 years ago by
Version: | → 1.0 |
---|
comment:2 Changed 4 years ago by
Type: | ожидается проверка → ожидаются исправления |
---|
comment:3 Changed 4 years ago by
Type: | ожидаются исправления → ожидается проверка |
---|
comment:4 Changed 4 years ago by
Version: | 1.0 → 2.0 |
---|
comment:5 Changed 4 years ago by
╰─>$ make
gcc -Wall -Wextra -Werror -fsanitize=address -g -I include -fsanitize=address -c src/main.c -o obj/main.o
gcc -Wall -Wextra -Werror -fsanitize=address -g -I include -fsanitize=address -c src/bmp.c -o obj/bmp.o
src/bmp.c: In function ‘crop’:
src/bmp.c:86:5: error: this ‘for’ clause does not guard... [-Werror=misleading-indentation]
for (int i = y; i < y + h; ++i)
src/bmp.c:89:9: note: ...this statement, but the latter is misleadingly indented as if it were guarded by the ‘for’
return crop_arr;
~
cc1: all warnings being treated as errors
Makefile:10: recipe for target 'obj/bmp.o' failed
make: * [obj/bmp.o] Error 1
comment:6 Changed 4 years ago by
Type: | ожидается проверка → ожидаются исправления |
---|
вот тут у Вас ошибка, внутрь этого цикла исполнение ни разу не зайдет
74 for (int j = h * 3; j < ostatok; ++j) {
сейчас в crop вырезается не тот кусок (картинка хранится перевернутой)
(легко проверить, попробовав вырезать угол)
если эти две проблемы поправить, программа делает то, что нужно.
Но остаются следующие проблемы:
(корректность)
При проблемах с аргументами, открытием файла, выделением памяти и прочим, программа должна корректно завершить работу и вернуть ненулевой код возврата.
1) exit из функций не позволяет освободить память, где-либо выделенную, поэтому лучше использовать коды возврата для обработки ошибок
2) не хватает проверок, что malloc возвращает не NULL
(корректность)
не реализовано
Программа обязана проверить корректность аргументов (см. консольное приложение). Достаточно проверить относительно тривиальные ошибки: выход за границы изображения и нехватку аргументов.
(стиль)
транслит - это плохо
Что может быть полезно:
- использовать short-circuit evaluation для аггрегации проблем кода возврата и стройной логики программы без if(неудача) return 1; (позволит реже делать проверки)
- завести струтуру BMP, в которой хранятся как значения rgb, так и весь заголовок
- пересчитывать значения в заголовке (4 штуки) при каждой операции crop/rotate
последнее можно считать относящимся к стилю (это архитектура программы, сейчас она решает поставленную задачу, но если бы это была библиотека, ей было бы неудобно пользоваться)
Также исходное изображение можно освобождать раньше, уже после crop оно не нужно
Главное, чтобы в финальную попытку работал основной функционал, все остальное не так важно.
comment:7 Changed 4 years ago by
Type: | ожидаются исправления → ожидается проверка |
---|
comment:8 Changed 4 years ago by
Resolution: | → задача сдана |
---|---|
Status: | assigned → closed |
Код освобождения памяти дублируется, его стоило бы вынести в отдельную функцию.
Не проверяется неотрицательность аргументов x,y,w,h
В save_bmp не хватает return 0, из-за этого код возврата программы всегда -1
load_bmp, crop, rotate:
если первая аллокация памяти не удалась, будет разыменование нулевого указателя.
Нет проверок, что последующие аллокации (w или h штук) произошли успешно, если это не так, программа аварийно завершится, потому что в дальнейшем эти указатели разыменуются.
biHeight - h - y стоило бы вынести в переменную, это упростило бы восприятие кода
вместо remainder (которое может быть воспринято как остаток от деления) стоило бы использовать слово alignment / padding
89 int k = 3 - j % 3;
90 int t = 3 * (h - i) - k;
если что-то - нетривиальный счетчик, лучше дать этой сущности говорящее название, чтобы читателю не приходилось догадаываться, что же это такое
вычисление значения padding-а стоило бы вынести в отделньную функцию, оно много раз дублируется
save_bmp:
64 check = 0;
эту строчку можно удалить
67 fclose(file);
это можно было бы делать после Error:
48 memcpy(header + 2,&bfSize, 4);
49 memcpy(header + 18,&biWidth, 4);
50 memcpy(header + 22,&biHeight, 4);
51 memcpy(header + 34,&biSizeImage, 4);
константы 2, 18, 22, 34, 54 стоило бы именовать
отсутствует проверка контрактов
Makefile
не хватает зависимости obj/main.o от include/bmp.h
Лучше не использовать транслитерацию в комментариях - пишите их на английском или кириллицей (все равно же для русскоговорящего); возможно, у Вас есть какое-то техническое ограничение, о котором я не знаю.
Сейчас get_int / print_int реализованы некорректно
Кажется, можно просто
а size все равно нужен только 4
После изменения изображения нужно обновить biSizeImage
save_bmp: файл следует открывать в режиме write, а не append (если файл уже есть, его нужно удалить, а не пытаться дописывать в конец) - "wb"
По Стандарту запрещены массивы нулевой длины
30 uint8_t end_pix_write[amount];
здесь amount может быть 0
valgrind ругается на следующее:
в final_arr есть область памяти, которая никак не инициализирована, но из нее производится чтение (в rotate это соответствует случаю
if (k == 0) k = 3;
- отсюда видно, какая именно область памяти останется пустой, k не бывает 0)можно, например, с помощью memset изначально проинициализировать все 0.
Но из-за этого же if-а происходит запись в 3 + 3 * (y - 1), то есть 3 * h - за пределы выделенной памяти.
Общий комментарий:
Сейчас не выполняется требование
стоит его реализовать
Также стоит лучше организовать декомпозицию - в main очень много знания о том, как именно представлено изображение, стоит как минимум убрать это знание из main. Оптимально, если main выполняет только следующие действия:
Также пока что именование не очень удачное - в разных местах программы одно и то же может именоваться разным образом (как в случае h/y) или наоборот одинаковое имя может соответствовать разным сущностям (output_bmp это массив пикселей, а out_bmp это имя файла).
Может быть удобно использовать структуры для хранения и передачи информации между разными блоками кода. Также может быть удобно использовать
attribute((packed)) / https://stackoverflow.com/questions/3318410/pragma-pack-effect для того, чтобы гарантировать желаемое выравнивание структуры (тогда можно будет ее читать с помощью fread напрямую из файла - так удобно поступить с заголовками).
Пока что в текущем состоянии будет мало баллов и за стиль, и за содержание. Если нужна подсказка / расшифровка / более развернутый комментарий - обращайтесь.