Управление памятью в C ++. - PullRequest
       1

Управление памятью в C ++.

2 голосов
/ 09 августа 2011

У меня есть следующая программа:

//simple array memory test.

#include <iostream>
using namespace std;

void someFunc(float*, int, int);

int main() {

  int convert = 2;

  float *arr = new float[17];
  for(int i = 0; i < 17; i++) {
    arr[i] = 1.0;
  }

  someFunc(arr, 17, convert);

  for(int i = 0; i < 17; i++) {
    cout << arr[i] << endl;
  }

  return 0;
}

void someFunc(float *arr, int num, int flag) {

  if(flag) {
    delete []arr;
  }
}

Когда я помещаю следующее в gdb и вставляю точку останова в float *arr ..., я прохожу программу и наблюдаю следующее:

  1. Печать массива arr после его инициализации дает мне 1 17 раз.
  2. Внутри someFunc я также печатаю arr до delete, чтобы получить тот же отпечаток, что и выше.
  3. При возвращении в main, когда я печатаю arr,Я получаю первую цифру как 0, а затем 16 1.0s.

Мои вопросы:
1. Как только массив был удален в someFunc, как я по-прежнему могу получить доступ к arr без сегментации в someFunc или main?
2. Приведенный выше фрагмент кода является тестовой версией другого фрагмента кода, который выполняется в более крупной программе.Я наблюдаю одинаковое поведение в обоих местах (первая цифра 0, но все остальные одинаковы. Если это какая-то необъяснимая ошибка памяти, как я наблюдаю одно и то же в разных областях?
3. Некоторые пояснения, которые необходимо заполнитьпробелы в моем понимании приветствуются.

Ответы [ 6 ]

3 голосов
/ 09 августа 2011

Разыменование указателя после того, как он был delete ed, является неопределенным поведением, что означает, что все может произойти.

3 голосов
/ 09 августа 2011

Segfault возникает при доступе к адресу памяти, который не отображается в процессе. Вызов delete [] освобождает память обратно в распределитель памяти, но обычно не в ОС.

Содержимое памяти после вызова delete [] является подробностью реализации, которая варьируется в зависимости от компиляторов, библиотек, ОС и особенно сборок debug-vs-release. Например, распределители памяти отладки часто заполняют память некоторой контрольной подписью, такой как 0xdeadbeef.

2 голосов
/ 09 августа 2011

delete возвращает память диспетчеру памяти ОС, но не обязательно очищает содержимое в памяти (это не должно происходить, поскольку это приводит к дополнительным затратам).Значения сохраняются в памяти.И в вашем случае вы обращаетесь к одной и той же памяти - поэтому она напечатает то, что находится в памяти - это не обязательно неопределенное поведение (зависит от диспетчера памяти)

2 голосов
/ 09 августа 2011

Как только массив был удален, любой доступ к нему является неопределенным поведением.Там нет никакой гарантии, что вы получите нарушение сегмента;на самом деле, как правило, вы не будете.Но нет гарантии того, что вы получите;в больших программах изменение содержимого массива может легко привести к повреждению памяти в другом месте.

1 голос
/ 09 августа 2011

Re 1: Вы не можете.Если вы хотите получить доступ к arr позже, не удаляйте его.

0 голосов
/ 09 августа 2011

C ++ не проверяет границы массива. Только если вы получите доступ к памяти, к которой у вас нет доступа, вы получите segfault

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