C++标准库中对std::string使用不合法(空指针或不以'\0'结尾)的c风格字符串(c style string)初始化的处理


使用c风格字符串初始化std::string时存在两种可能的错误情况:

  1. 传入空指针,
  2. 传入的c风格字符串不以'\0'结尾。

g++ (GCC) 11.2.0 中,使用c风格字符串初始化 std::string(basic_string)的代码如下:

basic_string(const _CharT* __s, const _Alloc& __a = _Alloc())
    : _M_dataplus(_M_local_data(), __a)
    {
        const _CharT* __end = __s ? __s + traits_type::length(__s)
            // We just need a non-null pointer here to get an exception:
            : reinterpret_cast<const _CharT*>(__alignof__(_CharT));
        _M_construct(__s, __end, random_access_iterator_tag());
    }

第4-6行的三目运算符作用如下:如果__s是一个空指针,则将__end设置为1;否则调用下列函数(进而调用libc中的strlen。错误1使用不以'\0'结尾的字符串调用strlen是未定义行为(The behavior is undefined if str is not a pointer to a null-terminated byte string.https://en.cppreference.com/w/c/string/byte/strlen)),将__end设置为满足迭代器要求的指针位置(字符串末尾'\0'的位置)。

static _GLIBCXX17_CONSTEXPR size_t
    length(const char_type* __s)
{
    #if __cplusplus >= 201703L
    if (__constant_string_p(__s))
        return __gnu_cxx::char_traits<char_type>::length(__s);
    #endif
    return __builtin_strlen(__s);
}

_M_construct进一步调用下列函数,错误2如果第一步传入的__s为空指针,这里第9-11行会抛出异常.

经过一系列错误检查,在17行创建内部c string空间,在23行进行字符串拷贝

template<typename _CharT, typename _Traits, typename _Alloc>
template<typename _InIterator>
void
basic_string<_CharT, _Traits, _Alloc>::
_M_construct(_InIterator __beg, _InIterator __end,
             std::forward_iterator_tag)
{
    // NB: Not required, but considered best practice.
    if (__gnu_cxx::__is_null_pointer(__beg) && __beg != __end)
        std::__throw_logic_error(__N("basic_string::"
                                     "_M_construct null not valid"));

    size_type __dnew = static_cast<size_type>(std::distance(__beg, __end));

    if (__dnew > size_type(_S_local_capacity))
    {
        _M_data(_M_create(__dnew, size_type(0)));
        _M_capacity(__dnew);
    }

    // Check for out_of_range and length_error exceptions.
    __try
    { this->_S_copy_chars(_M_data(), __beg, __end); }
    __catch(...)
    {
        _M_dispose();
        __throw_exception_again;
    }

    _M_set_length(__dnew);
}


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM