【发布时间】:2018-10-10 16:38:58
【问题描述】:
您好,我在处理对整数数组进行 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;
}
基本上,当数组太长时,由于堆缓冲区溢出,内存损坏就会出现。使用地址消毒器编译时显示:
==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,但其他平台也会导致相同的行为,所以我认为排序功能存在根本性问题。
【问题讨论】:
-
代表为 375,此时您应该知道不应使用“pastebin”链接。
-
+ 用于重现此“堆缓冲区溢出”的输入丢失。
-
为什么有这么多复杂的代码而不是
return std::to_string(a) < std::to_string(b);?并通过 const 引用传递int只是为了在第一行制作本地副本... -
这也可能被证明是有用的。 stackoverflow.com/questions/18291620/…
-
根据我之前的经验,“比较器堆溢出”错误中的可能问题几乎总是比较器代码中的错误。比较器中不正确或遗漏的条件会导致重复调用比较器以对数组进行排序,但该数组永远不会完成,从而导致内存泄漏。