自定义排序函数中的堆溢出

时间:2018-10-10 16:38:58

标签: c++ sorting

嗨,我在简单的程序上苦苦挣扎,该程序对整数数组进行lex排序

(完整程序在这里:https://pastebin.com/UMqEP62n

在足够大的整数向量上运行排序会导致随机数出现在数组中,然后取决于导致段错误的数据。

sort(nums.begin(), nums.end(), lex_compare);

比较功能:

bool lex_compare(const int &a, const int &b) {
    int ap = a, bp = b;
    vector<int> da, db;

    if (ap == 0) da.insert(da.begin(), ap%10);
    while (ap > 0) {
        da.insert(da.begin(), ap%10);
        ap /= 10;
    }
    if (bp == 0) db.insert(db.begin(), bp%10);
    while (bp > 0) {
        db.insert(db.begin(), bp%10);
        bp /= 10;
    }
    size_t size;
    if (da.size() < db.size()) {
        size = da.size();
    } else {
        size = db.size();
    }

    for (size_t i = 0; i < size; ++i)
        if (da[i] > db[i])
            return true;
        else if (da[i] < db[i])
            return false;
        else
            continue;

    if (da.size() > db.size())
        return false;
    else
        return true;
}

基本上,当数组太长时,由于堆缓冲区溢出,会出现内存损坏。使用地址Sanitizer编译时,它显示:

==4097==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x6140000001d0 at pc 0x00010aa396fe bp 0x7ffee51c5c50 sp 0x7ffee51c5c48
READ of size 4 at 0x6140000001d0 thread T0
#0 0x10aa396fd in lex_compare(int const&, int const&) main.cpp:8  

实质上是lex_compare函数的第一行:

int ap = a, bp = b;

在这里我无法弄清楚哪种错误会导致这种现象?是由于比较功能的大小吗?还是我有一些明显的内存读取错误?我使用的是clang 4.2.1,但其他平台也会引起相同的行为,因此我认为排序功能存在根本性的错误。

1 个答案:

答案 0 :(得分:5)

您的问题是您违反了compare requirement的要求,传递给std::sort的比较函数必须遵循。

比较要求要求如果为comp(a,b)==true,则为comp(b,a)==false,但比较函数不能执行此操作。例如,如果a = 0b = 0,那么comp(a, b)会将您带到

if (da.size() > db.size())
    return false;
else
    return true;

比较功能的一部分。由于大小相等,因此返回true。当我们翻转它并评估comp(b, a)时,我们会到达相同的块,并将再次返回true

您需要在false时返回a == b,但您不这样做。