Реализация обратных вызовов в 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, чтобы улучшить свои навыки.

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