Главная > Программирование > Макросы – это все-таки опасно…

Макросы – это все-таки опасно…


Ловили недавно просто замечательный баг, который, как оказалось, растет из макроса.

Чтобы продемонстрировать вот код тестового приложения:

#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; А макрос это скрывает! И создается впечатление что объект будет уничтожен на выходе из функции.

Рубрики:Программирование Метки:

Добавить комментарий

Fill in your details below or click an icon to log in:

Логотип WordPress.com

You are commenting using your WordPress.com account. Log Out / Изменить )

Фотография Twitter

You are commenting using your Twitter account. Log Out / Изменить )

Фотография Facebook

You are commenting using your Facebook account. Log Out / Изменить )

Connecting to %s

Follow

Get every new post delivered to your Inbox.