Макросы – это все-таки опасно…
Ловили недавно просто замечательный баг, который, как оказалось, растет из макроса.
Чтобы продемонстрировать вот код тестового приложения:
#include "stdafx.h"
#include
#include
#include
#define DECLARE_UNICODE_STRING_BY_WSTRING(strName, stdWstring) \
UNICODE_STRING strName = {(USHORT)stdWstring.size() * 2, (USHORT)stdWstring.size() * 2, (PWSTR)stdWstring.c_str()}
std::wstring GetPath()
{
return L"C:\\windows\\system32";
}
int _tmain(int argc, _TCHAR* argv[])
{
DECLARE_UNICODE_STRING_BY_WSTRING(moduleName, GetPath());
return 0; //здесь moduleName.Buffer указывает на пустую строку
}
Как же так получается, что строка становится пустой. Видно это только из ассемблера:
.text:00411558 call GetPath(void) ... .text:00411581 call ds:std::basic_string::c_str(void) ... .text:0041158E mov [ebp+moduleNameUs.Buffer], eax ... .text:004115A0 call ds:std::basic_string::~basic_string
Вызывается деструктор!
А связано это с тем, что область видимости экземпляра std::wstring, который вернула GetPath(), это:
{(USHORT)stdWstring.size() * 2, (USHORT)stdWstring.size() * 2, (PWSTR)stdWstring.c_str()}
То есть сразу же после, того как moduleName.Buffer будет присвоено значение, будет вызыван деструктор. И сделано это будет до строки return 0; А макрос это скрывает! И создается впечатление что объект будет уничтожен на выходе из функции.
Рубрики:Программирование
c++