Why abort() method is called sometimes when I iterate over directory using std::filesystem::directory_terator?

  abort, c++, c++17, iterator, std-filesystem

I am creating a simple file watcher in C++. I am using std::filesystem::directory_iterator and sometimes it crashes with abort() method being called. It perfectcly works when I track creating and editing of files (which is not strange because for that I use map::iterator). But when I need to track deleting and renaming of the file directory_iterator tends to crash sometimes. The thing is it can work for several times and then crash. And the number of times is always different. I have already commented out the code that can possibly cause the problem, so the problem is definitly in the directory iterator. What can possibly be the problem.

Here is the header of the file, if it’s relevant.

#ifndef FILEWATCHER_H
#define FILEWATCHER_H
#include <map>
#include <filesystem>

namespace fs = std::filesystem;

class FileWatcher
{
    size_t currentNumberOfFiles = 0;
    fs::path pathToWatch;
    std::map<fs::path, fs::file_time_type> pathsMap;
    std::string currentTime();
public:
    FileWatcher(fs::path path);
    void start();
};

#endif

And the .cpp file

#pragma warning(disable : 4996)
#include "FileWatcher.h"
#include "Event.h"
#include <iostream>

std::string FileWatcher::currentTime()
{
    auto now = std::chrono::system_clock::now();
    std::time_t nowTime = std::chrono::system_clock::to_time_t(now);
    std::string currentSystemTime = std::ctime(&nowTime);
    return currentSystemTime;
}

FileWatcher::FileWatcher(fs::path pathToWatch)
{
    this->pathToWatch = pathToWatch;
    //create a map with last modification of a given file in the directory
    for (auto& file : fs::directory_iterator(this->pathToWatch))
    {
        pathsMap.emplace(file.path(), fs::last_write_time(file));
    }
}

void FileWatcher::start()
{
    while (true)
    {
        currentNumberOfFiles = std::distance(fs::directory_iterator(pathToWatch), fs::directory_iterator());
        
        auto it = pathsMap.begin();
        while (it != pathsMap.end())
        {
            if (!fs::exists(it->first.string()))
            {
                if (currentNumberOfFiles < pathsMap.size())
                {
                    //file deleted
                    //FileType fileType = (fs::is_regular_file(it->first) ? FileType::FILE : FileType::DIRECTORY);
                    //Event event(EventType::DELETED, fileType, it->first, currentTime());
                    //event.printEvent();
                    std::cout << "Remove" << std::endl;
                    it = pathsMap.erase(it);
                    break;
                }
                else
                {

                    //file is renamed
                    //ileType fileType = (fs::is_regular_file(it->first) ? FileType::FILE : FileType::DIRECTORY);
                    //Event event(EventType::RENAMED, fileType, it->first, currentTime());
                    //event.printEvent();
                    std::cout << "Renamed" << std::endl;
                    it = pathsMap.erase(it);
                    break;
                }
            }
            else
            {
                it++;
            }
        }

        for (auto& file : fs::directory_iterator(pathToWatch))
        {
            if (pathsMap.count(file.path()) == 0)
            {

                //file is create
                pathsMap.emplace(file.path(), fs::last_write_time(file));
                //FileType fileType = (fs::is_regular_file(file) ? FileType::FILE : FileType::DIRECTORY);
                //Event event(EventType::CREATED, fileType, file.path(), currentTime());
                //event.printEvent();
                std::cout << "Created" << std::endl;
                break;
            }
            else
            {
                if (pathsMap[file.path()] != fs::last_write_time(file))
                {

                    //file is modified
                    //pathsMap.emplace(file.path(), fs::last_write_time(file));
                    pathsMap[file.path()] = fs::last_write_time(file.path());
                    //FileType fileType = (fs::is_regular_file(file.path()) ? FileType::FILE : FileType::DIRECTORY);
                    //Event event(EventType::EDITED, fileType, file.path(), currentTime());
                    //event.printEvent();
                    std::cout << "Modified" << std::endl;
                    break;
                }
            }
        }
    }
}

I will also attach abort() message which is produced.
abort() message

Visual Studio 2019 doesn’t produce any errors to the output log.

Source: Windows Questions C++

LEAVE A COMMENT