Лучшие практики для предотвращения проблем с указателями [дубликат]

При выполнении до конца ActiveControl рекурсивно, он не берет Вас к листовому управлению, которое фокусируется?

18
задан 7 revs, 3 users 82% 19 July 2012 в 15:05
поделиться

9 ответов

Что может пойти не так при неправильном использовании указателей:

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

  2. Нарушения доступа - Вы создаете указатель, который указывает на адрес памяти, к которому у вас нет доступа или который не существует. В конце концов, указатели - это просто целые числа, и ими можно манипулировать, как и любым другим числом. Когда вы попытаетесь разыменовать неверный указатель, ваша программа остановится. Дополнительная информация из Википедии.

  3. Ошибки нулевого указателя - это особый случай нарушения прав доступа. Как правильно «припарковать» указатель, чтобы он не указывал ни на что конкретное, нужно установить его значение в ноль или ноль. Попытка разыменовать нулевой указатель остановит вашу программу. Дополнительная информация из Википедии.

  4. Переполнение буфера - Вы выделяете указатель для символьного буфера из 30 символов. Затем вы переходите к потоковой передаче пользовательского ввода (из сокета, файла, консоли и т. Д.) В этот буфер. Если вы не реализуете должным образом проверки ограничения буфера, ваша программа потенциально может поместить в буфер более 30 символов. Это повредит любые данные, хранящиеся рядом с буфером в памяти, и, возможно, подвергнет вас атаке вредоносного кода. Дополнительная информация из Википедии.

  5. Повреждение памяти - Указатель - это просто целое число, которое содержит адрес памяти того, на что он указывает. В качестве целого числа Арифметика указателя может использоваться для управления значением указателя всевозможными интересными способами. Если расчеты указателя окажутся неверными, могут возникнуть небольшие ошибки. Указатель теперь будет указывать на какое-то неизвестное место в памяти, и при разыменовании на него может произойти все что угодно.

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

23
ответ дан 30 November 2019 в 06:17
поделиться

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

Существует также неправильная интерпретация типа объекта, на который указывает, но обычно это требует некоторых усилий, чтобы избежать неприятностей со стороны компилятора.

И утечки памяти, но это другая история, это касается распределения, не указатели как таковые.

3
ответ дан 30 November 2019 в 06:17
поделиться

Compiler Complaint

From http://xkcd.com

Думаю, я воспринимаю запрос на иллюстрацию буквально .

18
ответ дан 30 November 2019 в 06:17
поделиться

Просто инициализируйте ваши переменные указателя и хорошая очистка устранит 99% ваших проблем . Я имею в виду под хорошей уборкой; освобождение памяти и установка переменных-указателей в ноль.

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

3
ответ дан 30 November 2019 в 06:17
поделиться

The results when dereferencing a bad pointer are undefined, so by definition Anything can happen when you mess up with a pointer. This is why you should avoid using them when at all possible.

The C-ish languages are designed around the use of pointers, and they are dominant right now, so this going to sound like crazy advice to some. I'd advise folks to look into languages that are designed to minimize pointer use and check for common errors, like Ada.

My favorite pointer anectode is the following: I was once working for a group in Florida that maintained a networked flight simulation of 3 heliocpoters at Kurtland AFB in New Mexico (most of the way on the other side of the continent). There was a crash bug that popped up one day. The local site tech couldn't fix it, so after a month or so, one of our engineers got flown over to look at it. Two weeks later he was flummoxed, so another got pulled in. After another month our top engineer got flown over to help too.

One more month later (all the time with the company paying for 3 people living in Hotels, renting cars, and flying back every couple of weekends), they tracked down the problem. It turned out that somebody was indexing one past the end of an array (C has no index checking either). They were then grabbing the crap sitting at that location, passing it to a second machine over the network, and it was using that value as an array index. Since that code was also in C, again no checking. It grabbed the crap at that location and sent it to a third machine. That machine used the crap as a pointer and tried to dereference it. boom.

So a bug in the code on one machine was causing a crash two machines removed down the network. Thousands of dollars and several months of precious time were wasted tracking it down. All because they used a language with no range checks.

2
ответ дан 30 November 2019 в 06:17
поделиться
  • Никогда не игнорируйте предупреждения.
  • Используйте инструменты статического анализа , например Splint .

  • Самое важное: используйте инструменты динамического анализа - они часто предупреждают о некорректном использовании указателей, нарушении границ массива и т. Д. 'Я проверяю, что в них нет ошибок, даже если программа кажется работающей ...

2
ответ дан 30 November 2019 в 06:17
поделиться

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

Я бы не прожил и дня без интеллектуальных указателей. std :: auto_ptr, когда я передаю право собственности (четко определяйте ответственность), boost :: shared_ptr, когда право собственности разделяется, boost :: weak_ptr, когда кто-то только "наблюдает" за ресурсом.

1
ответ дан 30 November 2019 в 06:17
поделиться

The best practice is to avoid using pointers as much as possible. Use a managed language instead for the bulk of your software, and only fall down to C for small parts where this is necessary for accessing system resources or efficiency. In other words, C should be regarded much the same as assembly language.

(The original question I helped close as 'not a real question' was quite different and too broad to be useful.)

0
ответ дан 30 November 2019 в 06:17
поделиться

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

int *i;

while(1){
   *i = 0;
   i++;
}

По крайней мере, я помню, как мы это делали. Я считаю, что сейчас это не сработает.

1
ответ дан 30 November 2019 в 06:17
поделиться
Другие вопросы по тегам:

Похожие вопросы: