【问题标题】:question about fbstring initsmall() method关于 fbstring initsmall() 方法的问题
【发布时间】:2021-05-21 13:19:33
【问题描述】:

我正在阅读愚蠢的源代码。当我阅读 fbstring 的实现时,我对 initsmall 函数的实现感到困惑。
如果 bytesize 为 17,wordsize 为 8,则 (byteSize + wordWidth-1) / wordWidth 为 3。 reinterpret_cast>(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);
}

【问题讨论】:

    标签: c++ string folly


    【解决方案1】:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-05-05
      • 2020-08-01
      • 2011-11-08
      • 2011-02-16
      • 1970-01-01
      • 1970-01-01
      • 2011-03-30
      • 2011-07-25
      相关资源
      最近更新 更多