为什么我的 C++ 程序在使用调试器时运行良好,但在没有调试器时却无法运行?

问题描述 投票:0回答:2

我试图重新创建向量类及其基本功能,但我的程序在操作过程中不断退出。当我运行调试器时,它完全执行得很好。这是我的矢量类的样子:

template<class T>
class Vector {
    T* _array;
    size_t _size;
    size_t _capacity;


public:
    Vector() : _size(0), _capacity(8), _array(new T[_capacity]) { }
    ~Vector() { delete[] _array; }

    void _grow() {
        T* tmp = _array;
        size_t old_cap = _capacity;
        _capacity *= 2;
        _array = new T[_capacity];
        for (size_t i = 0; i < old_cap; i++) {
            _array[i] = tmp[i];
        }
        delete[] tmp;
    }

    void push_back(T const& item) {
        if (_size == _capacity) { _grow(); }
        _array[_size++] = item;
    }

    void pop_back() {
        _size--;
    }

    void insert(T item, int position) {
        // implement insert here
        for (int i = position; i < _size-1; i++) {
            _array[i+1] = _array[i];
        }
        _size++;
        if (_size == _capacity) {
            _grow();
        }
        _array[position] = item;
    }

    void remove(int position) {
        // implement remove here
        for (int i = position; i < _size-1; i++) {
            _array[i] = _array[i+1];
        }
        _size--;
    }

    T& operator[](int index) {
        // implement operator[] here
        return _array[index];
    }

    size_t size() const {
        return _size;
    }

    void clear() {
        // implement clear here
        _size = 0;
    }
};

这是实际初始化类对象并调用其成员函数的代码:

template<class T>
void noisy_push_back(Vector<T>& vector, T item) {
    vector.push_back(item);
    std::cout << "vector.push_back(" << item << ')' << std::endl;
}

template<class T>
void print_vector(Vector<T>& vector) {
    std::cout << "vector =";
    for (int i = 0; i < vector.size(); i++) {
        std::cout << ' ' << vector[i];
    }
}

void test1() {
    std::cout << "--- Test 1 output ---\n" << std::endl;

    Vector<std::string> vector;

    noisy_push_back<std::string>(vector, "wonder");
    noisy_push_back<std::string>(vector, "yak");
    print_vector(vector);

    std::cout << std::endl;
    noisy_push_back<std::string>(vector, "bookshelf");
    noisy_push_back<std::string>(vector, "euphoria");
    print_vector(vector);
}

当我正常运行程序时,它会添加“wonder”和“yak”,然后很好地打印矢量。当它尝试

push_back("bookshelf")
时,它会以
Process finished with exit code -1073741819 (0xC0000005)

退出

有什么想法吗?

我尝试在退出之前打印出向量大小,它符合预期:

size() = 2

此外,当我尝试运行调试器时,一切看起来都很正常,程序运行得很好。顺便说一句,我正在使用 CLion。

c++ vector initialization clion
2个回答
3
投票

你的编译器应该警告你这一点;如果没有,请调出警告!

 Vector() : _size(0), _capacity(8), _array(new T[_capacity])

但是,您正在尝试最后初始化您的

_array
,因为您的变量是按以下顺序声明的:

    T* _array;
    size_t _size;
    size_t _capacity;

然后

_array
将首先被初始化。
_capacity
在初始化时将是不确定的,因此你有未定义的行为。


-1
投票

你应该学会使用工具。首先启用警告。然后使用地址清理器查找内存错误: https://godbolt.org/z/r5EjWoce8

=================================================================
==1==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x602000000018 at pc 0x000000406672 bp 0x7ffc3d36ce50 sp 0x7ffc3d36ce48
READ of size 8 at 0x602000000018 thread T0
    #0 0x406671 in std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::_M_data() const /opt/compiler-explorer/gcc-13.1.0/include/c++/13.1.0/bits/basic_string.h:234
    #1 0x406671 in std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::_M_is_local() const /opt/compiler-explorer/gcc-13.1.0/include/c++/13.1.0/bits/basic_string.h:275
    #2 0x406671 in std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::capacity() const /opt/compiler-explorer/gcc-13.1.0/include/c++/13.1.0/bits/basic_string.h:1170
    #3 0x406671 in std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::_M_assign(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) /opt/compiler-explorer/gcc-13.1.0/include/c++/13.1.0/bits/basic_string.tcc:279
    #4 0x4087f1 in std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::assign(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) /opt/compiler-explorer/gcc-13.1.0/include/c++/13.1.0/bits/basic_string.h:1607
    #5 0x4087f1 in std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::operator=(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) /opt/compiler-explorer/gcc-13.1.0/include/c++/13.1.0/bits/basic_string.h:813
    #6 0x4087f1 in Vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >::push_back(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) /app/example.cpp:27
    #7 0x4087f1 in void noisy_push_back<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >(Vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >) /app/example.cpp:71
    #8 0x403304 in test1() /app/example.cpp:88
    #9 0x402328 in main /app/example.cpp:100
    #10 0x7f2a53229d8f  (/lib/x86_64-linux-gnu/libc.so.6+0x29d8f) (BuildId: c289da5071a3399de893d2af81d6a30c62646e1e)
    #11 0x7f2a53229e3f in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x29e3f) (BuildId: c289da5071a3399de893d2af81d6a30c62646e1e)
    #12 0x402384 in _start (/app/output.s+0x402384) (BuildId: d659454d1d76514eedee496e191fc29a836621ba)

0x602000000018 is located 0 bytes after 8-byte region [0x602000000010,0x602000000018)
allocated by thread T0 here:
    #0 0x7f2a53ed1ce8 in operator new[](unsigned long) (/opt/compiler-explorer/gcc-13.1.0/lib64/libasan.so.8+0xdcce8) (BuildId: 4508ebe68c8328f99c6a77c3715bff492eb1cfd5)
    #1 0x402f9e in Vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >::Vector() /app/example.cpp:11
    #2 0x402f9e in test1() /app/example.cpp:86

SUMMARY: AddressSanitizer: heap-buffer-overflow /opt/compiler-explorer/gcc-13.1.0/include/c++/13.1.0/bits/basic_string.h:234 in std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::_M_data() const
Shadow bytes around the buggy address:
  0x601ffffffd80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x601ffffffe00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x601ffffffe80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x601fffffff00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x601fffffff80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
=>0x602000000000: fa fa 00[fa]fa fa fa fa fa fa fa fa fa fa fa fa
  0x602000000080: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x602000000100: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x602000000180: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x602000000200: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x602000000280: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
Shadow byte legend (one shadow byte represents 8 application bytes):
  Addressable:           00
  Partially addressable: 01 02 03 04 05 06 07 
  Heap left redzone:       fa
  Freed heap region:       fd
  Stack left redzone:      f1
  Stack mid redzone:       f2
  Stack right redzone:     f3
  Stack after return:      f5
  Stack use after scope:   f8
  Global redzone:          f9
  Global init order:       f6
  Poisoned by user:        f7
  Container overflow:      fc
  Array cookie:            ac
  Intra object redzone:    bb
  ASan internal:           fe
  Left alloca redzone:     ca
  Right alloca redzone:    cb
==1==ABORTING

请注意,堆栈帧 6-9 显示了问题所在。

© www.soinside.com 2019 - 2024. All rights reserved.