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

2023-11-21

考虑:

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

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

n1570 7.24.4.1 PDF link

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

The memcmp函数比较第一个n所指向对象的字符s1到指向的对象的前 n 个字符s2

我的理解是否正确,该标准将行为描述为阅读所有内容n两个参数的字节,但是库可以像它们那样短路吗?


该功能不能保证短路,因为标准没有规定必须短路。

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

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

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

这是它可能崩溃的证据:https://ideone.com/8jTREr

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

std::memcmp 可以读取第一个差异之后的任何字节吗? 的相关文章

随机推荐