Разве это не нормально с точки зрения утечки памяти и т. Д. - PullRequest
1 голос
/ 15 ноября 2011

Прошло около 2 месяцев с тех пор, как я начал изучать c ++, и я не совсем уверен, что делаю неправильно для своего проекта. У меня есть динамически размещенный массив с начальным размером и после того, как я хочу изменить его размер. Мне интересно, почему следующий код неправильный

    int *firstPtr = new int [4];
    for (int i = 0; i < 4; i++) {
        firstPtr[i] = i;
    }

    int *tempPtr = new int[5];
    for (int i = 0; i < 4; i++) {
        tempPtr[i] = firstPtr[i];
    }
    tempPtr[4] = 4;
   // firstPtr = new int[5];
    firstPtr = tempPtr;
    delete tempPtr;

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

потому что вывод:

10757752
10753936
2
3
4


PS: Я не могу использовать для этого realloc / malloc и т. Д., Так как в проекте только указатели Как я могу исправить это без них.

Ответы [ 6 ]

3 голосов
/ 15 ноября 2011
firstPtr = tempPtr;

first Ptr теперь указывает на ту же память, что и tempPtr.

delete tempPtr;

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

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

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

Чтобы получить то, что, как я предполагаю, вы хотите, вам нужно удалить строку

firstPtr = tempPtr;

или удалите память после:

for (int i = 0; i < 5; i++) {
    cout << firstPtr[i] << endl;
}
delete[] tempPtr;

Обратите внимание, что во втором случае вы получите утечку памяти, поскольку память, изначально указанная firstPtr, больше не доступна.

Полный рабочий и правильный код будет следующим:

int *firstPtr = new int [4];
for (int i = 0; i < 4; i++) {
    firstPtr[i] = i;
}

int *tempPtr = new int[5];
for (int i = 0; i < 4; i++) {
    tempPtr[i] = firstPtr[i];
}
tempPtr[4] = 4;

for (int i = 0; i < 5; i++) {
    cout << firstPtr[i] << endl;
}
delete[] tempPtr;
delete[] firstPtr;

Некоторые ASCII art:

firstPtr = new int[4];

firstPtr
   |
+------++------++------++------+
|      ||      ||      ||      |
|      ||      ||      ||      |
+------++------++------++------+

for (int i = 0; i < 4; i++) {
    firstPtr[i] = i;
}

firstPtr
   |
+------++------++------++------+
|   0  ||   1  ||   2  ||   3  |
|      ||      ||      ||      |
+------++------++------++------+

int *tempPtr = new int[5];
    for (int i = 0; i < 4; i++) {
        tempPtr[i] = firstPtr[i];
    }
    tempPtr[4] = 4;

tempPtr
   |
+------++------++------++------++------+
|   0  ||   1  ||   2  ||   3  ||   4  |
|      ||      ||      ||      ||      |
+------++------++------++------++------+

Итак, теперь в памяти у вас есть:

firstPtr
   |
+------++------++------++------+
|   0  ||   1  ||   2  ||   3  |
|      ||      ||      ||      |
+------++------++------++------+

tempPtr
   |
+------++------++------++------++------+
|   0  ||   1  ||   2  ||   3  ||   4  |
|      ||      ||      ||      ||      |
+------++------++------++------++------+

Ваша следующая строка:

firstPtr = tempPtr;

делает это:

no longer pointed to by firstPtr
   |
+------++------++------++------+
|   0  ||   1  ||   2  ||   3  |
|      ||      ||      ||      |
+------++------++------++------+

tempPtr
firstPtr  -  firstPtr now points here
   |
+------++------++------++------++------+
|   0  ||   1  ||   2  ||   3  ||   4  |
|      ||      ||      ||      ||      |
+------++------++------++------++------+

delete tempPtr;

tempPtr
firstPtr  -  firstPtr now points here
   |
+------++------++------++------++------+
|   x  ||   x  ||   x  ||   x  ||   x  |
|      ||      ||      ||      ||      |
+------++------++------++------++------+

Итак, теперь tempPtr указывает на удаление памяти. Надеюсь, это прояснит ситуацию.

1 голос
/ 15 ноября 2011

Это здесь

firstPtr = tempPtr;
delete tempPtr;

вы видите, вы присваиваете значение tempPtr для firstPtr, что означает, что они ссылаются на одну и ту же ячейку памяти (на данный момент у вас нет указателяк старой памяти, на которую раньше указывал firstPtr), затем вы освобождаете (delete) память, на которую указывает tempPtr, что на самом деле является той же самой памятью.

Правильнопуть должен быть

delete firstPtr;
firstPtr = tempPtr;
1 голос
/ 15 ноября 2011
  1. , назначив firstPtr, не сможет освободить память за перезаписанным указателем
  2. удаляя tempPtr вы делаете данные, на которые указывает firstPtr, недействительными (непосредственная причина неправильного вывода)

Решение:

  1. добавить строку для удаления firstPtr перед строкой присваивания "firstPtr = tempPtr;"
  2. переместить строку, которая удаляет tempPtr ниже цикла "cout <<" </li>
0 голосов
/ 15 ноября 2011

Вы получаете доступ к удаленной памяти.Это неопределенное поведение.

Это похоже на чтение значения из указателя malloc() ed после вызова free().

0 голосов
/ 15 ноября 2011
firstPtr = tempPtr;
delete tempPtr;

Затем вы используете firstPtr, но это то же самое, что и tempPtr, который является указателем, который вы удалили.

Попробуйте нарисовать на бумаге, что происходит внутри вашей кучи, чтобы понять.

0 голосов
/ 15 ноября 2011

Вместо

 firstPtr = tempPtr;
 delete tempPtr;

Вам нужно

 delete [] firstPtr;
 firstPtr = tempPtr;

И позже, когда вы закончите, не забудьте

 delete [] firstPtr;

В вашем оригиналеПосле того, как вы отправите сообщение, сначала наберите в поле firstPtr только что выделенную память, а затем освободите ее.Таким образом, firstPtr и tmpPrt указывают на свободную память.Использование освобожденной памяти является неопределенным поведением.Также, пожалуйста, рассмотрите возможность использования std::vector<int> s.Это облегчит вашу жизнь.

...