UUID are unique identifiers which are used, for example, to identify COM objects.
To generate a new UUID, use the command line tool “uuidgen.exe”.
UUID are unique identifiers which are used, for example, to identify COM objects.
To generate a new UUID, use the command line tool “uuidgen.exe”.
Different problems can cause this error.
It is often related to the settings of your projects. If you use different run-time libraries for your main program and for your libraries/DLLs, they will not allocate and deallocate memory in the same way. Consequently, if some memory allocated by a library is released by another one, you may get this kind of error.
You can check your projects settings in : project->settings->C++->Code generation->Use run-time library.
However, the explanation can be really simpler. Just try to delete two times a same object, and you may get this error. To ensure that an object is not deleted twice, just put a breakpoint in its destructor.
I encountered this problem after doing a stupid mistake. I declared a CWinThread m_thread member variable in a class CMyClass I forgot that its m_bAutoDelete member variable is set to TRUE by default. Logically, m_thread was deleting itself once it was terminated. And of course, the destructor of CMyClass was trying to delete m_thread too… BOOM !!!
In some cases, you may need to convert a unicode string into an ANSI C null-terminated string. The WideCharToMultiByte function allows you to do this.
In the following example, I have used the ReadDirectoryChangesW function to detect a file modification in a directory. The name of the modified file is stored in UNICODE format. I want to convert it to a standard C string.
PFILE_NOTIFY_INFORMATION pstFileNotif;
…
// Initialization of pstFileNotif
…char szNotifFilename[ MAX_PATH ] = { 0 };
int iNbChar = WideCharToMultiByte(
CP_OEMCP,
NULL,
pstFileNotif->FileName,
pstFileNotif->FileNameLength / sizeof( WCHAR ),
szNotifFilename,
sizeof( szNotifFilename ) / sizeof( char ),
NULL, NULL ) ;if ( iNbCar == 0 )
{
// Error
}
Be careful : the size of the 2 strings is not their length in bytes, but their length in characters (a UNICODE character takes 2 bytes)
You may have wondered how these antivirus programs detect a modification on any file as soon a it is done. Instead of spending their time checking all the files, they use an event approach provided by microsoft.
The ReadDirectoryChangesW method allows you to monitor a given directory, and to wait (without consumming processos resource) until a change occurs.
The sample code below illustrates how to detect a change (modification of the last time written attribute) of a given file.
char szFilename[ MAX_PATH ] = “monitoredfile.txt”; // The file monitoredchar szFiledir[ MAX_PATH ] = “.”; // Monitoring the previous file in the current directorym_hMonitoredDir = CreateFile( szFiledir, FILE_LIST_DIRECTORY,
FILE_SHARE_DELETE|FILE_SHARE_READ|FILE_SHARE_WRITE,
NULL, OPEN_EXISTING,
FILE_FLAG_BACKUP_SEMANTICS, NULL );if ( m_hMonitoredDir == INVALID_HANDLE_VALUE )
{
DWORD dwErr = GetLastError();
return;
}char szBuf[ MAX_PATH ];
DWORD dwBytesRead = 0;// Waiting file changes
while ( ReadDirectoryChangesW( m_hMonitoredDir, szBuf, MAX_PATH,
FALSE, FILE_NOTIFY_CHANGE_LAST_WRITE,
&dwBytesRead, NULL, NULL ) )
{
PFILE_NOTIFY_INFORMATION pstFileNotif = (PFILE_NOTIFY_INFORMATION)( szBuf );
if ( pstFileNotif->Action == FILE_ACTION_MODIFIED )
{
char szNotifFilename[ MAX_PATH ] = { 0 };
if ( int iNotifFilenameLen = WideCharToMultiByte( CP_OEMCP, NULL,
pstFileNotif->FileName,
pstFileNotif->FileNameLength / sizeof( WCHAR ),
szNotifFilename, sizeof( szNotifFilename ) / sizeof( char ),
NULL, NULL ) )
{
if ( strcmp( szFilename, szNotifFilename ) == 0 )
{
DoYourStuff();
}
}
}
}
This code works fine, but imagine you want to execute it in a thread. You’ll get into trouble when you’ll want to terminate your thread. Why ? Because ReadDirectoryChangesW() as it is used here works synchronously. It hangs until a file change occurs. If you don’t want to change your code, the only way to lunock it is to make a change to the monitored file so that we get out of ReadDirectoryChangesW() and that we can check if we must break our loop.
That’s not a very nice way to manage a clean exit…
There is a better solution : using ReadDirectoryChangesW() asynchronously.
To do so :
The code below illustrates the solution.
/** Index of the file change event in CFileChangeMonitor::dwEvents*/
const int EVENT_INDEX_FILECHANGE = 0;
/** Index of the terminate event in CFileChangeMonitor::dwEvents*/
const int EVENT_INDEX_TERMINATE = 1;HANDLE m_events[ 2 ] ; // Array containing the events used
unsigned int CFileChangeMonitor::DoWaitFileChange( const char* szFilename ){ m_hMonitoredDir = CreateFile( szFiledir, FILE_LIST_DIRECTORY, FILE_SHARE_DELETE|FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS|FILE_FLAG_OVERLAPPED, NULL ); OVERLAPPED stOverlapped;
memset( &stOverlapped, NULL, sizeof( stOverlapped ) );
m_events[ EVENT_INDEX_FILECHANGE ] = CreateEvent( NULL, FALSE, FALSE, NULL );
m_events[ EVENT_INDEX_TERMINATE ] = CreateEvent( NULL, FALSE, FALSE, NULL );
stOverlapped.hEvent = m_events[ EVENT_INDEX_FILECHANGE ];char szBuf[ MAX_PATH ];
DWORD dwBytesRead = 0;while ( ReadDirectoryChangesW( m_hMonitoredDir, szBuf, MAX_PATH,
FALSE, FILE_NOTIFY_CHANGE_LAST_WRITE,
&dwBytesRead, &stOverlapped, NULL ) )
{
// Wait either for a file change or a terminate event
DWORD dwWaitRes = WaitForMultipleObjects( 2, m_events, FALSE, INFINITE );
switch ( dwWaitRes )
{
case EVENT_INDEX_FILECHANGE: // Change on the monitored file
if ( GetOverlappedResult( m_hMonitoredDir, &stOverlapped, &dwBytesRead, TRUE ) )
{
PFILE_NOTIFY_INFORMATION pstFileNotif = ( PFILE_NOTIFY_INFORMATION )( szBuf );
if ( pstFileNotif->Action == FILE_ACTION_MODIFIED )
{
char szNotifFilename[ MAX_PATH ] = { 0 };
if ( int iNotifFilenameLen = WideCharToMultiByte( CP_OEMCP, NULL,
pstFileNotif->FileName,
pstFileNotif->FileNameLength / sizeof( WCHAR ), szNotifFilename,
sizeof( szNotifFilename ) / sizeof( char ),
NULL, NULL ) )
{
if ( strcmp( szFilename, szNotifFilename ) == 0 )
OnFileChanged();
}
}
}
break;
default: // EVENT_INDEX_TERMINATE : must terminate
CloseHandle( m_hMonitoredDir );
CloseHandle( m_events[ EVENT_INDEX_FILECHANGE ] );
CloseHandle( m_events[ EVENT_INDEX_TERMINATE ] );
m_events[ EVENT_INDEX_TERMINATE ] = INVALID_HANDLE_VALUE;
m_events[ EVENT_INDEX_FILECHANGE ] = INVALID_HANDLE_VALUE;
m_hMonitoredDir = INVALID_HANDLE_VALUE;
return 0;
}
}return 0;
} // unsigned int CFileChangeMonitor::DoWaitFileChange