Опасности указателей - PullRequest
       0

Опасности указателей

4 голосов
/ 16 января 2011

Я пытаюсь выучить C. Поскольку я уже немного знаком с языками более высокого уровня (PHP, Javascript, Python), я чувствую, что большая часть работы, которую я должен сделать, заключается в изучении того, как заменить структуры, которые я бы дал как должное(скажем, массивы переменного размера) с помощью указателей и ручного управления памятью.Моя проблема в том, что я немного обеспокоен игрой с указателями.

Обычно я пытаюсь поэкспериментировать с другими языковыми функциями, но моя проблема в том, что неправильное использование указателей может привести к неожиданным результатам.В частности: возможно ли - если я ошибусь - что я могу испортить сегменты памяти, которые используют другие программы, вызывая неправильную работу этих программ?Или операционная система (в моем случае различные версии Ubuntu) не позволит мне вмешиваться в память, выделенную для разных процессов?

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

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

Ответы [ 4 ]

8 голосов
/ 16 января 2011

В частности: возможно ли - если я ошибусь - что я могу испортить сегменты памяти, используемые другими программами, что приведет к неправильной работе этих программ?

Не на большинстве (всех?) Основных операционных систем, доступных сегодня. Защита памяти была особенностью большинства систем Unix / Linux, Windows и Mac OS в течение десятилетия. Защита памяти - это система контроля доступа на уровне ОС, которая предотвращает запись программ в память, которая им не принадлежит. Это, как вы предлагаете, предотвращает запись программного обеспечения в память, принадлежащую другим процессам, а также предотвращает считывание программным обеспечением памяти, которая ему не принадлежит (серьезный риск безопасности).

Это не значит, что вам не о чем беспокоиться в будущем, но если вы начинаете изучать C на современном настольном компьютере, вам не стоит об этом думать. Если вы допустите ошибку в своем C-коде, вы, вероятно, не нанесете вреда ОС! :)

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

http://en.wikipedia.org/wiki/Buffer_overflow и http://en.wikipedia.org/wiki/Memory_protection

5 голосов
/ 16 января 2011

Возможны повреждения и сбои, но пока вы осторожны с размером значения в памяти, на который указывает указатель, и вы уверены, что вы не меняете указатели, и вы уверены, что вы НЕ ДЕЛАЕТЕ АДРЕСА HARDCODE MEMORY с вами все будет в порядке.

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

Хороший пример

int *i = malloc(sizeof(int));
// Use I further.
free(i);

Неправильный пример

int *i;
i = malloc(sizeof(int));
double j;
i = &j;
j = 3.1415// Mem corruption due to differently sized values, given a double is LARGER than an int.

(Не уверен, что это скомпилируется. Зависит от флагов компилятора.)

Ужасный пример, коррупция гарантирована на 99%

int *i = 0x00ABCDEF; // Hard coded mem adress.
int j = 123;
int *k = &j;
memcpy(i, k, sizeof(int));
4 голосов
/ 16 января 2011

Большинство современных настольных операционных систем (включая Linux) используют виртуальную память, чтобы предотвратить неправильную работу программы от других программ.Каждый процесс получает свое собственное адресное пространство, и если вы переполняете буфер или неправильно используете указатели, самое худшее, что может произойти, это сбой вашего процесса.Вы не должны влиять на другие процессы в системе, если вы не пишете драйвер устройства или не работаете от имени пользователя root (и если вы работаете от имени пользователя root, вам нужно будет сделать что-то плохое для файла, который читает другой процесс и т. Д.)... у вас все равно не будет прямого доступа к памяти другого процесса).

С точки зрения перехвата ошибок перед тем, как их совершить, вот несколько правил, которым нужно следовать:

  1. Всегда проверяйте все вновь полученные указатели (например, возвращаемые значения malloc, аргументы функций и т. Д.) На нулевое значение, прежде чем их использовать.
  2. Переверните все предупреждения вашего компилятора и обращайте на них внимание.
  3. После free выделения динамически выделенной памяти установите указатель на ноль.Это должно помочь вам поймать какой-нибудь висячий указатель или ошибки двойного освобождения.(Конечно, если вы скопировали этот указатель и сохранили его в других местах своего кода, у вас могут возникнуть эти проблемы, если вы не будете осторожны.)
2 голосов
/ 16 января 2011

В большинстве современных операционных систем (включая Linux) каждый процесс выполняется в отдельном адресном пространстве , что означает, что вся память, к которой он может обращаться, является не реальной ОЗУ, а собственной закрытой «песочницей памяти», которые не влияют на другие приложения (на самом деле это могло бы произойти, если бы у вас были сегменты памяти RW, совместно используемые другими приложениями, но вы и другое приложение должны были бы явно их создавать).

Кстати, часто, если выделайте ошибки с указателями, в результате вы получаете указатели, которые указывают на недопустимые области памяти, и при первой попытке разыменования их ОС закроет ваше приложение из-за ошибки сегментации;не беспокойтесь об этом, просто ОС сообщает вам, что вы путаетесь с указателями.:) Наиболее серьезными проблемами, с другой стороны, являются те, где ОС не может обнаружить, что вы неправильно указали некоторые элементы указателя.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...