Интерпретация дампа объекта
Этот раздел применим к:
Выпуск |
Visual Basic |
C# |
F# |
C++ |
Web Developer |
---|---|---|---|---|---|
Express |
![]() |
![]() |
![]() |
Только машинные коды |
![]() |
Pro, Premium и Ultimate |
![]() |
![]() |
![]() |
Только машинные коды |
![]() |
Рассмотрим этот дамп объекта более подробно:
{5} strcore.cpp(80) : non-object block at $00A7521A, 9 bytes long
{4} strcore.cpp(80) : non-object block at $00A751F8, 5 bytes long
{3} strcore.cpp(80) : non-object block at $00A751D6, 6 bytes long
{2} a CPerson at $51A4
Last Name: Smith
First Name: Alan
Phone #: 581-0215
{1} strcore.cpp(80) : non-object block at $00A7516E, 25 bytes long
Программа, которая создала этот дамп, выделяла память явным образом только дважды — один раз в стеке, а другой раз в куче:
// Do your memory allocations and deallocations.
CString s("This is a frame variable");
// The next object is a heap object.
CPerson* p = new CPerson( "Smith", "Alan", "581-0215" );
CPerson получает три аргумента — указатели на тип char, используемые для инициализации переменных-членов CString. В дампе памяти объект CPerson размещается вместе с тремя не-объектными блоками (3, 4 и 5). Они содержат знаки для переменных-членов CString и не будут удалены в случае вызова деструктора объекта CPerson.
Блок номер 2 — собственно объект CPerson. $51A4 представляет собой адрес блока, за которым следует содержимое объекта, выводимое CPerson::Dump при вызове с помощью DumpAllObjectsSince.
Нетрудно догадаться, что блок номер 1 связан с переменной фрейма CString, это видно из порядкового номера и размера, соответствующего количеству знаков в переменной фрейма CString. Переменные, размещенные во фрейме, автоматически освобождаются, когда фрейм выходит за пределы области действия.
Переменные фрейма
В основном можно не волноваться по поводу объектов кучи, связанных с переменными фрейма, потому что они автоматически освобождаются, когда эти переменные выходят за пределы области действия. Чтобы избежать беспорядка в диагностическом дампе, следует располагать вызовы Checkpoint так, чтобы они находились вне области действия переменных фрейма. Например, поместите фигурные скобки так, чтобы они окружали код предыдущего выделения памяти:
oldMemState.Checkpoint();
{
// Do your memory allocations and deallocations ...
CString s("This is a frame variable");
// The next object is a heap object.
CPerson* p = new CPerson( "Smith", "Alan", "581-0215" );
}
newMemState.Checkpoint();
С квадратными скобками в этих местах дамп памяти для этого примера выглядит следующим образом:
Dumping objects ->
{5} strcore.cpp(80) : non-object block at $00A7521A, 9 bytes long
{4} strcore.cpp(80) : non-object block at $00A751F8, 5 bytes long
{3} strcore.cpp(80) : non-object block at $00A751D6, 6 bytes long
{2} a CPerson at $51A4
Last Name: Smith
First Name: Alan
Phone #: 581-0215
Не-объектные выделения
Заметьте, что есть выделения-объекты (например, CPerson) и есть не-объекты. " Не-объектные выделения" — это выделения для объектов, которые не являются производными от CObject, или выделения простых типов языка С, таких как char, int или long. Если класс, производный от CObject, выделяет дополнительное пространство, например внутренний буфер, такие объекты отобразят и объектное, и не-объектное выделение.
Предотвращение утечек памяти
Заметьте: в приведенном выше коде блок памяти, связанный с переменной фрейма CString, был освобожден автоматически и не отобразился как утечка. Автоматическое освобождение, обусловленное правилами ограничения области видимости, предотвращает большинство утечек памяти, связанных с переменными фрейма.
Однако для объектов, распределенных в куче, во избежание утечки памяти нужно явно удалять объект. Чтобы очистить последнюю утечку памяти в предыдущем примере, удалите объект CPerson, размещенный в куче:
{
// Do your memory allocations and deallocations.
CString s("This is a frame variable");
// The next object is a heap object.
CPerson* p = new CPerson( "Smith", "Alan", "581-0215" );
delete p;
}