mahipal.friends Ответов: 2

В чем разница между функцией heapalloc() для отладки и выпуска ?


Мой проект использует две разные функции для выпуска и отладки. Мой код терпит крах в релизной версии, при выделении памяти.

Выпускать:
WINBASEAPI
_Ret_maybenull_
_Post_writable_byte_size_(dwBytes)
LPVOID
WINAPI
HeapAlloc(_In_ HANDLE hHeap,_In_ DWORD dwFlags,_In_ SIZE_T dwBytes);


Отлаживать:
#ifdef _DEBUG
#define HeapAlloc( a, b, c ) _calloc_dbg( (c), 1, _NORMAL_BLOCK, __FILE__, __LINE__ )
#endif




Код соответствует приведенному ниже, он используется для чтения xml-файла в C++\VC++.
Здесь я написал только примерную часть, которая будет читаться строка за строкой.

HANDLE hHeap = NULL;
SYSTEM_INFO si;
GetSystemInfo( &si );
hHeap = HeapCreate( HGE, 16 * si.dwPageSize, 0L );

int HGE = HEAP_GENERATE_EXCEPTIONS;
TCHAR *xmlTag = _T("nXMLPages");
size_t lenTag = _tcslen( xmlTag );
TCHAR *StartXMLTag = NULL, *EndXMLTag = NULL;
StartXMLTag = (TCHAR *) HeapAlloc( hHeap, HGE, ( lenTag + 2 ) * sizeof( TCHAR ) );
EndXMLTag = (TCHAR *) HeapAlloc( hHeap, HGE, ( lenTag + 4 ) * sizeof( TCHAR ) );	

//Место сбоя при вызове HeapAlloc() для EndXMLTag

Что я уже пробовал:

Входной файл данных как; &ЛТ;nxmlpages&ГТ;4

Richard MacCutchan

Вам нужно использовать свой отладчик для сбора дополнительной информации. Проверьте значения всех переменных в точке отказа.

2 Ответов

Рейтинг:
0

CPallini

Типичные сбои в релизной версии происходят из-за неинициализированных переменных. Во всяком случае, в приведенном вами примере кода переменные инициализируются (за исключением следующих случаев: HGE который используется еще до его появления декларация, а полагаю, что компилятор будет жаловаться на это). Я вижу, вы не проверили возвращаемое значение HeapCreate.


Richard MacCutchan

Я просто поддержал это, и рядом со звездами появилась маленькая ссылка, которая гласила "отменить". Но я неправильно истолковал его как "Uno" и подумал: "откуда он знает, что Карло итальянец? :)

CPallini

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

Рейтинг:
0

Rick York

Разница заключается в том, что в режиме отладки он вызывает версию отслеживания памяти calloc, а в релизе-HeapAlloc. Эти два совершенно разные и требуют различных, соответствующих функций высвобождения. Кроме того, использование семейства malloc/calloc не требует от вас сначала создавать кучу, как это делает HeapAlloc. Вот что microsoft может сказать о них : Сравнение Методов Выделения Памяти | Microsoft Docs[^]

Лично я, если бы не было необходимости, остался бы с семейством вызовов malloc (new/delete для c++), чтобы воспользоваться преимуществами функции отслеживания памяти, доступной вместе с ними.

Если вы должны использовать HeapAlloc, вот удобный небольшой класс шаблонов, который может помочь вам в этом. Самое приятное, что он автоматически освобождает память при удалении объекта и предоставляет операторы, которые устраняют необходимость приведения указателя. Он использует глобальную кучу, так что вам не нужно ее создавать. Во всяком случае, вот она:

template <typename T> class CHeapAlloc
{
public:
    CHeapAlloc( size_t count = 1 )
    {
        size_t size = count * sizeof( T );
        m_ptr = (T *)::HeapAlloc( ::GetProcessHeap(), HEAP_ZERO_MEMORY, size );
    }

    virtual ~CHeapAlloc()
    {
        if( m_ptr )
        {
            ::HeapFree( ::GetProcessHeap(), 0, m_ptr );
            m_ptr = nullptr;
        }
    }

    operator T*()         { return m_ptr; }

    T * operator->()      { return m_ptr; }

public:
    T * m_ptr;
};
Я не могу вспомнить, где я нашел это, но я думаю, что это пришло отсюда.