terminating with uncaught exception of type std::length_error: basic_string

前言

最近fix一个崩溃问题,崩溃关键信息如标题如示,具体的原因调用:assign(const value_type* __s, size_type __n)时第二个参数传了负数,负数赋值到无符号long时就是一个很大的正数了!

basic_string<_CharT, _Traits, _Allocator>&
basic_string<_CharT, _Traits, _Allocator>::assign(const value_type* __s, size_type __n)
{
    _LIBCPP_ASSERT(__n == 0 || __s != nullptr, "string::assign received nullptr");
    size_type __cap = capacity();
    if (__cap >= __n)
    {
        value_type* __p = _VSTD::__to_raw_pointer(__get_pointer());
        traits_type::move(__p, __s, __n);
        traits_type::assign(__p[__n], value_type());
        __set_size(__n);
        __invalidate_iterators_past(__n);
    }
    else
    {
        size_type __sz = size();
        __grow_by_and_replace(__cap, __n - __cap, __sz, 0, __sz, __n, __s);
    }
    return *this;
}

void
basic_string<_CharT, _Traits, _Allocator>::__grow_by_and_replace
    (size_type __old_cap, size_type __delta_cap, size_type __old_sz,
     size_type __n_copy,  size_type __n_del,     size_type __n_add, const value_type* __p_new_stuff)
{
    size_type __ms = max_size();
    if (__delta_cap > __ms - __old_cap - 1)
        this->__throw_length_error(); //这里抛异常,导致崩溃
    pointer __old_p = __get_pointer();
    size_type __cap = __old_cap < __ms / 2 - __alignment ?
                          __recommend(_VSTD::max(__old_cap + __delta_cap, 2 * __old_cap)) :
                          __ms - 1;
    pointer __p = __alloc_traits::allocate(__alloc(), __cap+1);
    __invalidate_all_iterators();
    if (__n_copy != 0)
        traits_type::copy(_VSTD::__to_raw_pointer(__p),
                          _VSTD::__to_raw_pointer(__old_p), __n_copy);
    if (__n_add != 0)
        traits_type::copy(_VSTD::__to_raw_pointer(__p) + __n_copy, __p_new_stuff, __n_add);
    size_type __sec_cp_sz = __old_sz - __n_del - __n_copy;
    if (__sec_cp_sz != 0)
        traits_type::copy(_VSTD::__to_raw_pointer(__p) + __n_copy + __n_add,
                          _VSTD::__to_raw_pointer(__old_p) + __n_copy + __n_del, __sec_cp_sz);
    if (__old_cap+1 != __min_cap)
        __alloc_traits::deallocate(__alloc(), __old_p, __old_cap+1);
    __set_long_pointer(__p);
    __set_long_cap(__cap+1);
    __old_sz = __n_copy + __n_add + __sec_cp_sz;
    __set_long_size(__old_sz);
    traits_type::assign(__p[__old_sz], value_type());
}

业务场景

具体的业务场可以抽像成出下示例代码

int main() {
    string test;

    char a[10] {'\0', 'c', 'c', 'b'};

    unsigned long maxSize = -1;
    cout << "size = " << strlen(a) << endl;
    cout << "maxSize = " << maxSize << ", string.max_size = " << test.max_size() << endl;
    test.assign(a, strlen(a) - 1);
}

如上代码的运行结果(macOS上)

/Users/dw_luogongwu/CLionProjects/untitled1/cmake-build-debug/untitled1
size = 0
maxSize = 18446744073709551615, string.max_size = 18446744073709551599
libc++abi.dylib: terminating with uncaught exception of type std::length_error: basic_string

Process finished with exit code 6

terminating with uncaught exception of type std::length_error: basic_string_第1张图片

关键点

  • strlen方法需要特别注意和处理’\0’(字符串结束符)的情况
  • assign方法第二个参数用特别reivew,确保不是一个负数或一个很大的数,最算没有到string.max_size = 18446744073709551599,但是应用也不允许分配那么大的内存的,同样也会崩溃

你可能感兴趣的:(C/C++,Android开发之旅,c++,string,assign,length_error)