std :: memcmp可以读取超过第一个差异的任何字节吗?

时间:2018-04-04 23:20:21

标签: c++

考虑:

constexpr char s1[] = "a";
constexpr char s2[] = "abc";
std::memcmp(s1, s2, 3);

如果memcmp在它看到的第一个差异处停止,它将不会读取超过s1的第二个字节(nul终结符),但是我没有看到C标准中的任何内容来确认此行为,并且我不知道C ++中的任何扩展它的东西。

  

n1570 7.24.4.1 PDF link

     

int memcmp(const void *s1, const void *s2, size_t n);

     

memcmp函数将n指向的对象的第一个s1字符与s2指向的对象的前n个字符进行比较

我的理解是否正确,标准将行为描述为读取两个参数的所有n个字节,但是库可能会短路 - 如果它们发生了?

1 个答案:

答案 0 :(得分:5)

该功能无法保证短路,因为标准并未说明必须。

不仅不能保证短路,而且在实践中许多实现都不会。例如,glibc比较类型unsigned long int的元素(最后几个字节除外),因此它可以读取超过该位置的7个字节,在64位实现上进行不同的比较。

有些人可能认为这不会导致平台glibc目标上的访问冲突,因为对这些unsigned long int的访问将始终对齐,因此不会跨越页面边界。但是当两个源具有不同的对齐时,glibc将从其中一个源读取两个连续的unsigned long int s,这些源可能位于不同的页面中。如果不同的字节位于第一个字节中,则在glibc执行比较之前仍然可以触发访问冲突(参见函数memcmp_not_common_alignment)。

简而言之:即使在此长度之前出现不同的字节,指定小于缓冲区实际大小的长度也是未定义的行为,并且可能导致常见实现崩溃。

以下是可以崩溃的证据:https://ideone.com/8jTREr