Ошибка отладки _msize

0

Я трачу много времени, пытаясь выяснить, почему у меня есть утверждение в этом коде.

Если в классе нет деструктора, он работает хорошо.

Можете ли вы объяснить, почему у меня есть Assert с классом, содержащим деструктор.

Я не хочу знать количество элементов в массиве. Я просто хочу понять Assert, когда в классе есть деструктор.

С Visual C++ "новый" вызывает функцию "malloc".

================================================== ===================================

Более детально:

С помощью: CTheClass * pArrayTheclass= new CTheClass [1];

При отладке в функции _heap_alloc_dbg_impl() вы можете найти следующую строку кода: blockSize = sizeof (_CrtMemBlockHeader) + nSize + nNoMansLandSize;

где: sizeof (_CrtMemBlockHeader): 32 nSize: 4 nNoMansLandSize: 4

После этого выделяется память (withHeaderBlock), а функция возвращает указатель на часть данных.

И в конце "operator new []" в файле "new2.cpp" этот указатель данных возвращается к распределению программы.

Но с: CTheClassWithDestructor * pArrayTheClassWithDestructor = новый CTheClassWithDestructor [1]; почти то же самое...

но nSize равен 8; sizeof (int) + 4 байта

Но на этот раз, даже если в конце "operator new [] у нас есть указатель dataPart.
В основной программе я получаю этот указатель со смещением 4.

И если я вычитаю 4 из указателя, я не буду утверждать, когда вызываю функцию _msize().

Это объясняет утверждение. Утверждение является причиной этого смещения 4.

Но почему у нас есть это смещение 4?

Вывод

Это смещение в 4 байта содержит количество элементов.

Если класс имеет деструктор, компилятор резервирует 4 байта для хранения количества элементов в массиве.

Если для вызова нет деструктора, у нас нет дополнительных 4 байтов в качестве смещения.

Благодарю Марка

#include <malloc.h>

class CTheClass
{
private:
    int TheValue_;
};

class CTheClassWithDestructor
{
public:
    ~CTheClassWithDestructor()
    {
        int TheValue_ = 0;
    }
private:
    int TheValue_;
};

int _tmain(int argc, _TCHAR* argv[])
{
int size;

CTheClass* pArrayTheClass = new CTheClass[1];
size = _msize(pArrayTheClass);
delete [] pArrayTheClass;

CTheClassWithDestructor* pArrayTheClassWithDestructor 
                   = new CTheClassWithDestructor[1];
size = _msize(pArrayTheClassWithDestructor);           /// ASSERT On this line
delete [] pArrayTheClassWithDestructor;

return 0;
}
Теги:
visual-c++
memory-management

1 ответ

1

С Visual C++ new вызовы функции malloc.

Это отчасти верно: new выражения в вашем коде требуют вызова operator new для выделения памяти, а operator new действительно вызывает malloc. Но указатель на исходный элемент, который дает new выражение, необязательно является указателем, полученным из malloc.

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

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

  • 0
    Я добавил раздел «Более подробно:» @James McNellis
  • 0
    Эти четыре байта используются для бухгалтерской информации (они хранят количество элементов, подлежащих уничтожению). Для CTheClassWith_int уничтожение не требуется, поэтому компилятор не выделяет место для информации учета.
Показать ещё 3 комментария

Ещё вопросы

Сообщество Overcoder
Наверх
Меню