Valgrind не сообщает об утечке памяти при «удалении массива»

После реализации кода C ++, приведенного ниже, я запустилvalgrind --leak-check=full чтобы проверить, не было ли утечки памяти. Результат был 0 байт были использованы на выходе а также утечки не возможны.

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

Я искал некоторые объяснения (например:ператоры @delete и delete [] в C ++) и все, что я прочитал, говорит, что используяdelete без[] может вызвать утечку памяти, поскольку вызывает только деструктор для первого объекта в массиве.

Я изменил код для удаления [], и вывод valgrind был таким же (как и ожидалось). Но теперь я в замешательстве: "Есть ли проблема с валгриндом или нет?&quodelete действительно отлично работает для массивов даже без оператора[]? "

#include <iostream>
#include <string.h>
using namespace std;
class Foo {
  private: char *x;
  public:
    Foo(const char* px) {
       this->x = new char[strlen(px)+1];
       strcpy(this->x, px);
    }
    ~Foo() {
       delete x;
    }
    void printInfo() {  cout << "x: " << x << endl;  }
};
int main() {
   Foo *objfoo = new Foo("ABC123");
   objfoo->printInfo();
   delete objfoo;
   return 0;
}
 Bo Persson14 мая 2012 г., 17:32
Известно, что, например, MSVC генерирует один и тот же код дляdelete x а такжеdelete[] x когда массив содержит встроенные типы, такие какchar. Коддруго для типов классов с деструктором.
 Dave S14 мая 2012 г., 17:21
Plus, используя valgrind 3.2.1 в вашей программе, отметьте, что существует 'Несоответствие free () / delete / delete []'. Это не утечка памяти, а ошибка.
 Moacir Ponti14 мая 2012 г., 18:27
Спасибо Джерри, я не смог найти этот вопрос. Ответы там очень интересны
 Jerry Coffin14 мая 2012 г., 17:49
Хотя вы обнаруживаете это с помощью другого инструмента, код и вопрос здесь являются возможной копиейункция @_CrtMemDumpAllObjectsSince () не может обнаружить утечки, если вызывается delete array вместо delete [] array и мой ответ на этот вопрос примерно одинаков.
 Benjamin Lindley14 мая 2012 г., 17:18
Ответы на вопрос, который вы связали, не содержат упоминаний об утечках памяти. На самом деле они говорят то же самое, что говорит Алс ниже. Так почему ты говоришь "все, что я прочитал, говорит, что использование delete без [] приводит к утечке памяти." ?

Ответы на вопрос(2)

Решение Вопроса

Использование удаления без [] вызывает утечку памяти.

Нет, это вызывает Неопределенное поведение.

Ваша программа, в которой вы размещаете, используяnew [] и освободить с помощьюdelete имеет неопределенное поведение. На самом деле, вам повезло (довольно не повезло), это не демонстрирует странного поведения.

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

 Sebastian Mach14 мая 2012 г., 17:15
Upvote для "довольно неудачно".
 Moacir Ponti14 мая 2012 г., 18:32
Алс, спасибо также за примечание. Означает ли неопределенное поведение, что никто не может знать, что произойдет? Но известно, что повреждение кучи очень вероятно (как цитирует Стивена), так почему валгринд не может его найти?
 Moacir Ponti14 мая 2012 г., 18:29
Стефен, да, я знаю, что это ответственность программиста, и я также знаю последствия. Я просто хочу понять, почему Valgrind не смог найти возможную утечку.
 Alok Save14 мая 2012 г., 18:39
@ MoacirPontiJr .: Да. Неопределенное поведение означает, что все (в буквальном смысле) возможно. Как только программа имеет неопределенное поведение, вы не можете ожидать никакого поведения, все ставки отключены. Также, как я сказал в ответ на результат несоответствияnew [] а такжеdelete является неопределенным поведением, которое может быть не обязательно утечкой памяти.
 Stephen Newell14 мая 2012 г., 18:26
Я бы не сказал этого лучше, но я процитирую FAQ, чтобы спрашивающий мог ссылаться на происходящее: «Ответственность за установление связи между новым T [n] и delete [] лежит на программисте, а не на компиляторе». p правильно. Если вы ошиблись, компилятор не сгенерирует ни сообщение об ошибке времени компиляции, ни времени выполнения. Повреждение кучи является вероятным результатом. Или хуже. Ваша программа, вероятно, умрет. " Parashift.com / C ++ - чаво-облегченный / FreeStore-mgmt.html # чаво-16,12

delete а такжеdelete[] не о освобождении памяти, а о вызовах деструкторов.

Пока официально неопределенное поведение, на практике это будет более или менее работать ... кроме этогоdelete вызовет только деструктор первого элемента.

Как примечание, вы можете получить проблему:

#include <iostream>

struct A{
  ~A() { std::cout << "destructor\n"; }
};

int main() {
  A* a = new A[10];
  delete a;
}

немного как

*** glibc detected *** ./prog: munmap_chunk(): invalid pointer: 0x093fe00c ***
======= Backtrace: =========
/lib/libc.so.6[0xb759dfd4]
/lib/libc.so.6[0xb759ef89]
/usr/lib/gcc/i686-pc-linux-gnu/4.3.4/libstdc++.so.6(_ZdlPv+0x21)[0xb77602d1]
./prog(__gxx_personality_v0+0x18f)[0x8048763]
./prog(__gxx_personality_v0+0x4d)[0x8048621]
======= Memory map: ========

Посмотри на Ideone.

 Alok Save14 мая 2012 г., 17:48
Я думаю, что это спор ОП с егоdelete вызов в деструкторе.
 PlasmaHH14 мая 2012 г., 17:50
Большинство реализаций (к счастью) потерпят неудачу для большинства типов, когда «удаляют новый T [n]», потому что они хранят размер перед выделением, таким образом, имея слегка смещенные указатели для вызова базового необработанного менеджера памяти

Ваш ответ на вопрос