是否为libc++的Bug?std::char_traits::copy断言条件存疑
关于libc++中std::char_traits::copy断言条件的疑问
首先给出libc++中该函数的实现代码:
template <class _CharT> inline _LIBCPP_CONSTEXPR_AFTER_CXX17 _CharT* char_traits<_CharT>::copy(char_type* __s1, const char_type* __s2, size_t __n) { if (!__libcpp_is_constant_evaluated()) { _LIBCPP_ASSERT(__s2 < __s1 || __s2 >= __s1+__n, "char_traits::copy overlapped range"); } char_type* __r = __s1; for (; __n; --__n, ++__s1, ++__s2) assign(*__s1, *__s2); return __r; }
你疑惑这个_LIBCPP_ASSERT的条件是不是写反了,认为应该改成:
__s1 < __s2 || __s1 >= __s2+__n
其实你并没有完全搞反条件,但忽略了两个关键细节:
断言的触发逻辑
_LIBCPP_ASSERT(cond, msg)的规则是:当cond为false时才触发错误提示。原条件__s2 < __s1 || __s2 >= __s1+__n为false的场景是__s1 ≤ __s2 < __s1+__n——也就是源的起始位置落在目标区间内部。这种情况下,正向拷贝会先覆盖源的后续未读取数据,必然导致错误结果,所以断言会触发警告。重叠场景的检查范围
你提出的条件触发错误的场景是__s2 ≤ __s1 < __s2+__n——也就是目标起始落在源区间内部,这种场景下正向拷贝同样会出现数据覆盖问题,但libc的断言并没有检查这一点。原因在于:std::char_traits::copy的规范本身就要求源和目标区间不能重叠(重叠时行为未定义),而libc的这个断言只是做了最低限度的检查,只拦截了最容易引发明显错误的重叠场景(源在目标区间内部),并没有覆盖所有重叠情况。
简单来说,原断言的条件并没有写反,它针对的是「源起始侵入目标区间」的危险场景;你提出的条件针对的是「目标起始侵入源区间」的场景,两者都是需要避免的重叠情况,但libc++的断言只实现了前者的检查。
内容的提问来源于stack exchange,提问作者n.m.is-an-unemployed-ai-agent
相关产品推荐
相关产品推荐

