Как я могу поддерживать корреляцию между определениями конструкций и их кодом построения / разрушения? - PullRequest
2 голосов
/ 28 июня 2019

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

Я пытаюсь сохранить симметрию в коде, где вещи одного типа структурированы и названы аналогичным образом, что работает для сопоставления кодов Construct () и Deconstruct () , но структуры определены в отдельныхфайлы, которые я не могу выровнять их определения с функциями .

Вопрос: есть ли способ через кодирование, чтобы я больше осознавал, что я (или кто-то еще) изменил структуруи функции нуждаются в обновлении?

Усилия:

Простое:

- Улучшена организация кода, чтобы помочь минимизировать проблему

- Работал, чтобы привыкнуть обновлять все сразу

- Использовал комментарии для документирования членов структуры, но это справедливоt означает, что в результате получится дублирование

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

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

Самая эффективная вещь, которую я придумал, это использовать утверждение времени компиляции:

static_assert(sizeof(struct Foobar) == 128, "Foobar structure size changed, reevaluate construct and destroy functions");

Это довольно хорошо, определенно достаточно хорошо.Я не против обновления константы при изменении структуры.К сожалению, утверждения времени компиляции очень зависят от платформы (компилятора) и стандарта C, и я пытаюсь поддерживать обратную и межплатформенную совместимость моего кода.

Это хорошая ссылка в отношении утверждений времени компиляции C:

http://www.pixelbeat.org/programming/gcc/static_assert.html

Редактировать:

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

Это похоже на взломанный способ заставить язык служить моей непреднамеренной цели, а это не то, чего я хочу.Я хочу быть профессионалом.Если профессиональная практика не направлена ​​на решение этой проблемы поддерживаемости кода, то это ответ.

Ответы [ 2 ]

2 голосов
/ 28 июня 2019

Я программирую на C почти 40 лет, и я не знаю хорошего решения этой проблемы.

В некоторых кругах популярно использовать набор тщательно продуманных определений макросов.так что вы можете написать структуру один раз, не как прямое объявление структуры C, а как последовательность этих макросов, а затем, определив макрос по-разному и повторно развернув его, превратите свое «определение» в либо объявление, либо определение, либоинициализация.Лично я чувствую, что эти методы слишком запутанные и приносят больше хлопот, чем они того стоят, но их можно использовать для достойного эффекта.

В противном случае единственное решение - хотя это не то, что вы ищетеfor - это «Будьте осторожны».

В идеальном проекте (хотя я прекрасно понимаю, что такого нет) вы можете сначала определить свои структуры данных, а затем потратить оставшееся время на написание и отладкукод, который использует их.Если вам никогда не доводилось добавлять поля в структуры, то, очевидно, у вас не возникнет этой проблемы.(Извините, если это звучит как шутливый или бесполезный комментарий, но я думаю, что это одна из причин того, что я, как и @CoffeeTableEspresso, упомянутый в комментарии, на практике не испытываю слишком много подобных проблем.)

Возможно, стоит отметить, что C ++ имеет более или менее ту же проблему.Моя самая большая особенность пожеланий в C ++ всегда заключалась в том, что можно было бы инициализировать членов класса в объявлении класса.(На самом деле, я думаю, что я слышал, что недавний пересмотр стандарта C ++ позволяет это сделать - в этом случае другой не обязательно полезный ответ на ваш вопрос - «Используйте вместо C ++».)

1 голос
/ 28 июня 2019

C не позволяет вам иметь мягкие struct переопределения, но он позволяет вам иметь мягкие макро переопределения.

Так что, пока вы

  1. сохранить тело структуры в макросе (согласно фиксированному соглашению об именах)
  2. переопределить макрос в точке вашего конструктора

вы получите предупреждение, если structтело изменяется, и вы не обновили соответствующий конструктор.

Пример:

header.h:

#define MC_foo_bod  \
    int x; \
    double y; \
    void *p
struct foo{ MC_foo_bod; };

foo__init.c

#include "header.h"

#ifdef MC_foo_bod
    //try for a silent redefinition
    //if it wasn't silent, the macro changed and so should this code
    #define MC_foo_bod  \
        int x; \
        double y; \
        void *p
#else
    #error "" 
    //oops--not a redefinition
    //perhaps a typo in the macro name or a failure to include the header?
#endif
void foo__init(struct foo*X)
{
    //...
}
...