Реализация обратных вызовов в C

CBeginner
Практиковаться сейчас

Введение

В этом проекте вы научитесь реализовывать обратный вызов (callback) функцию на языке C. Обратные вызовы - это мощный метод в программировании на C, особенно в контексте разработки Linux-систем, где они широко используются.

👀 Предварительный просмотр

$ gcc test_callback.c callback.c -o test_callback
$./test_callback
Alarm1:0
Alarm2:1
Alarm3:2

🎯 Задачи

В этом проекте вы научитесь:

  • определять и использовать обратные вызовы в C;
  • регистрировать и запускать будильники с использованием обратной вызов функции;
  • обрабатывать крайние случаи и ошибки в реализации обратной вызов функции.

🏆 Достижения

После завершения этого проекта вы сможете:

  • понять концепцию обратных вызовов и их использование в программировании на C;
  • реализовать систему будильников на основе обратных вызовов, включая регистрацию и запуск будильников;
  • писать надежный и защищенный код для обработки потенциальных проблем в обратной вызов функции;
  • применить свои знания о обратных вызовах в других областях программировании на C, таких как событийно-ориентированные системы или асинхронные операции.

Разобраться с обратной вызов функцией

В этом шаге вы узнаете о концепции обратных вызовов в языке C и о том, как они используются в разработке Linux-приложений на C.

Обратные вызовы - это способ передачи функции в качестве аргумента другой функции, которая впоследствии может вызвать переданную функцию позднее. Это мощный метод, позволяющий создавать более гибкий и модульный код.

В коде, представленном в файле callback.c, обратная вызов функция используется для реализации системы будильников. Структура alarm представляет будильник, а функция register_alarm используется для регистрации будильника. Затем функция hit_alarm используется для запуска зарегистрированных будильников.

✨ Проверить решение и практиковаться

Идентифицировать и исправить дефекты

Теперь давайте взглянем на предоставленный код в файле callback.c и исправим дефекты.

  1. Сегментация: Вероятно, это происходит потому, что alarm_list не заполняется или не доступается правильно, что приводит к несанкционированному доступу к памяти.
  2. Неправильная обработка индекса в register_alarm: Переменная index локальна для register_alarm и каждый раз, когда функция вызывается, инициализируется заново до 0. Это заставляет регистрировать все будильники с индексом 1, перезаписывая друг друга.

Обновите файл callback.c следующим образом:

#include "callback.h"

alarm alarm_list[MAX_ALARMS];
int current_index = 0; // Глобальный трекер индекса

void register_alarm(alarm a) {
    if (current_index < MAX_ALARMS) {
        alarm_list[current_index] = a;
        current_index++;
    }
    // Если количество зарегистрированных будильников превышает MAX_ALARMS, ничего не делать (не сообщать об ошибке)
}

int hit_alarm(int index) {
    if (index < 0 || index >= MAX_ALARMS ||!alarm_list[index])
        return 1;
    (*alarm_list[index])(index);
    return 0;
}

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

  1. Добавлена глобальная переменная current_index для отслеживания текущего индекса для регистрации будильников.
  2. В register_alarm мы проверяем, меньше ли current_index чем MAX_ALARMS, перед регистрацией будильника. Если количество зарегистрированных будильников превышает MAX_ALARMS, мы не сообщаем об ошибке и просто продолжаем.
  3. В hit_alarm мы добавили дополнительные проверки, чтобы убедиться, что индекс находится в допустимом диапазоне и что на этом индексе на самом деле зарегистрирован будильник. Если нет, мы возвращаем 1, чтобы показать, что ни один будильник не был активирован.
✨ Проверить решение и практиковаться

Тестировать обратную вызов функцию

Теперь, когда мы исправили дефекты в файле callback.c, давайте протестируем обратную вызов функцию, запустив предоставленную программу test_callback.c.

Скомпилируйте программу:

gcc test_callback.c callback.c -o test_callback

Запустите программу:

./test_callback

Вывод:

Alarm1:0
Alarm2:1
Alarm3:2

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

Поздравляем! Вы успешно отлажили и исправили реализацию обратной вызов функции.

✨ Проверить решение и практиковаться

Резюме

Поздравляем! Вы завершили этот проект. Вы можете практиковаться в более лабораториях в LabEx, чтобы улучшить свои навыки.