문제

I'm trying to use std::sort on a data type that contains information read from a boost::filesystem::dictionary_iterator. It appears that as the sorting algorithm has done n comparisons, n being the number of files in the directory, that information gets lost and I end up segfaulting. Valgrind says I'm using uninitialized values and doing invalid reads.

How can I change my File data type or algorithms so that the information is kept between passes?

#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;
}

(This is not my actual program, but exhibits the same behavior.)

도움이 되었습니까?

해결책

The call to compare() at the end is wrong, it returns an int that can be -1, 0 or 1 like strcmp(). Use a simple call to std::less()(a_filename, b_filename) instead. Also make sure you have unit tests that make sure the comparator creates a strict-weak ordering, as is required for std::sort.

Comparator with internal checking:

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;
}

If NDEBUG is defined (i.e. assert() deactivated) the compiler should be able to optimize this to the same amount of code as before. And now, I wish you much fun writing the code that sorts the filenames 9.png, 10.png and 11.png in that order. ;)

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top