簡體   English   中英

調試錯誤R6010-已調用abort()

[英]Debug error R6010 - abort() has been called

我正打算制作一個程序,輸出該文件所在文件夾中所有文件的名稱,如果其中兩個文件的大小相同,則僅輸出一個文件。 請注意,我是Boost庫的新手,而不是經驗豐富的程序員。

這是我想出的:

#include <boost/filesystem.hpp>      
#include <iostream>
#include<string>
#include<cstdio>
using namespace std;
void files(string a = ".")
{
bool check = 1;
boost::filesystem::directory_iterator iterator(a);

for (; iterator != boost::filesystem::directory_iterator(); ++iterator)
{

    if (is_directory(iterator->path()))
    {
        files(iterator->path().string());
    }
    else
    {
        boost::filesystem::directory_iterator iterator2(a);
        iterator2 = iterator;
        if (iterator != boost::filesystem::directory_iterator())
        {
            iterator2++;
        }
        for (; iterator2 != boost::filesystem::directory_iterator(); ++iterator2)
        {
            if (file_size(iterator->path()) == file_size(iterator2->path()))
            {
                check = 0;
            }
        }
    }
    if (check == 1)
    {

        cout << (iterator->path().filename()) << endl;
    }
    else
    {
        check = 1;
    }
}
}


int main()
{
files();
}

我試圖使其無例外地列出所有文件,並且工作正常,但是當我添加第二個for循環和第二個directory_iterator時,出現了問題。

潛在的問題是, boost::filesystem::directory_iterator是一個輸入迭代器,不能保證保持相等性:請參閱directory_iterator文檔中的注釋。

在實現中,很可能使用的是POSIX opendirreaddir接口之類的東西,其中有一個底層的打開文件描述符,從該目錄中依次讀取目錄條目。

因此,推進iterator2 (可能在分配后與iterator1共享相同的基礎狀態)可能會更改iterator1還將返回的內容。

確實,在我的測試平台(Linux,g ++)上,在iterator2循環完成且iterator2等於最終迭代器之后, iterator1也等於最終迭代器,並且程序在嘗試訪問文件名時會出現段錯誤。

簡而言之,即使並不清楚情況確實如此,iterator2和iterator1也沒有獨立的狀態。 要變通解決此問題,最簡單的方法是記錄您在std::set (或C ++ 11中的std::unordered_set中看到的文件大小,並僅在該集合尚不包含路徑時打印路徑該文件的大小。

我在這里包括了一個使用std::set來執行此操作的版本。 為簡單起見,我將遞歸關系省略到了子目錄中。 您需要確定是否要忽略與同一子目錄中的文件或任何子目錄中的文件具有相同大小的文件。

#include <boost/filesystem.hpp>      
#include <iostream>
#include <string>
#include <set>

using namespace std;
void files(string a = ".")
{
    boost::filesystem::directory_iterator iterator(a),dir_end;
    std::set<uintmax_t> file_sizes;

    for (; iterator != dir_end; ++iterator) {
        bool emit = true;

        if (!is_directory(iterator->path())) {
            uintmax_t size = file_size(iterator->path());
            if (file_sizes.find(size) == file_sizes.end()) {
                // set does not contain this file size yet.
                file_sizes.insert(size);
            }
            else {
                // set already contains this file size, so don't print path
                emit = false;
            }
        }

        if (emit) {
            cout << (iterator->path().filename()) << endl;
        }
    }
}

int main() {
    files();
}

我自己做這個是手指運動。

我意識到它可能太普通/太復雜(例如,它可以很好地處理由於權限問題而導致文件大小失敗的情況),但也許您仍然可以從中得到一些啟發:

生活在Coliru

#include <boost/filesystem.hpp>
#include <boost/range/adaptors.hpp>
#include <boost/range/algorithm.hpp>
#include <map>
#include <iostream>
#include <string>
#include <cstdio>

namespace fs = boost::filesystem;

template <
    typename KeyFunc,
    typename OutputUnique,
    typename HandleDupe,
    typename Path = boost::filesystem::path,
    typename KeyType = decltype(std::declval<KeyFunc>()(Path{})),
    typename Record = std::pair<boost::optional<KeyType> const, Path>
>
void files(std::string const& curdir, OutputUnique output, KeyFunc const& key, HandleDupe const& handler)
{
    using namespace boost::adaptors;
    using namespace boost;

    using path  = fs::path;
    using paths = std::vector<path>;

    auto safe_key = [&key](path const& p) { 
        optional<KeyType> sz;
        try { sz = key(p); } catch(...) { }
        return std::make_pair(sz, p); 
    };

    std::function<void(path const&)> recurse = [&](path const& curdir) {
        paths files;
        paths dirs;

        std::map<optional<KeyType>, path> seen;

        try {
            auto entries 
                = make_iterator_range(fs::directory_iterator(curdir), {})
                | transformed(std::mem_fn(&fs::directory_entry::path))
                ;

            std::partition_copy(
                    entries.begin(), entries.end(),
                    back_inserter(dirs),
                    back_inserter(files),
                    [](path const& p) { return is_directory(p); }
                );

            for(auto& f: files) {
                auto insertion = seen.insert(safe_key(f));

                if (!insertion.second && insertion.first->first)
                    handler(*insertion.first, safe_key(f));
                else
                    *output++ = f;
            }

            boost::for_each(dirs, recurse);
        } catch(std::exception const& e) {
            std::cerr << "Skipping " << curdir << ": " << e.what() << "\n";
        }
    };

    recurse(curdir);
}

template <typename OutputUnique = std::ostream_iterator<fs::path> >
void files(std::string const& curdir = ".", OutputUnique output = std::ostream_iterator<fs::path>(std::cout, "\n"))
{
    using fs::path;
    using Record = std::pair<boost::optional<size_t> const, path>;
    files(
            curdir,
            output, 
            [](path const&p) { return file_size(p); },
            [](Record const&, Record const&) { }
         );
}

#include <boost/function_output_iterator.hpp>

int main() { 
    files("."); // prints non-dupes recursively

    // advanced use: print nothing for non-dupes, but print the duplicate pairs
    auto devnull = boost::make_function_output_iterator([](fs::path){});
    files(".", 
            devnull,                                     // back_inserter(some_vector), etc.
            [](fs::path const& p){return file_size(p);}, // some other key? 
            [](auto const& dupe, auto const& orig) {
                std::cout << "Duplicate size (" << *dupe.first << ") in " << dupe.second << "\n"
                          << "\tOriginal: " << orig.second << "\n";
            }); 
}

打印

"./main.cpp"
"./a.out"
Duplicate size (3208) in "./main.cpp"
    Original: "./dupe.cpp"

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM