Является ли использование #include «component.c» плохой практикой или есть какое-либо нарушение стандартных правил мисры? (потенциально правило 3-3-1)
До сих пор я понимаю, что это обычно классифицируется как плохая практика, но может использоваться в определенных сценариях, будет ли это особой проблемой для приложений, критически важных с точки зрения безопасности?
Правило Misra 3-3-1 гласит, что объекты или функции с внешней связью должны быть объявлены в заголовочном файле.
Как правило, это плохая практика для всего программирования на C, а не только для MISRA. Вы используете компоновку, чтобы объединить результат компиляции отдельных файлов C.
Я не знаю, как эта практика может повысить какую-либо безопасность. Не делай этого.
Да, включение файлов .c
обычно считается плохой практикой. Однако есть очень специфические случаи, когда это может быть хорошим вариантом. В этих случаях я иногда предпочитаю давать файлу другое расширение, например. .inc
, чтобы указать, что это не отдельный .c
-файл.
MISRA C 3-3-1 не существует. Вы используете C или C++? Вам нужно знать, на каком языке программирования вы программируете, прежде чем приступать к более сложным вещам, таким как соответствие требованиям MISRA.
Что касается программирования, связанного с безопасностью, вы должны быть в состоянии привести очень веские аргументы для любого сценария, в котором вы отклоняетесь от лучших практик. Я действительно не понимаю, как вам удалось пройти проверку кода с таким аргументом, не говоря уже об утверждении типа третьей стороной.
Когда вы пишете такую программу, это называется единство сборки . Хороший пример такой программы — компилятор для языка программирования Odin. Так что это можно сделать, но, как и все остальное, есть компромиссы.
Он помещает больше источника в одну единицу перевода. Это может помочь в оптимизации, аналогично тому, как работает оптимизация времени компоновки, поскольку компилятор может фактически видеть исходный код из функций в других файлах C.
Меньше беспорядка в файлах проекта (меньше заголовков) и, следовательно, меньше повторений.
Сильно упрощенная сборка; Это может быть так же просто, как создать только один файл, даже если в проекте много файлов.
Труднее понять коллегам, которые используют более распространенные методы.
Вы больше не можете определить статическую переменную с очень общим именем в файле C, потому что этот файл C может быть частью более крупной единицы перевода. Вы получите более подробные имена переменных.
Как правило, это замедляет сборку. Системы сборки (такие как make) могут ускорить компиляцию, только перекомпилируя то, что зависит от всех изменений. Если вы объединяете вещи в единую единицу перевода, все это нужно будет создавать для каждого изменения. В большом проекте это приведет к большему потреблению памяти во время сборки.
Вы не можете распараллелить сборку.
Я на самом деле не знаю, но это не нарушает правило, которое вы опубликовали:
Правило Misra 3-3-1 гласит, что объекты или функции с внешней связью должны быть объявлены в заголовочном файле.
Включив файл C, вы больше не будете иметь внешней связи, потому что они находятся в одной и той же единице перевода.
Я никогда раньше не слышал термина «сборка единства». Я думаю, вы узнаете что-то новое каждый день. Однако, судя по описанию в Википедии, сборка единства — это конкретный вариант использования файлов .c, а не термин, описывающий практику в целом. В таком случае я не думаю, что будет правильно говорить: «Когда вы пишете такую программу, это называется сборкой единства».
Я не верю, что это жизнеспособно как единственный режим сборки. Возможно, только для выпускных сборок, где скорость инкрементальной сборки не так важна.
Это также вопрос безопасности с точки зрения того, что вы можете не захотеть предоставлять свой код, поэтому вы просто предоставляете заголовок и объектные файлы.
Не знаете, как это решает вопрос о #include
-ing файле C?
если вы #include .c файл, он вам нужен, поэтому вам нужен код, но если вы #include .h файл, вам просто нужно иметь заголовочный файл и объектный файл, чтобы дать его для ссылки.
Вы ссылаетесь на стандарт MISRA C++, а не на стандарт MISRA C. Стандартное правило MISRA C++ 3-1-1 не запрещает вам #include-ing C-файлы в другие C-файлы, потому что любой C-файл может включать один другой и ничего не объявлять как имеющее внешнюю связь. Правило/требование относится к внешней компоновке, а не к включению C-файла. Я полагаю, что если бы они добавили правило для включения других файлов C, оно было бы в разделе «Включение исходного файла» правил 16-2-X, но я только что проверил, и ничего не говорится о включении других файлов C. Лично я не возражаю против включения других файлов C, потому что я вижу #include просто как операции копирования и вставки, которые можно использовать по своему усмотрению.
Использование #include "component.c" считается плохой практикой
Вообще говоря, да.
Обычно функция включения файлов препроцессора зарезервирована для поддержки факторизации общих объявлений в их собственных файлах, чтобы их не нужно было дублировать в нескольких источниках. Такой факторинг дает огромные преимущества для удобства сопровождения во всех проектах, кроме самых маленьких, и это почти требование, чтобы библиотеки можно было использовать. Файл, содержащий только такие объявления, обычно называется «заголовком» и обычно именуется с суффиксом .h
. В этом смысле проблема частично заключается в именовании файлов и шаблонах программирования.
С другой стороны, исходные файлы C, содержащие определения функций или объектов (в отличие от объявлений), обычно именуются с суффиксом .c
. Язык C запрещает несколько внешних определений одного и того же идентификатора (функции или имени переменной) в одной и той же программе, поэтому такие .c
файлы не могут быть #include
преобразованы более чем в одну единицу перевода, участвующую в программе, и если они включены хотя бы в одну, то они также не должны компилироваться напрямую. Обычный способ создать программу из нескольких файлов .c
— это скомпилировать их независимо, а затем связать вместе.
При условии, что вы наверняка избежите дублирования определений, по своей сути нет ничего неправильного в #include
один .c
файл в другой. Но это имеет смысл только в качестве специальной договоренности. Это создает дополнительный риск и не дает особых преимуществ с точки зрения спецификации языка. Кроме того, поскольку это противоречит общепринятым правилам, это может удивить и сбить с толку разработчиков — возможно, даже более опытных в будущем.
Есть ли какое-либо нарушение стандартных правил мисры? (потенциально правило 3-3-1)
По сути, это не нарушает правило MISRA 3-3-1, но упрощает написание кода, нарушающего это правило. То есть сделать возможным иметь все необходимые внешние объявления в одном файле .c плюс его включения вместо предоставления отдельного заголовка.
Я не вижу другого правила MISRA-2012, которое нарушило бы такое включение. Но это не выдерживает никакой критики со мной в код-ревью.
Правило 3-1-1 — это правило MISRA C++:2008.
Применимыми рекомендациями MISRA C:2012 являются (вероятно) правила 20.2 и 20.3, которые не запрещают использование расширений .c
.
--
В MISRA C:2004 Правило 8.5 запрещало исходный код в заголовочном файле (предполагаемом, что это файл .h
). Это правило было удалено для MISRA C: 2012, чтобы разрешить использование функций inline
.
--
Лично я считаю, что #include
-инг .c
-файла — плохая идея — это предполагает неправильное понимание языка, компилятора и компоновщика.
Если вы сделаете это, расширенный файл будет считаться одной единицей перевода для целей анализа...
(см. профиль для принадлежности)
Да, это наихудшая практика, и она, по крайней мере, приведет к ошибкам компоновщика.