В Windows, как я могу заменить `GlobalAlloc` на` new`? - PullRequest
1 голос
/ 10 февраля 2012

В Windows, как я могу заменить GlobalAlloc на new?

Здравствуйте, у меня есть этот фрагмент кода (отсюда: "Чтение из почтового ящика" ), которыйвыделить память с помощью GlobalAlloc.

DWORD cbRead = 0;
LPTSTR lpszBuffer = (LPTSTR) ::GlobalAlloc(GPTR, cbMessage); //cbMessage is from a call to GetMailslotInfo
if( NULL == lpszBuffer )
    return FALSE;
lpszBuffer[0] = '\0';
BOOL fResult = ::ReadFile(hSlot, lpszBuffer, cbMessage, &cbRead, 0);
if (fResult)
{
    _tprintf(TEXT("Contents of the mailslot: %s\n"), lpszBuffer);
}
::GlobalFree((HGLOBAL) lpszBuffer);

Я хотел бы изменить код и использовать умный указатель вместо простых LPTSTR (и избавиться от GlobalFree) и new вместоGlobalAlloc.cbMessage - это «Размер следующего сообщения в байтах», и поэтому мне нужно что-то вроде malloc, которое работает для нетипизированной памяти, есть ли какая-нибудь форма new, подходящая для моего случая?

Ответы [ 2 ]

3 голосов
/ 10 февраля 2012

Как правило, вы не можете.

Различные функции выделения памяти (GlobalAlloc, malloc, new, SysAlloc, VirtualAlloc, HeapAlloc) существуют, потому что они выделяют память по-разному, в разных местах, в разных размерах, пометьте ее по-разному, используйте разные базовые менеджеры и множество других отличий. Некоторые из них находятся в локальной куче, некоторые глобальные, некоторые виртуальные, некоторые не указывают, другие выделяют память и что-то с ней делают, например SysAllocString, другие работают с COM, например CoGetMalloc и т. Д.

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

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

Для обычных MFC и / или ATL часто имеют интеллектуальные указатели и вспомогательные функции, которые работают с одним или несколькими специализированными распределителями. Если это возможно, вы можете посмотреть на это.

1 голос
/ 11 февраля 2012
boost::scoped_array<TCHAR> buffer(new TCHAR[cbMessage / sizeof(TCHAR)]);
buffer[0] = 0;
BOOL fResult = ::ReadFile(hSlot, buffer.get(), cbMessage, &cbRead, 0);
if (fResult)
{
    _tprintf(TEXT("Contents of the mailslot: %s\n"), buffer.get());
}

Для управления памятью используется умный указатель, поэтому вам не нужно явно освобождать ее.(Повышение scoped_array .)

...