当我尝试对字符串向量应用大于比较函数的排序时,我最近遇到了一个非常奇怪的c ++ STL排序行为,详细的实现可以在下面找到:
//Compare the modify time of two files
bool cmp_modifytime(const base::String &file1, const base::String &file2)
{
struct stat statbuf1, statbuf2;
stat(file1.getBuffer(), &statbuf1);
stat(file2.getBuffer(), &statbuf2);
return statbuf1.st_mtime > statbuf2.st_mtime;
}
主要例程:
std::vector<base::String> lFiles;
getFilesFromDir(dir, lFiles);
int fileCount = lFiles.size();
for(int i = 0; i <fileCount; i++)
{
tmp_str = dir;
tmp_str.append("/");
tmp_str.append(lFiles[i]);
lFiles[i] = tmp_str;
}
sort(lFiles.begin(), lFiles.end(), cmp_modifytime);
当我解码崩溃时,回溯看起来如下:
#0 0xf49a8940 in typeinfo for base::AString () from xxx
#1 0xf4919262 in cmp_modifytime (file1=..., file2=...) at xxx
#2 0xf491f91a in std::__unguarded_partition<__gnu_cxx::__normal_iterator<base::String*, std::vector<base::String> >, base::String, bool (*)(base::String const&, base::String const&)> (__first=..., __last=..., __pivot=..., __comp=0xf491923b <cmp_modifytime(base::String const&, base::String const&)>)
at xxx
#3 0xf491e5da in std::__unguarded_partition_pivot<__gnu_cxx::__normal_iterator<base::String*, std::vector<base::String> >, bool (*)(base::String const&, base::String const&)>
(__first=..., __last=..., __comp=0xf491923b <cmp_modifytime(base::String const&, base::String const&)>)
at xxx
#4 0xf491d0cc in std::__introsort_loop<__gnu_cxx::__normal_iterator<base::String*, std::vector<base::String> >, int, bool (*)(base::String const&, base::String const&)> (
__first=..., __last=..., __depth_limit=7, __comp=0xf491923b <cmp_modifytime(base::String const&, base::String const&)>)
at xxx
#5 0xf491d0ef in std::__introsort_loop<__gnu_cxx::__normal_iterator<base::String*, std::vector<base::String> >, int, bool (*)(base::String const&, base::String const&)> (
__first=..., __last=..., __depth_limit=8, __comp=0xf491923b <cmp_modifytime(base::String const&, base::String const&)>)
at xxx
#6 0xf491d0ef in std::__introsort_loop<__gnu_cxx::__normal_iterator<base::String*, std::vector<base::String> >, int, bool (*)(base::String const&, base::String const&)> (
__first=..., __last=..., __depth_limit=9, __comp=0xf491923b <cmp_modifytime(base::String const&, base::String const&)>)
at xxx
#7 0xf491c198 in std::sort<__gnu_cxx::__normal_iterator<base::String*, std::vector<base::String> >, bool (*)(base::String const&, base::String const&)> (__first=...,
__last=..., __comp=0xf491923b <cmp_modifytime(base::String const&, base::String const&)>)
at xxx
#8 0xf4919521 in main routine
崩溃发生在compare函数中,有趣的是我发现其中一个输入String对象是一个空字符串:
(gdb) p file1
$1 = (const base::String &) @0x11db6180: {<base::Object> = {_vptr.Object = 0xf49a88e8}, <base::AString> = {_vptr.AString = 0xf49a8908}, buffer = 0x0, hashValue = 4294967295, size = -1, immutable = false}
(gdb) p file2
$2 = (const base::String &) @0x11db5f58: {<base::Object> = {_vptr.Object = 0xf49a8888}, <base::AString> = {_vptr.AString = 0xf49a88c8}, buffer = 0x11db6ba8 "testString123", hashValue = 4294967295, size = 13, immutable = false}
(gdb) p &file2
$3 = (const base::String *) 0x11db5f58
(gdb) p &file1
$4 = (const base::String *) 0x11db6180
更有趣的是,这个空字符串地址与我尝试进行排序的向量的_M_finish相同,这意味着以某种方式排序将vector.end()带入compare函数:
(gdb) p lFiles._M_impl._M_finish
$7 = (std::allocator<base::String>::pointer) 0x11db6180
这绝不应该在我的理解中发生。