Showing posts with label watchout. Show all posts
Showing posts with label watchout. Show all posts

Monday, November 07, 2005

watch out for those macros.. "macros are evil !"

macros are evil !

i want to set an item text in a listview control representing a date
ListView_SetItemText(hWnd, iIndex, 1, log.GetTimeString().GetBuffer(0));

the log object is like this:
class CLog : public CObject
{

...
CString GetDateString() { return m_datetime.Format(_T("%d/%m/%Y")); }
CString GetTimeString() { return m_datetime.Format(_T("%H:%M:%S")); }

...

}

ListView_SetItemText(hWnd, iIndex, 1, log.GetTimeString().GetBuffer(0));
is bad because the CString object returned by the GetTimeString is temporary (and valid only in that line) but the ListView_SetItemtext is a macro !
looking inside it, it looks like this:

#define ListView_SetItemText(hwndLV, i, iSubItem_, pszText_) { LV_ITEM _ms_lvi;_ms_lvi.iSubItem = iSubItem_;_ms_lvi.pszText = pszText_;SNDMSG((hwndLV), LVM_SETITEMTEXT, (WPARAM)(i), (LPARAM)(LV_ITEM *)&_ms_lvi);}
so once the buffer is set to _ms_lvi.pszText the CString object is destroyed and the SNDMSG will send an invalid buffer

always use memset on the structures

never leave a structure with unfilled values, for example:

BROWSEINFO bi;
SHBrowseForFolder(&bi);

in order to avoid this, a good practice would be one of these:

- remember to always initialize members we don't need:
bi.hwndOwner = NULL;

- just initialize the variabile:
BROWSEINFO bi = { 0 };

- use memset on the structure:
memset(bi, 0, sizeof(BRWOSEINFO));