2013-05-10 6 views
2

Мне любопытно, если этот код вызывает память утечка, вероятно, из-за того, что я переназначил указатель на строку 3 перед удалением его по строке 4 ??Этот код вызывает утечку памяти?

Спасибо.

1. int y = 12; 
2. int *pt = new int; 
3. pt = &y; 
4. delete pt; 
+0

Я думаю, что он выходит из строя причиной пт не указывает на пространство памяти больше БРОНИРОВАТЬ – DGomez

+1

Ваш код будет более вероятно, аварии ... – JosephH

+0

@DGomez, Не надо. Это UB. – chris

ответ

8

Это не только сливает динамически выделяемый int но и неопределенное поведение, потому что вы не можете delete объект, который не был выделен с new (§5.3.5/2).

значение операнда delete может быть нулевое значение указателя, указатель на объект, не массив, созданный с помощью предыдущей новой экспрессии или указатель на подобъектом (1.8), представляющий собой базу класс такого объекта (п. 10). Если нет, поведение не определено.

Поскольку объект обозначается y не был выделен с новой экспрессией, вы не можете использовать delete, чтобы уничтожить его. Его продолжительность жизни зависит от ее объема.

+0

Так что я должен быть осторожным при переназначении указателей? Я слышал, что в C это была проблема, но в C++ этого не было. – user2054339

+2

@ user2054339 Вы должны быть осторожны с указателями в целом. Необработанный тип указателя говорит очень мало о времени жизни объекта, на который он указывает. Предпочитают использовать интеллектуальные указатели, которые намного понятнее. –

+0

Будет ли это правильным способом (я знаю, может быть, не изящным, но все же) удалить p1 и p2? '\t int * y; \t int * p1 = new int; \t int * p2 = new int; \t y = p1; \t delete y; \t y = p2; \t delete y; ' – user2054339

2

Это может вызвать утечку памяти, если она не вызвала сбой сначала.

Нельзя удалять объект с «автоматическим» хранением.

0

Да.

Момент, когда вы потеряли указатель на newint вы просочилась

pt = &y; // Here the memory allocated is not reachable now and can not be deleted 

И это UB

delete pt; // pt is pointing to automaticaly allocated memory now. You can't delete that. 
+2

Зачем нужен downvote? – stardust

+0

Возможно, вы не упомянули об аспекте UB. Если программа даже * выживает * удаляет автоматический объект, то да, есть * вероятно * утечка ... но вторая, что 'delete', происходит, программа запускается с рельсов. Нет смысла даже пытаться * рассуждать о поведении за пределами этого момента. – cHao

+0

Да, действительно ... моя тоже была опущена. –

0

Он должен врезаться, потому что вы Ассинг стека адрес в указатель, а затем удалить Это. По крайней мере, это не определено, что происходит.

0

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

4

Всякий раз, когда вы не уверены утечки памяти в вашем коде, вы можете использовать valgrindvalgrind --tool=memcheck, чтобы проверить их, но обязательно компилировать код без оптимизации и в полном режиме отладки (например, «г ++ -g»).

Вот выход для вашей программы:

=29667== Memcheck, a memory error detector 
==29667== Copyright (C) 2002-2009, and GNU GPL'd, by Julian Seward et al. 
==29667== Using Valgrind-3.6.0.SVN-Debian and LibVEX; rerun with -h for copyright info 
==29667== Command: ./main 
==29667== 
==29667== Invalid free()/delete/delete[] 
==29667== at 0x4C26DCF: operator delete(void*) (vg_replace_malloc.c:387) 
==29667== by 0x4006AB: main (main.cpp:7) 
==29667== Address 0x7fefffd0c is on thread 1's stack 
==29667== 
==29667== 
==29667== HEAP SUMMARY: 
==29667==  in use at exit: 4 bytes in 1 blocks 
==29667== total heap usage: 1 allocs, 1 frees, 4 bytes allocated 
==29667== 
==29667== LEAK SUMMARY: 
==29667== definitely lost: 4 bytes in 1 blocks 
==29667== indirectly lost: 0 bytes in 0 blocks 
==29667==  possibly lost: 0 bytes in 0 blocks 
==29667== still reachable: 0 bytes in 0 blocks 
==29667==   suppressed: 0 bytes in 0 blocks 
==29667== Rerun with --leak-check=full to see details of leaked memory 
==29667== 
==29667== For counts of detected and suppressed errors, rerun with: -v 
==29667== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 4 from 4) 

Ваш код теряет 4 байта на выходе().

Вот список вещей вы можете сделать с MemCheck, от инструмента website

MemCheck является детектор ошибок памяти. Он может обнаруживать следующие проблемы , которые являются общими для программ на C и C++.

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

  • Использование неопределенных значений, то есть значений, которые не были инициализированы, или которые были получены из других неопределенных значений.

  • Неправильного освобождение динамической памяти, например, двойные освобождая блоки кучи, или несогласованного использования таНоса/новый/новый [] по сравнению с бесплатно/удалить/удалить []

    • Перекрытие SRC и dst в memcpy и связанных с ними функциях.

    • Утечка памяти.

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

+0

Kudos для показа valgrind и использования. Но этот эксперимент не помогает в том смысле, что его код также содержит неопределенное поведение (путем вызова 'delete' на то, что не было выделено' new'), что означает, что после этого все будет позади. –

+2

@NikBougalis Valgrind обнаруживает недействительный 'delete': вы можете видеть его на выходе. Если это не помогает, я не знаю, что есть. –

+0

Я не согласен - это было полезно здесь, и я должен был быть более осторожным в моей фразировке. Но мой главный момент заключался в том, что как только вы нажимаете неопределенное поведение * ничего *, и поэтому UB ** должен ** явно указывать на OP. С UB в игре можно * возможно, что valgrind мог вернуться с «никакой утечкой памяти, вы - золотой *» или даже с чем-то, начинающимся с «Hey sexy ...» –

Смежные вопросы