Избегайте неоправданных ограничений на длину или количество любых структур данных, включая имена файлов, строки, файлы, символы, отводя память для всех таких структур динамически. Во многих Unix-утилитах "длинные строки по-тихому обрезаются". Это неприемлемо для GNU-утилит.
Программы, которые читают файлы, не должны выкидывать символы NUL, или какие-либо другие непечатные символы, включая те из них, которые имеют код, больший чем 0177. Исключение составляют утилиты, специально предназначенные для работы с некоторыми типами принтеров, которые не могут обрабатывать такие символы.
Выполняйте проверку кода завершения для каждого системного вызова, кроме случаев, когда Вы уверены, что хотите игнорировать ошибки. Включайте текст системного сообщения об ошибке (из perror или эквивалентной функции) в каждое сообщение об ошибке, вызванное исполнением системного вызова с неуспешным кодом завершения, а так же имя файла (если ошибка связана с каким-то файлом) и имя программы. Сообщения вроде "cannot open foo.c" или "stat failed" недостаточно.
Проверяйте каждый вызов malloc или realloc на возвращение нулевого результата. Проверяйте результат realloc даже в том случае, если Вы уменьшаете размер блока; в системах, которые округляют размеры блоков до степени 2, realloc может выделить новый блок, если Вы указали меньший размер.
В Unix-системах realloc может разрушить блок памяти если он вернул нулевое значение. GNU-реализация realloc не допускает такой ошибки: если выполнение этой функции невозможно, то исходный блок остается неизменным. Можете считать, что эта ошибка исправлена. Если Вы желаете выполнять Вашу программу на Unix, и хотите избежать неприятностей в этом случае, воспользуйтесь GNU-malloc.
Вы должны считать, что free изменяет содержимое блока, который освобождается. Все, что Вы хотите выбрать из блока, нужно выбирать до вызова free.
Используйте getopt_long для разбора аргументов, конечно если синтаксис аргументов не делает использование этой функции нецелесообразным.
Если Вы выполняете запись в статические переменные во время исполнения программы, используйте явный C-код для их инициализации. Оставьте описания с инициализатором для данных, которые не изменяются.
Старайтесь избегать использования низкоуровневых интерфейсов, позволяющих добраться до структур данных Unix (таких, как структуры каталогов, utmp или разметку памяти ядра), поскольку вероятнее всего это не будет совместимым. Если Вам нужно найти все файлы в каталоге, используйте readdir или какой-то другой высокоуровневый интерфейс. Это позволит поддерживать совместимость с GNU.
По умолчанию, GNU-система должна предоставлять функции обработки сигналов в BSD и в POSIX. GNU-программы должны писаться с учетом этого.
В проверках на ошибки, которые обнаруживают невозможные условия, следует просто прерывать исполнение. Обычно здесь не надо печатать никаких сообщений. Эти проверки показывают наличие ошибок. Если кто-то захочет исправить ошибку, пусть он прочитает исходный текст и запустит отладчик. Объясните лучше проблему в комментариях к исходному тексту. Соответствующие данные должны быть переменных, которые можно просто просмотреть с помощью отладчика, так что не надо пересылать их куда-либо еще.