Изучение C на управляемых ОО языках - PullRequest
6 голосов
/ 22 сентября 2010

Я довольно комфортно программирую на таких языках, как Java и C #, но мне нужно использовать C для проекта (из-за низкоуровневых вызовов API OS), и у меня возникают трудности с указателями и управлением памятью (как видно * 1001) * здесь )

Сейчас я в основном набираю код и передаю его компилятору, чтобы посмотреть, работает ли он. Это просто не подходит мне. Может ли кто-нибудь указать мне хорошие ресурсы для понимания указателей и управления памятью из управляемых языков?

Ответы [ 5 ]

5 голосов
/ 22 сентября 2010
3 голосов
/ 22 сентября 2010

Один из хороших ресурсов, которые вы уже нашли, ТАК.

Конечно, вы компилируете со всеми предупреждениями, не так ли?

Обучение в процессе работы во многом зависит от качества вашего компилятора и предупреждений / ошибок, которые он передает вам.Лучшее в этом отношении, что я нашел в мире Linux / POSIX - это clang .Приятно отслеживает происхождение ошибок и довольно хорошо сообщает вам об отсутствующих заголовочных файлах.

1 голос
/ 22 сентября 2010

Язык Си не делает ничего, о чем вы явно не говорите.

Нет автоматически вызываемых деструкторов, и это хорошо и плохо (поскольку ошибки в деструкторах могут бытьболь).

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

if (var = malloc(SIZE)) {  // try to keep this line
     use_var(var);
     free(var);  // and this line close and with easy to comprehend code between them
} else {
     error_action();
}
return; // try to limit the number of return statements so that you can ensure resources
       // are freed for all code paths

Попытка сделать ваш код таким, насколько это возможно, поможет, хотя это не всегда возможно.

Хорошей идеей является создание набора макросов или встроенных функций, которые инициализируют ваши объекты.Также создайте другой набор функций, которые выделяют память ваших объектов и передают ее функциям инициализатора.Это позволяет легко инициализировать как локальные, так и динамически размещенные объекты.Подобные операции для деструктороподобных функций также являются хорошей идеей.

Использование методов ОО является хорошей практикой во многих случаях, и для этого в C просто требуется немного больше ввода (но обеспечивает больший контроль).Путтеры, геттеры и другие вспомогательные функции могут помочь поддерживать объекты в согласованных состояниях и уменьшить изменения, которые необходимо внести при обнаружении ошибки, если вы можете сохранить интерфейс таким же.

Вам также следует обратить внимание наperror функция и errno "variabl".

Обычно вы хотите избегать использования каких-либо подобных исключений в C. Я обычно стараюсь избегать их и в C ++, и использую их только для действительно плохихошибки - те, которые не должны происходить.Одна из главных причин их избегания заключается в том, что в C не существует магических вызовов деструкторов, поэтому нелокальные GOTO часто будут пропускать (или иным образом портить) некоторый тип ресурса.При этом в C есть вещи, которые предоставляют аналогичные функциональные возможности.

Основным исключением, как механизм в C, являются функции setjmp и longjmp.setjmp вызывается из одного места в коде и передается (непрозрачная) переменная (jmp_buf), которая позже может быть передана в longjmp.Когда выполняется вызов longjmp, он фактически не возвращается к вызывающей стороне, а возвращается как ранее вызванный setjmp с этим jmp_buf.setjmp вернет значение, указанное при вызове longjmp.Обычные вызовы setjmp возвращают 0.

Другое исключение, например, функциональность, зависит от платформы, но включает сигналы (которые имеют свои собственные ошибки).

Другие вещи, на которые следует обратить внимание:

Макрос assert, который можно использовать для завершения программы при сбое параметра (некоторого логического теста).Звонки на номер assert исчезают, когда вы #define NDEBUG перед вами #include <assert.h>, поэтому после тестирования вы можете легко удалить утверждения.Это действительно хорошо для тестирования указателей NULL перед их разыменованием, а также некоторых других условий.Если условие не выполнено, assert пытается напечатать имя исходного файла и номер строки неудачного теста.

Функция abort вызывает сбой программы, не выполняя всю очистку этого вызова exit делает.Это может быть сделано с помощью сигнала на некоторых платформах.assert звонки abort.

1 голос
/ 22 сентября 2010

Научитесь использовать gdb для пошагового выполнения кода и вывода значений переменных (скомпилируйте с -g для включения символов отладки).

Используйте valgrind для проверки на утечки памяти и другие связанные с этим проблемы (например, повреждение кучи).

1 голос
/ 22 сентября 2010

Несколько советов:

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

    Integer i = new Integer();
    
    i=5;
    

есть

int *p;

p=malloc(sizeof(int));

*p=5;
  • Выделение памяти (malloc) может завершиться ошибкой, поэтому проверьте указатель на ноль, прежде чем использовать его.
  • Функции ОС могут не работать, и это может быть обнаружено по возвращаемым значениям.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...