・WndProcからスレッドを作成して、そのスレッドにディレクトリを監視させます。ディレクトリはCode(WPARAM)と紐づけて、変更があった時にWndProcにメッセージを投げてそれを処理するというプログラムを書いているのですが、ヒープが壊れます(★★のところ)。原因はおそらく★を付けたところなのですが、どうしてそうなるかと、どのようにそれを回避するかがわかりません。対策法をご教示いただけると幸いです。
壊れたときの出力:
HEAP CORRUPTION DETECTED: after Normal block (#1176) at 0x00000043142539C0.
CRT detected that the application wrote to memory after end of heap buffer.
//スレッドメイン
void watcher::watcher_main( const size_t& Address )
{
CHANDLE _hEvent;
CHANDLE _hDict; //自動的にCloseHandleを呼び出す
OVERLAPPED _Overlapped{ 0 };
std::vector<UCHAR> _Buffer( 1024 * 64, 0 );
DWORD _Size;
(中略)
if (!ReadDirectoryChangesW( _hDict, _Buffer.data(), _Buffer.size(),
FALSE, _get()._info[Address].Info.Flags, nullptr, &_Overlapped, nullptr )) {
_AtExit();
break;
}
if (WaitForSingleObject( _hEvent, 600 ) == WAIT_TIMEOUT) {
continue; //何もしない
}
_Size = 0;
if (auto _Ret = GetOverlappedResult( _hDict, &_Overlapped, &_Size, FALSE );
_Ret == FALSE || _Size == 0) {
// 結果取得に失敗した場合
std::wstring _Temp;
const DWORD& Error = GetLastError();
getErrorText( _Temp );
trace << L"Buffer over " << ( _Size == 0 ) << L' ' << _Temp << L' ' << Error;
}
else {
_get()._this.lock();
auto _Entry = reinterpret_cast<FILE_NOTIFY_INFORMATION*>( _Buffer.data() );
size_t _Offset = 0;
while (true) {
_get()._info[Address].Info.Buffer.emplace_back( _Entry->FileName,
_Entry->FileNameLength / sizeof( WCHAR ), _Entry->Action ); //★
if (_Entry->NextEntryOffset == 0) {
break;
}
_Entry = reinterpret_cast<FILE_NOTIFY_INFORMATION*>(
reinterpret_cast<unsigned char*>( _Entry ) + _Entry->NextEntryOffset );
}
trace << L"Sending Message To Main routine";
//もう_get()にはさわらないのでアンロックする
_get()._this.unlock();
SendMessageW( _get()._hWnd, WM_MODIFIED_FILE, _get()._info[Address].Info.Code, 0 );
_Buffer.clear();
}
}
//Terminate
_AtExit( false );
_get()._info[Address].Status = status::terminate;
}
class wactcher {
enum class file_action
{
created = FILE_ACTION_ADDED,
removed = FILE_ACTION_REMOVED,
modified = FILE_ACTION_MODIFIED,
renamed_old_name = FILE_ACTION_RENAMED_OLD_NAME,
renamed_new_name = FILE_ACTION_RENAMED_NEW_NAME
};
struct notify_info
{
std::wstring FileName; //変更されたファイル名
file_action Type; //変更の種類
notify_info( const notify_info& Left );
notify_info( notify_info&& Right );
notify_info( const WCHAR* Str,const size_t& Length, const DWORD& dwRowFileAction );
~notify_info() noexcept;
};
//後略
}
//コンストラクタ(ムーブ・コピー・デストラクタは=defaultと同等の内容かと思われるので割愛)
watcher::notify_info::notify_info( const WCHAR* Str, const size_t& Length, const DWORD& dwRowFileAction ) :
FileName( Length, 0 ), Type( static_cast<file_action>( dwRowFileAction ) ) //★
/*文字列の長さとその文字列をとるwstringのコンストラクタを使っても同じ*/
{
FileName.assign( Str, Length );
}
//メイン関数側
case WM_MODIFIED_FILE:
switch (wParam) {
case CURRENT_DIR_CODE: {
const auto _ModifiedList = watcher::getChanged( CURRENT_DIR_CODE ); //★★
}
(後略)