Opened 5 years ago

Closed 4 years ago

#431 closed ожидается проверка (задача сдана)

WW#4

Reported by: berbat.georgiy Owned by: Артур Гулецкий (huletski)
Component: WW_mergesort Version: 3.0
Keywords: Cc:

Description

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

Change History (7)

comment:1 Changed 5 years ago by Артур Гулецкий (huletski)

Type: ожидается проверкаожидаются исправления

Тесты частично проходят -> +8.

То есть ещё можно получить баллы за эту лабу?

Да, только для этого надо будет ответить на пару вопросов ниже.

Вопросы:
1) main.c:8 - зачем нужно ключевое слово static именно перед этой функцией?
2) main.c:8 - почему единый компаратор для int и char будет работать?
3) как у вас был построен процесс работы над решением, при котором получилось такое обилие комментариев?

Замечания:

  • нарушен стиль отступов -> -1;
  • memcpy использовать было запрещено, в решении она вызывается (mergesort.c:14) -> -2;
  • не соблюдается единый стиль именования переменных (где-то snake_case, где-то camelCase) -> -0.5;
  • на стеке массивы переменного размера лучше не заводить, т.к. в общем случае памяти на стеке может не хватить.

Итог: 4.5, доделывайте. Также жду ответов на вопросы.

comment:2 Changed 5 years ago by berbat.georgiy

Type: ожидаются исправленияожидается проверка
Version: 1.02.0

1)Да, static, там действительно не нужен - у меня больше нигде и не используется эта функция,
кроме как в main, поэтому "скрывать" её словом static смысла не было.
2)Изначально это был компаратор только для char, и я подумал, что раз const char* это указатель
на последовательность символов в памяти, а функция всё равно принимает const void*, поэтому почему
бы не попробовать сравнивать ей и int'ы. На нескольких тестах прошло, поэтому так и оставил.
Для себя объяснил сейчас это тем, что, видимо, происходило какое-то приведение типов и отсюда неточность.
Сейчас вижу, что не для всех чисел типа int это работает корректно, поэтому сделал аналогичный для int.
3)Очень долго не мог понять, почему не происходило сортировки введёных значений.
Программа просто выводила массив в том же виде, в каком он был заполнен изначально.
Одногруппник посоветовал просто закомментировать каждую строку программы, даже в самых очевидных местах, сказал, это поможет найти ошибку. Помогло.

Что сделано:
Привел именование переменных к одному виду, написал реализацию memcpy по сигнатуре из стандарта языка си, разделил компаратор, и сортировка типа int теперь работает корректно.

comment:3 Changed 5 years ago by Артур Гулецкий (huletski)

Type: ожидается проверкаожидаются исправления

2) main.c:8 - почему единый компаратор для int и char будет работать?

2)Изначально это был компаратор только для char, и я подумал, что раз const char* это указатель на последовательность символов в памяти, а функция всё равно принимает const void*, поэтому почему бы не попробовать сравнивать ей и int'ы. На нескольких тестах прошло, поэтому так и оставил. Для себя объяснил сейчас это тем, что, видимо, происходило какое-то приведение типов и отсюда неточность.

Чтобы так работало, вам надо было написать memcmp условный, а так вы сравнивали младшие байты двух интов.

3) как у вас был построен процесс работы над решением, при котором получилось такое обилие комментариев?

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

Похоже на rubber duck debugging. Альтернативый метод - идти от простого к сложному: написали простой вариант функциональности (e.g. сортировку пузырьком, использование захардкоженногo массива), проверили что работает, усложнили (последовательно реализовали и проверили считывание данных из аргументов и mergesort). Это бы избавило вас от поиска бага в непонятном месте, так как изменения были бы более атомарными.


Теперь тесты работают -> +10.

Замечания:

  • единый стиль отступов не соблюдается -> -1;
  • имена переменных надо чинить и в main.c -> -0.5;
  • раз надо изменять main.c, то сделайте еще так, чтобы содержимое сортируемого массива хранилось не на стеке как сейчас (e.g. arrINT), а в динамической памяти -> -0.5.

Итог: 8, доделывайте.

comment:4 Changed 5 years ago by berbat.georgiy

Type: ожидаются исправленияожидается проверка
Version: 2.03.0

Привёл переменные в main к одному виду. Попытался что-то сделать с отступами. Сделал динамическое выделение памяти. Вроде для строк слишком много теперь памяти выделяется, но это же не проблема?

comment:5 Changed 5 years ago by Артур Гулецкий (huletski)

Type: ожидается проверкаожидаются исправления

Теперь освобождается не вся память, выделенная под строки:

{lab_04}[2008]$ valgrind ./lab_04 str ab cd
==3059== Memcheck, a memory error detector
==3059== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==3059== Using Valgrind-3.11.0 and LibVEX; rerun with -h for copyright info
==3059== Command: ./lab_04 str ab cd
==3059== 
ab cd
==3059== 
==3059== HEAP SUMMARY:
==3059==     in use at exit: 100 bytes in 2 blocks
==3059==   total heap usage: 6 allocs, 4 frees, 1,156 bytes allocated
==3059== 
==3059== LEAK SUMMARY:
==3059==    definitely lost: 100 bytes in 2 blocks
==3059==    indirectly lost: 0 bytes in 0 blocks
==3059==      possibly lost: 0 bytes in 0 blocks
==3059==    still reachable: 0 bytes in 0 blocks
==3059==         suppressed: 0 bytes in 0 blocks
==3059== Rerun with --leak-check=full to see details of leaked memory
==3059== 
==3059== For counts of detected and suppressed errors, rerun with: -v
==3059== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)

Нужно починить:

  • утечку памяти;
  • добавить include guard в mergesort.h;
  • стиль отступов все еще (кое-где табы).

Вроде для строк слишком много теперь памяти выделяется, но это же не проблема?

Выделяется память по 50 символов на каждую строку. Почему не больше или меньше? Если вы решили копировать содержимое строк (чего делать не нужно, храните указатели на элементы argv), можно выделять ровно столько памяти, сколько требуется для хранения строке (strlen(s) + 1).

И как обычно вопрос: что происходит в main.c:74?

Баллы остаются без изменений, доделывайте.

comment:6 Changed 4 years ago by berbat.georgiy

Type: ожидаются исправленияожидается проверка

что происходит в main.c:74?

По указателям на аргументы командной строки считываю вводимые строки, которое, кстати, являются аргументами командной строки за счёт того, что разделены пробелом, в массив строк. Собственно, то же самое происходит и с int'ами в в main.c:45, только с преобразованием из const char* в int.

Убрал обособленное выделение памяти для каждой строки, вроде, памяти, выделенной на массив строк, достаточно. Теперь её не надо освобождать. Valgrind всё ещё выдаёт ошибку adress 0x0 is not stack'd, malloc'd or free'd. Всё ещё не понимаю, как её можно устранить.

comment:7 in reply to:  6 Changed 4 years ago by Артур Гулецкий (huletski)

Resolution: задача сдана
Status: assignedclosed

Replying to berbat.georgiy:

что происходит в main.c:74?

По указателям на аргументы командной строки считываю вводимые строки, которое, кстати, являются аргументами командной строки за счёт того, что разделены пробелом, в массив строк. Собственно, то же самое происходит и с int'ами в в main.c:45, только с преобразованием из const char* в int.

Было ощущение, что в прошлой версии = использовалось для копирования содержимого строки (как для int'ов). Надеюсь, вы понимаете, что это этого не происходит, т.к. копируется значение указателя.

Убрал обособленное выделение памяти для каждой строки, вроде, памяти, выделенной на массив строк, достаточно. Теперь её не надо освобождать. Valgrind всё ещё выдаёт ошибку adress 0x0 is not stack'd, malloc'd or free'd. Всё ещё не понимаю, как её можно устранить.

На каких данных выдает? На данных str ab cd работает нормально. Если все еще падает - напишите мне письмо с примеров ввода.


Тесты прошли -> +10.

Основные замечания:

  • include guard не починили -> -1;
  • отступы не починили (main.c:23 - два пробела, main.c:29 - табы) -> -1;
  • результат вызова malloc нужно и в main.c проверять;
  • два выделения памяти на вызов merge. Можно было выделить один большой блок памяти и установить указатель на второй подмассив в его середину (сразу после конца памяти под элементы левого).

--
Итог: все те же 8.

Note: See TracTickets for help on using tickets.