ИУП: интенсив 7 дней + диагностический пакет (32 вопроса, 9 задач с автопроверкой)

This commit is contained in:
Kodlo-chan
2026-09-23 16:05:09 +07:00
commit 4cd63b3d4d
40 changed files with 2464 additions and 0 deletions
+20
View File
@@ -0,0 +1,20 @@
Задача 09 — разбор падения.
1. Дефекты (сколько и какие):
- ...
- ...
2. Сборка и первые шаги:
$ g++ -g -O0 -fsanitize=address,undefined crash.c -o crash
$ ./crash world
<что вывел ASAN — своими словами>
3. Команды gdb по шагам и что они показали:
(gdb) ...
...
4. Почему программа падала именно так (механизм):
...
5. Что изменено в crash.c (минимальные правки):
...
+21
View File
@@ -0,0 +1,21 @@
/* Задача 09: программа с дефектами. Починить минимально. */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char **argv) {
const char *word = argc > 1 ? argv[1] : "hello";
size_t n = strlen(word);
char *buf = malloc(n);
if (!buf) {
return 2;
}
strcpy(buf, word);
printf("len=%zu\n", strlen(buf));
free(buf);
free(buf);
return 0;
}
+23
View File
@@ -0,0 +1,23 @@
# Задача 09 — отладка: найти и исправить дефекты (gdb)
В `crash.c` лежит программа, которая падает на части входов и портит память.
Задача — не переписать её с нуля, а **найти дефекты отладчиком и починить минимально**.
Ожидаемое поведение после починки:
- `./crash` (без аргумента) печатает `len=5` и завершается с кодом 0;
- `./crash <слово>` печатает `len=<длина слова>` и завершается с кодом 0;
- `./crash ""` печатает `len=0` и завершается с кодом 0;
- сборка с `-fsanitize=address,undefined` не даёт ни одного сообщения об ошибке.
Что сделать:
1. Собрать с отладочной информацией и санитайзерами:
`gcc -g -O0 -fsanitize=address,undefined crash.c -o crash`
2. Разобраться, что именно портит память, а что приводит к падению при выходе.
Полезно: `gdb ./crash`, `run`, `bt`, `frame`, `info locals`, `watch`.
3. Исправить `crash.c` (минимальные правки, стиль сохранить).
4. Заполнить `answer.txt`: сколько дефектов нашёл, какие именно, какими командами
отладчика это подтвердил (по шагам), почему падало именно так.
Проверка: `python3 grade.py 09` — компилирует `crash.c` (компилятор C, gcc) с ASAN/UBSAN
и прогоняет 5 входов.
`answer.txt` проверяется ревью (это часть оценки: важен ход разбора, а не только результат).
+66
View File
@@ -0,0 +1,66 @@
#!/usr/bin/env python3
"""Тест задачи 09: сборка crash.c с ASAN/UBSAN и прогон входов."""
import os
import subprocess
import sys
HERE = os.path.dirname(os.path.abspath(__file__))
SRC = os.path.join(HERE, "crash.c")
BIN = os.path.join(HERE, "crash_checked")
failures = 0
def check(cond, name, extra=""):
global failures
if cond:
print(f"ok {name}")
else:
print(f"FAIL {name} {extra}")
failures += 1
def main():
r = subprocess.run(["gcc", "-g", "-O1", "-Wall", "-Wextra",
"-fsanitize=address,undefined", "-fno-omit-frame-pointer",
SRC, "-o", BIN], capture_output=True, text=True, timeout=180)
check(r.returncode == 0, "сборка с ASAN/UBSAN прошла", r.stderr[:800])
if r.returncode != 0:
print("\nFAILURES: 1")
sys.exit(1)
cases = [
([], "len=5"),
(["world"], "len=5"),
(["a"], "len=1"),
([""], "len=0"),
(["x" * 300], "len=300"),
]
for args, expect in cases:
try:
run = subprocess.run([BIN] + args, capture_output=True, text=True, timeout=60,
env={**os.environ, "ASAN_OPTIONS": "detect_leaks=1"})
except subprocess.TimeoutExpired:
check(False, f"вход {args or '<нет>'}: завершился за 60 c")
continue
out = run.stdout.strip()
err = run.stderr
label = f"вход {args[0][:12]!r}" if args else "вход без аргумента"
check(run.returncode == 0, f"{label}: код возврата 0 (получен {run.returncode})")
check(out == expect, f"{label}: вывод {expect!r} (получено {out!r})")
check("AddressSanitizer" not in err and "runtime error" not in err,
f"{label}: санитайзеры молчат", err[:400].replace("\n", " | "))
# answer.txt заполнен (проверка на «не оставил заготовку»)
apath = os.path.join(HERE, "answer.txt")
if os.path.exists(apath):
txt = open(apath, encoding="utf-8").read()
check("..." not in txt and len(txt) > 400, "answer.txt заполнен разбором (ревью отдельно)")
else:
check(False, "answer.txt: файл с разбором не найден")
print(f"\n{'FAILURES: %d' % failures if failures else 'ALL PASS'}")
sys.exit(1 if failures else 0)
if __name__ == "__main__":
main()