2013-04-16 2 views
0

Je suis en train de coder un dossier de programmation à regarder. J'utilise la bibliothèque FileWatch.h. Ceci est mon FileWatch.hAccédez à l'emplacement de lecture de violation 0xba2f1498

#ifndef FILEWATCH_H 
#define FILEWATCH_H 

class FileChangeObserver 
{ 
public: 
    virtual ~FileChangeObserver() 
    { 

    } 
    virtual void OnFileChanged() = 0; 
}; 
// information concerning a directory being watched 
class FileWatcher 
{ 
public: 
    // Watching file modifications using a loop 
    void Init(LPCTSTR filefullpath); 
    bool CheckForChanges(DWORD waittime=0); 
    // Watching file modification via a thread 
    void StartWatchThread(); 
    bool IsThreadRunning(); 
    void SynchronousAbort(); 
    FileWatcher(FileChangeObserver *observer) : hDir(NULL), curBuffer(0), 
     filePath(NULL), hWatchingThread(NULL), observer(observer) 
    { 
     ZeroMemory(&this->overl, sizeof(this->overl)); 
     // create the event used to abort the "watching" thread 
     hEvtStopWatching = CreateEvent(NULL, TRUE, FALSE, NULL); 
    } 
    FileWatcher() 
    { 
    } 
    ~FileWatcher() 
    { 
     SynchronousAbort(); 
     delete observer; 
     free(filePath); 
     CloseHandle(hEvtStopWatching); 
    } 
public: 
    HANDLE   hDir;  // handle of the directory to watch 
    FileChangeObserver *observer; // function called when a file change is detected 
    TCHAR *   filePath; // path to the file watched 
    FILE_NOTIFY_INFORMATION buffer[2][512]; 
     // a double buffer where the Windows API ReadDirectory will store the list 
     // of files that have been modified. 
    int curBuffer; // current buffer used (alternate between 0 and 1) 
    bool NotifyChange(); 
public: 
    // fields for use by the WathingThread 
    OVERLAPPED overl; // object used for asynchronous API calls 
    HANDLE hWatchingThread; // handle of the watching thread 
    HANDLE hEvtStopWatching; // this event is fired when the watching thread needs to be aborted 
}; 
static DWORD WINAPI WatchingThread(void *param); 
#endif 

Ceci est mon FileWatch.cpp

#include "stdafx.h" 
#include "FileWatch.h" 
#include "assert.h" 
#if _MSC_VER > 1600 
extern "C" { 
WINBASEAPI BOOL WINAPI 
GetOverlappedResult(_In_ HANDLE hFile, _In_ LPOVERLAPPED lpOverlapped, _Out_ LPDWORD lpNumberOfBytesTransferred, _In_ BOOL bWait); 
} 
#endif 
bool FileWatcher::IsThreadRunning() 
{ 
    return hWatchingThread && (WaitForSingleObject(hWatchingThread, 0) == WAIT_TIMEOUT); 
} 
// Ask for the thread to stop and waith until it ends 
void FileWatcher::SynchronousAbort() 
{ 
    SetEvent(hEvtStopWatching); 
    if (hWatchingThread) 
    { 
     WaitForSingleObject(hWatchingThread, INFINITE); 
     CloseHandle(hWatchingThread); 
     Sleep(500); 
     hWatchingThread = NULL; 
    } 
    CloseHandle(overl.hEvent); 
    overl.hEvent = NULL; 
    CloseHandle(hDir); 
    hDir = NULL; 
} 
// Start watching a file for changes 
void FileWatcher::StartWatchThread() 
{ 
    // if the thread already exists then stop it 
    if (IsThreadRunning()) 
     SynchronousAbort(); 
    assert(hDir); 
    if (!hDir) 
    { 
     return; 
    } 
    // reset the hEvtStopWatching event so that it can be set if 
    // some thread requires the watching thread to stop 
    ResetEvent(hEvtStopWatching); 
    DWORD watchingthreadID; 
    hWatchingThread = CreateThread(NULL, 0, WatchingThread, this, 0, &watchingthreadID); 
} 
void FileWatcher::Init(const TCHAR* fileFullPath) 
{ 
    // if the thread already exists then stop it 
    if (IsThreadRunning()) 
     SynchronousAbort(); 
    // str::ReplacePtr(&filePath, fileFullPath); 
    //TCHAR *dirPath = path::GetDir(filePath); 
    hDir = CreateFile(
     L"C:\\", // pointer to the directory containing the tex files 
     FILE_LIST_DIRECTORY,    // access (read-write) mode 
     FILE_SHARE_READ|FILE_SHARE_DELETE|FILE_SHARE_WRITE, // share mode 
     NULL, // security descriptor 
     OPEN_EXISTING, // how to create 
     FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OVERLAPPED , // file attributes 
     NULL); // file with attributes to copy 
    // free(dirPath); 
    ZeroMemory(&overl, sizeof(overl)); 
    ZeroMemory(buffer, sizeof(buffer)); 
    overl.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL); 
    // watch the directory 
    ReadDirectoryChangesW(
     hDir, /* handle to directory */ 
     &buffer[curBuffer], /* read results buffer */ 
     sizeof(buffer[curBuffer]), /* length of buffer */ 
     FALSE, /* monitoring option */ 
     //FILE_NOTIFY_CHANGE_CREATION| 
     FILE_NOTIFY_CHANGE_LAST_WRITE, /* filter conditions */ 
     NULL, /* bytes returned */ 
     &overl, /* overlapped buffer */ 
     NULL); /* completion routine */ 
} 
// Thread responsible of watching the directory containg the file to be watched for modifications 
DWORD WINAPI WatchingThread(void *param) 
{ 
    //qDebug()<<"in WatchingThread"; 
    FileWatcher *fw = (FileWatcher *)param; 
    HANDLE hp[2] = { fw->hEvtStopWatching, fw->overl.hEvent }; 
    for (;;) 
    { 
     DWORD dwObj = WaitForMultipleObjects((sizeof(hp)/(sizeof(hp[0]))) 
              , hp, FALSE, INFINITE); 
     if (dwObj == WAIT_OBJECT_0) // the user asked to quit the program 
     { 
      //qDebug()<<"in WatchingThread the user asked to quit the program"; 
      //exit(-1); 
      break; 
     } 
     if (dwObj != WAIT_OBJECT_0 + 1) 
     { 
      // BUG! 
      //assert(0); 
      // qDebug()<<"dwObj "<<dwObj<<" last error "<<GetLastError(); 
      break; 
     } 
     //qDebug()<<"WatchingThread fw->NotifyChange() "; 
     //if (fw->wakeup) 
     fw->NotifyChange(); 
    } 
    return 0; 
} 
// Call ReadDirectoryChangesW to check if the file has changed since the last call. 
bool FileWatcher::CheckForChanges(DWORD waittime) 
{ 
    if (!overl.hEvent) 
    { 
     return false; 
    } 
    DWORD dwObj = WaitForSingleObject(overl.hEvent, waittime); 
    if (dwObj != WAIT_OBJECT_0) 
    { 
     return false; 
    } 
    return NotifyChange(); 
} 
// Call the ReadDirectory API and determine if the file being watched has been modified since the last call. 
// Returns true if it is the case. 
bool FileWatcher::NotifyChange() 
{ 
    //qDebug()<<"in NotifyChange"; 
    DWORD dwNumberbytes; 
    GetOverlappedResult(hDir, &overl, &dwNumberbytes, FALSE); 
    FILE_NOTIFY_INFORMATION *pFileNotify = (FILE_NOTIFY_INFORMATION *)buffer[curBuffer]; 
    // Switch the 2 buffers 
    curBuffer = (curBuffer + 1) % (sizeof(buffer)/(sizeof(buffer[0]))); 
    SecureZeroMemory(buffer[curBuffer], sizeof(buffer[curBuffer])); 
    // start a new asynchronous call to ReadDirectory in the alternate buffer 
    ReadDirectoryChangesW(
     hDir, /* handle to directory */ 
     &buffer[curBuffer], /* read results buffer */ 
     sizeof(buffer[curBuffer]), /* length of buffer */ 
     TRUE, /* monitoring option */ 
     FILE_NOTIFY_CHANGE_FILE_NAME | 
      FILE_NOTIFY_CHANGE_DIR_NAME | 
      FILE_NOTIFY_CHANGE_ATTRIBUTES | 
      FILE_NOTIFY_CHANGE_SIZE | 
      FILE_NOTIFY_CHANGE_LAST_WRITE | 
      FILE_NOTIFY_CHANGE_LAST_ACCESS | 
      FILE_NOTIFY_CHANGE_CREATION | 
      FILE_NOTIFY_CHANGE_SECURITY, 
     //FILE_NOTIFY_CHANGE_LAST_WRITE, /* filter conditions */ 
     NULL, /* bytes returned */ 
     &overl, /* overlapped buffer */ 
     NULL); /* completion routine */ 
    // Note: the ReadDirectoryChangesW API fills the buffer with WCHAR strings. 
    for (;;) 
    { 
     if (pFileNotify->Action == FILE_ACTION_ADDED) 
     { 
      //qDebug()<<"in NotifyChange if "; 
       char szAction[42]; 
       char szFilename[MAX_PATH] ; 
       memset(szFilename,'\0',sizeof(szFilename)); 
       strcpy(szAction,"added"); 
       wcstombs(szFilename, pFileNotify->FileName, MAX_PATH); 
       if(observer) 
        observer->OnFileChanged(); 
       return true; 
       //OnFileChanged(szFilename,szAction); 
       // qDebug()<<"in NotifyChange after OnFileChanged "; 
     } 
     // step to the next entry if there is one 
     if (!pFileNotify->NextEntryOffset) 
     { 
      return false; 
     } 
     pFileNotify = (FILE_NOTIFY_INFORMATION *)((PBYTE)pFileNotify + pFileNotify->NextEntryOffset); 
    } 
    pFileNotify=NULL; 
    return true; 
} 

Dans le programme principal, je:

case IDM_ABOUT: 
      //DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About); 
      { 
       FileWatcher *cWatcher = new FileWatcher(); 
      cWatcher->Init(L"AB"); 
      cWatcher->NotifyChange(); 
      break; 
      } 

J'ai une erreur messeage que: violation d'accès lecture emplacement 0xba2f1498. Quelle est la solution?

+3

Personne ne va démêler ce gâchis. Vous devez fournir la trace du débogueur. Le problème se résume à accéder à la mémoire que vous n'êtes pas censé accéder, mais il est difficile de dire où exactement, sauf si vous postez la trace du débogueur. Alors développez votre question pour obtenir de l'aide. –

+0

Je vois un 'delete observer' et' free (filePath) 'mais pas de code qui alloue de la mémoire pour l'un ou l'autre, outre le fait que vous mélangez l'allocation de style c et l'allocation de style C++ ensemble. –

+0

@Haroogan Je veux changer de répertoire, puis-je utiliser ce code? tout changement dans le dossier: supprimer le dossier, nouveau dossier, renommer ... Je ne sais pas comment les attraper. – user2284783

Répondre

1

Dans votre destructor vous avez:

delete observer; 
free(filePath); 

mais vous ne cochez pas pour vous assurer que l'un est affecté à l'avance qui est clairement un problème, d'autant plus que votre constructeur par défaut n'initialise pas une de ces variables. C'est au-delà du fait que vous mélangez l'allocation de style C avec l'allocation de style C++.

+0

Je ne sais pas comment appeler la fonction pour regarder le changement de dossier dans le principal. Je le trouve dans: [link] (https://github.com/kzmkv/SumatraPDF/tree/master/src). Je veux après, cliquez sur Aide/À propos de nous pouvons regarder tout changement dans C: lecteurs – user2284783

3

Vous avez un constructeur par défaut qui laisse toutes vos variables non initialisées.

FileWatcher() 
{ 
} 

Qui est utilisé ici.

  FileWatcher *cWatcher = new FileWatcher(); 
     cWatcher->Init(L"AB"); 

Init laisse également plusieurs variables non initialisées, telles que curBuffer dans cette ligne.

 &buffer[curBuffer], /* read results buffer */ 

C'est probablement pourquoi vous obtenez Access violation reading location 0xba2f1498

Une bonne pratique serait de vous assurer que votre objet est toujours tout à fait valable avant que le constructeur se termine.

+0

Que dois-je faire? Merci – user2284783

+0

@ user2284783 Vous devez modifier votre constructeur pour initialiser ** toutes ** les variables membres qui ne seraient pas valides si elles n'étaient pas initialisées. Ce qui signifie généralement * tous *. –

+0

@ user2284783 Par exemple, il semblerait que votre code se casse si 'curBuffer' n'est pas' 0' ou '1'. Alors, prenez des mesures pour vous assurer que c'est l'un de ceux-là. –

Questions connexes