2

std::sortから読み取った情報を含むデータ型で使用しようとしていboost::filesystem::dictionary_iteratorます。ソート アルゴリズムがディレクトリ内のファイル数をn比較するとn、その情報が失われ、セグメンテーション フォールトが発生するようです。Valgrind は、初期化されていない値を使用していて、無効な読み取りを行っていると言っています。

Fileパス間で情報が保持されるように、データ型またはアルゴリズムを変更するにはどうすればよいですか?

#include <iostream>
#include <algorithm>
#include <vector>
#include <string>
#include <boost/filesystem.hpp>
namespace fs = boost::filesystem;

struct File {
    fs::path path;
    fs::file_status status;
};

bool comp(const File& a, const File& b) {
    static size_t count = 0;
    std::cout << "Compare function called " << ++count << " times" << std::endl;
    std::string a_filename = a.path.filename().native();
    std::string b_filename = b.path.filename().native();
    return a_filename.compare(b_filename);
}

int main() {
    std::vector<File> vec;

    // Read directory
    fs::directory_iterator it("/etc"), end;
    for (; it != end; it++) {
        File f = *(new File);
        f.path = it->path();
        f.status = it->status();
        vec.push_back(f);
    }

    std::sort(vec.begin(), vec.end(), comp);

    // Clean up
    for (std::vector<File>::iterator it = vec.begin(); it != vec.end(); it++)
        delete &(*it);

    return 0;
}

(これは私の実際のプログラムではありませんが、同じ動作を示します。)

4

1 に答える 1

2

最後の compare() の呼び出しは間違っています。strcmp() のように、-1、0、または 1 の int を返します。代わりに std::less()(a_filename, b_filename) への単純な呼び出しを使用してください。また、std::sort に必要なように、コンパレーターが厳密な弱い順序付けを作成することを確認する単体テストがあることを確認してください。

内部チェック付きコンパレータ:

inline bool do_compare(const File& a, const File& b)
{
    /* ... */
} 

bool compare(const File& a, const File& b)
{
    bool const res = do_compare(a, b);
    if(res)
        assert(!do_compare(b, a));
    return res;
}

NDEBUG が定義されている (つまり、assert() が無効化されている) 場合、コンパイラはこれを以前と同じ量のコードに最適化できるはずです。それでは、ファイル名 9.png、10.png、11.png をこの順序で並べ替えるコードを楽しく書いてください。;)

于 2013-03-30T14:16:25.717 に答える