Как сделать defer в C через cleanup-паттерн
В Go есть `defer`. В C - нет. Но это не значит, что нельзя получить тот же эффект.
Главная проблема в C - ресурсы:
- забыли закрыть файл
- не освободили память
- не закрыли сокет
- утечки и баги в error-path
Хитрый приём - использовать единый блок очистки через `goto cleanup`. Это самый надёжный способ имитировать defer в C.
Идея:
- ресурсы выделяются по шагам
- при ошибке — переход в cleanup
- в конце — освобождаем всё в одном месте
Так код становится безопаснее и проще для поддержки.
Пример:
Почему это хороший паттерн:
- нет дублирования освобождения ресурсов
- все error-path’ы безопасны
- легко добавлять новые ресурсы
- стандартная практика в системном C (ядро Linux использует тот же подход)
Главная идея: в C «defer» — это дисциплина структуры кода.
https://antonz.org/defer-in-c/
В Go есть `defer`. В C - нет. Но это не значит, что нельзя получить тот же эффект.
Главная проблема в C - ресурсы:
- забыли закрыть файл
- не освободили память
- не закрыли сокет
- утечки и баги в error-path
Хитрый приём - использовать единый блок очистки через `goto cleanup`. Это самый надёжный способ имитировать defer в C.
Идея:
- ресурсы выделяются по шагам
- при ошибке — переход в cleanup
- в конце — освобождаем всё в одном месте
Так код становится безопаснее и проще для поддержки.
Пример:
#include <stdio.h>
#include <stdlib.h>
int process_file(const char* path) {
FILE* file = NULL;
char* buffer = NULL;
int result = -1;
file = fopen(path, "r");
if (!file) goto cleanup;
buffer = malloc(1024);
if (!buffer) goto cleanup;
// работа с файлом
fread(buffer, 1, 1024, file);
result = 0; // успех
cleanup:
if (buffer) free(buffer);
if (file) fclose(file);
return result;
}
Почему это хороший паттерн:
- нет дублирования освобождения ресурсов
- все error-path’ы безопасны
- легко добавлять новые ресурсы
- стандартная практика в системном C (ядро Linux использует тот же подход)
Главная идея: в C «defer» — это дисциплина структуры кода.
https://antonz.org/defer-in-c/
❤4👍3
Языки программирования и их инструкции импорта
🐍 Python - import module
☕ Java - import package.Class;
⚡ C - #include <stdio.h>
🛠️ C++ - #include <iostream>
🌐 JavaScript - import module from "module"
🛠️ C# - using Namespace;
🐹 Go - import "package"
🦀 Rust - use crate::module;
🐘 PHP - require "file.php";
💎 Ruby - require "library"
🐪 Kotlin - import package.Class
🍎 Swift - import Module
🔷 TypeScript - import {x} from "module"
🧮 R - library(package)
🐚 Bash - source file.sh
🧱 Dart - import 'package:lib/lib.dart';
🎯 Scala - import package.Class
🐼 Groovy - import package.Class
🧠 Julia - using Module
🔧 Assembly (x86 Linux) - %include "file.inc"
🐍 Python полезные ресурсы 🚀Max
@pythonl
🐍 Python - import module
☕ Java - import package.Class;
⚡ C - #include <stdio.h>
🛠️ C++ - #include <iostream>
🌐 JavaScript - import module from "module"
🛠️ C# - using Namespace;
🐹 Go - import "package"
🦀 Rust - use crate::module;
🐘 PHP - require "file.php";
💎 Ruby - require "library"
🐪 Kotlin - import package.Class
🍎 Swift - import Module
🔷 TypeScript - import {x} from "module"
🧮 R - library(package)
🐚 Bash - source file.sh
🧱 Dart - import 'package:lib/lib.dart';
🎯 Scala - import package.Class
🐼 Groovy - import package.Class
🧠 Julia - using Module
🔧 Assembly (x86 Linux) - %include "file.inc"
🐍 Python полезные ресурсы 🚀Max
@pythonl
❤8👍1👎1