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

Rya*_*ing 7 c++

考虑:

constexpr char s1[] = "a";
constexpr char s2[] = "abc";
std::memcmp(s1, s2, 3);
Run Code Online (Sandbox Code Playgroud)

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

n1570 7.24.4.1 PDF链接

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

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

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

int*_*jay 5

该功能不能保证短路,因为标准没有说它必须.

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

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

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

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