0

我正在阅读愚蠢的源代码。当我阅读 fbstring 的实现时,我对 initsmall 函数的实现感到困惑。
如果bytesize为 17,wordsize为 8,则(byteSize + wordWidth-1) / wordWidth为 3。reinterpret_cast<const size_t >(data)[2]是否访问data的第 17 个 char 元素和以下 7 个元素?不会越界了吧?
下面是实现代码,完整代码在https://github.com/facebook/folly/blame/master/folly/FBString.h

// Small strings are bitblitted
template <class Char>
inline void fbstring_core<Char>::initSmall(
    const Char* const data, const size_t size) {
  // Layout is: Char* data_, size_t size_, size_t capacity_
  static_assert(
      sizeof(*this) == sizeof(Char*) + 2 * sizeof(size_t),
      "fbstring has unexpected size");
  static_assert(
      sizeof(Char*) == sizeof(size_t), "fbstring size assumption violation");
  // sizeof(size_t) must be a power of 2
  static_assert(
      (sizeof(size_t) & (sizeof(size_t) - 1)) == 0,
      "fbstring size assumption violation");

// If data is aligned, use fast word-wise copying. Otherwise,
// use conservative memcpy.
// The word-wise path reads bytes which are outside the range of
// the string, and makes ASan unhappy, so we disable it when
// compiling with ASan.
#ifndef FOLLY_SANITIZE_ADDRESS
  if ((reinterpret_cast<size_t>(data) & (sizeof(size_t) - 1)) == 0) {
    const size_t byteSize = size * sizeof(Char);
    constexpr size_t wordWidth = sizeof(size_t);
    switch ((byteSize + wordWidth - 1) / wordWidth) { // Number of words.
      case 3:
        ml_.capacity_ = reinterpret_cast<const size_t*>(data)[2];
        FOLLY_FALLTHROUGH;
      case 2:
        ml_.size_ = reinterpret_cast<const size_t*>(data)[1];
        FOLLY_FALLTHROUGH;
      case 1:
        ml_.data_ = *reinterpret_cast<Char**>(const_cast<Char*>(data));
        FOLLY_FALLTHROUGH;
      case 0:
        break;
    }
  } else
#endif
  {
    if (size != 0) {
      fbstring_detail::podCopy(data, data + size, small_);
    }
  }
  setSmallSize(size);
}
4

1 回答 1

0

是的,它会超出范围。这就是为什么它在编译器投诉的情况下使用 FOLLY_SANITIZE_ADDRESS 的原因。如果编译器对此没有问题,那么它会复制单词,尽管它复制的大小超过了您需要的大小。但是由于 setSmallSize() 可以告诉您字符串的大小,因此额外复制的字节可以放入字符串缓冲区但不会被读取。

于 2022-01-10T02:16:55.057 回答