简单研究一下c++ vector是否会栈溢出

这篇博客通过实例展示了在Linux环境下栈溢出的情况,探讨了栈空间限制(8M)与在main函数中定义大容量char数组导致的段错误。同时,对比了使用std::vector时并不会引发栈溢出,因为vector在堆上分配内存,避免了栈溢出的问题。作者还测试了存放对象的vector,结果同样没有发生栈溢出。通过对std::vector源码的分析,确认了其在堆上分配内存的事实。
摘要由CSDN通过智能技术生成

使用char数组复现问题

我在linux环境下,简单复现了一下栈溢出的情况。首先使用ulimit -a | grep stack得到当前shell下应用程序的栈大小是8192K,也就是8M。在main函数中定义了一个9M空间的char数组。然后编译运行,预期运行时提示段错误。

[root@wxk test]# ulimit -a | grep stack
stack size              (kbytes, -s) 8192
[root@wxk test]# g++ -v
使用内建 specs。
COLLECT_GCC=g++
COLLECT_LTO_WRAPPER=/usr/libexec/gcc/x86_64-redhat-linux/4.8.5/lto-wrapper
目标:x86_64-redhat-linux
配置为:../configure --prefix=/usr --mandir=/usr/share/man --infodir=/usr/share/info --with-bugurl=http://bugzilla.redhat.com/bugzilla --enable-bootstrap --enable-shared --enable-threads=posix --enable-checking=release --with-system-zlib --enable-__cxa_atexit --disable-libunwind-exceptions --enable-gnu-unique-object --enable-linker-build-id --with-linker-hash-style=gnu --enable-languages=c,c++,objc,obj-c++,java,fortran,ada,go,lto --enable-plugin --enable-initfini-array --disable-libgcj --with-isl=/builddir/build/BUILD/gcc-4.8.5-20150702/obj-x86_64-redhat-linux/isl-install --with-cloog=/builddir/build/BUILD/gcc-4.8.5-20150702/obj-x86_64-redhat-linux/cloog-install --enable-gnu-indirect-function --with-tune=generic --with-arch_32=x86-64 --build=x86_64-redhat-linux
线程模型:posix
gcc 版本 4.8.5 20150623 (Red Hat 4.8.5-39) (GCC)
[root@wxk test]#
[root@wxk test]# cat test_stack.cpp
#include <vector>
int main() {
    char a[1024 * 1024 * 9] = {0};
    return 0;
}
[root@wxk test]# g++ -std=c++11 test_stack.cpp
[root@wxk test]# ./a.out
段错误
[root@wxk test]#

使用std::vector是否会导致栈溢出

按我之前的理解,使用vector时应该也会导致栈溢出,实际测试却并不是这样。

[root@wxk test]# ulimit -a | grep stack
stack size              (kbytes, -s) 8192
[root@wxk test]# cat test_stack.cpp
#include <vector>
int main() {
    // char a[1024 * 1024 * 9] = {0};
    std::vector<char> a(1024 * 1024 * 9, 0);
    return 0;
}
[root@wxk test]# g++ -std=c++11 test_stack.cpp
[root@wxk test]# ./a.out
[root@wxk test]#

那么如果vector存的不是基础数据类型,而是对象会怎么样,我改了一下代码,再次验证了一下,结果是一样的,不会栈溢出。

[root@wxk test]# ulimit -a | grep stack
stack size              (kbytes, -s) 8192
[root@wxk test]# cat test_stack.cpp
#include <vector>
int main() {
    // char a[1024 * 1024 * 9] = {0};
    // std::vector<char> a(1024 * 1024 * 9, 0);
    struct Info {
        char a[1024 * 1024] = {0};
    };
    std::vector<Info> a(9);
    return 0;
}
[root@wxk test]# g++ -std=c++11 test_stack.cpp
[root@wxk test]# ./a.out
[root@wxk test]#

看了一下std::vector的源码,在我的机器上,源码路径在/usr/include/c++/4.8.5/bits/stl_vector.h,看了源码后发现,vector使用的空间是在堆上分配的,所以不会导致栈溢出。
vector类是从基类_Vector_base继承而来的。

struct _Vector_base {
      typedef typename __gnu_cxx::__alloc_traits<_Alloc>::template
        rebind<_Tp>::other _Tp_alloc_type;
        
      struct _Vector_impl
      : public _Tp_alloc_type
      {
        pointer _M_start;
        pointer _M_finish;
        pointer _M_end_of_storage;
       };
       
    public:
      _Vector_impl _M_impl;
      
     pointer
      _M_allocate(size_t __n)
      { return __n != 0 ? _M_impl.allocate(__n) : 0; }
      
      _Vector_base(size_t __n)
      : _M_impl()
      { _M_create_storage(__n); }

    private:
      void
      _M_create_storage(size_t __n)
      {
        this->_M_impl._M_start = this->_M_allocate(__n);
        this->_M_impl._M_finish = this->_M_impl._M_start;
        this->_M_impl._M_end_of_storage = this->_M_impl._M_start + __n;
      }
};

class vector : protected _Vector_base<_Tp, _Alloc> {
};

函数调用链入下

引用\[1\]:在C++中,栈溢出是由于程序使用的栈空间超过了操作系统给程序分配的栈大小所导致的。当我们在程序中声明一个大数组时,比如double a\[1000\]\[1000\],它占用大量的栈空间,而操作系统一般只给程序分配1M ~ 2M的栈空间。因此,当数组的大小超过了栈空间的限制,就发生栈溢出的情况。\[1\] 引用\[3\]:为了解决C++中的栈溢出问题,有几种常见的方法。首先,可以将大数组改为使用STL的vector容器来代替。vector在堆上分配内存,而不是在栈上,因此可以避免栈溢出的问题。另外,如果一个函数有很多局部变量,可以考虑将其拆分为多个函数,使用指针和STL来替代数据量大的变量。这样可以减少函数使用的栈空间,避免栈溢出的发生。\[3\] 因此,要解决C++中的栈溢出问题,可以采取以下措施: 1. 将大数组改为使用STL的vector容器来代替。 2. 将一个多局部变量的函数拆分为多个函数,使用指针和STL来替代数据量大的变量。这样可以减少函数使用的栈空间。 通过以上方法,可以有效地避免C++中的栈溢出问题。 #### 引用[.reference_title] - *1* [C++栈溢出的原因及解决方法](https://blog.csdn.net/WukongAKK/article/details/82559827)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insert_down28v1,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* [[转]C++栈溢出的原因以及可行的解决方法](https://blog.csdn.net/weixin_30474613/article/details/97864537)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insert_down28v1,239^v3^insert_chatgpt"}} ] [.reference_item] - *3* [C++栈溢出的解决方法总结](https://blog.csdn.net/qq_43376782/article/details/122141990)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insert_down28v1,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值