类析构函数上的SIGSEGV

SIGSEGV on class destructor

本文关键字:SIGSEGV 析构函数      更新时间:2023-10-16

我有以下类。

标题:

#include <iostream>
#include <vector>
#include <regex>
#ifndef GENERATION_H
#define GENERATION_H
class Generation {
public:
    Generation(int x, int y);
    ~Generation() {
    }
    void setCell(int x, int y, bool alive);
    bool getCell(int x, int y);
    int surroundingLivingCells(int x, int y);
    int getX();
    int getY();
    static std::shared_ptr<Generation> parseRil(int x_i, int y_i, const std::string& ril);
private:
    int _x;
    int _y;
    std::vector<int> _born = {3};
    std::vector<int> _starve = {3, 5};
    std::vector<std::vector<int>> _data;    
};
#endif // GENERATION_H

Cpp:

#include <regex>
#include "generation.h"
Generation::Generation(int x, int y) : _x(x), _y(y) {
    _data.resize(y, std::vector<int>(x, 0));
}
void Generation::setCell(int x, int y, bool alive) {
    _data[y][x] = alive ? 1 : 0;
}
bool Generation::getCell(int x, int y) {
    return _data[y][x] == 1;
}
int Generation::surroundingLivingCells(int x, int y) {
    int c = 0;
    for (int yy=y-1;yy<=y+1;++yy) {
        for (int xx=x-1;xx<=x+1;++xx) {
            if (xx == x && yy == y)
                continue;
            if (xx>=0 && yy>=0 && xx < _x && yy < _y) {
                c += _data[yy][xx];
            }
        }       
    }
    return c;
}
int Generation::getX() {
    return _x;
}
int Generation::getY() {
    return _y;
}
std::shared_ptr<Generation> Generation::parseRil(int x_i, int y_i, const std::string& ril) {
    std::shared_ptr<Generation> g(new Generation(x_i, y_i));
    std::regex ril_regex("((\d*)(\w))([!$]*)");
    auto ril_begin = std::sregex_iterator(ril.begin(), ril.end(), ril_regex);
    auto ril_end = std::sregex_iterator();
    int x = 0;
    int y = 0;
    for (auto i = ril_begin; i != ril_end; ++i) {
        std::smatch ril_match = *i;
        int amount = ril_match[2] != "" ? std::stoi(ril_match[1]) : 1;
        bool alive = ril_match[3] == "o";
        for (int j=x; j<x+amount;++j) {
            g->setCell(j, y, alive);
        }
        x += amount;
        if (ril_match[4] == "$") {
            y += 1;
            x = 0;
        }
    }
    return g;
}

当我用x=213y=142和ril创建类并销毁对象时,程序崩溃:

std::shared_ptr<Generation> g(Generation::parseRil(x, y, ril));
g.reset();

我使用默认的析构函数,没有自定义代码。在parseRil中似乎出了问题,因为用构造函数创建和破坏对象的工作很好。

堆栈:

Program received signal SIGSEGV, Segmentation fault.
0x00007ffff6b6fe36 in _int_free () from /usr/lib/libc.so.6
(gdb) bt
#0  0x00007ffff6b6fe36 in _int_free () from /usr/lib/libc.so.6
#1  0x000000000046175e in __gnu_cxx::new_allocator<int>::deallocate (this=0x6dd800, __p=0x6f3410)
    at /usr/include/c++/6.1.1/ext/new_allocator.h:110
#2  0x00000000004602f7 in std::allocator_traits<std::allocator<int> >::deallocate (__a=..., __p=0x6f3410, 
    __n=213) at /usr/include/c++/6.1.1/bits/alloc_traits.h:442
#3  0x000000000045eb0a in std::_Vector_base<int, std::allocator<int> >::_M_deallocate (this=0x6dd800, 
    __p=0x6f3410, __n=213) at /usr/include/c++/6.1.1/bits/stl_vector.h:178
#4  0x000000000045da87 in std::_Vector_base<int, std::allocator<int> >::~_Vector_base (this=0x6dd800, 
    __in_chrg=<optimized out>) at /usr/include/c++/6.1.1/bits/stl_vector.h:160
#5  0x000000000045cd35 in std::vector<int, std::allocator<int> >::~vector (this=0x6dd800, 
    __in_chrg=<optimized out>) at /usr/include/c++/6.1.1/bits/stl_vector.h:427
#6  0x000000000046181b in std::_Destroy<std::vector<int, std::allocator<int> > > (__pointer=0x6dd800)
    at /usr/include/c++/6.1.1/bits/stl_construct.h:93
#7  0x00000000004603f5 in std::_Destroy_aux<false>::__destroy<std::vector<int, std::allocator<int> >*> (
    __first=0x6dd800, __last=0x6ddbc0) at /usr/include/c++/6.1.1/bits/stl_construct.h:103
#8  0x000000000045ec4a in std::_Destroy<std::vector<int, std::allocator<int> >*> (__first=0x6dce70, 
    __last=0x6ddbc0) at /usr/include/c++/6.1.1/bits/stl_construct.h:126
#9  0x000000000045dc17 in std::_Destroy<std::vector<int, std::allocator<int> >*, std::vector<int, std::allocator<int> > > (__first=0x6dce70, __last=0x6ddbc0) at /usr/include/c++/6.1.1/bits/stl_construct.h:151
#10 0x000000000045cd6d in std::vector<std::vector<int, std::allocator<int> >, std::allocator<std::vector<int, std::allocator<int> > > >::~vector (this=0x6bc668, __in_chrg=<optimized out>)
    at /usr/include/c++/6.1.1/bits/stl_vector.h:426
#11 0x000000000045c8f0 in Generation::~Generation (this=0x6bc630, __in_chrg=<optimized out>)
    at /home/amu/Code/github/GoMtL/src/generation.h:10
#12 0x0000000000484bfc in std::_Sp_counted_ptr<Generation*, (__gnu_cxx::_Lock_policy)2>::_M_dispose (
    this=0x6bbe50) at /usr/include/c++/6.1.1/bits/shared_ptr_base.h:372
#13 0x000000000045dee4 in std::_Sp_counted_base<(__gnu_cxx::_Lock_policy)2>::_M_release (this=0x6bbe50)
    at /usr/include/c++/6.1.1/bits/shared_ptr_base.h:150
#14 0x000000000045cf67 in std::__shared_count<(__gnu_cxx::_Lock_policy)2>::~__shared_count (
    this=0x7fffffffe408, __in_chrg=<optimized out>) at /usr/include/c++/6.1.1/bits/shared_ptr_base.h:662
#15 0x000000000045c930 in std::__shared_ptr<Generation, (__gnu_cxx::_Lock_policy)2>::~__shared_ptr (
    this=0x7fffffffe400, __in_chrg=<optimized out>) at /usr/include/c++/6.1.1/bits/shared_ptr_base.h:928
#16 0x0000000000485e55 in std::__shared_ptr<Generation, (__gnu_cxx::_Lock_policy)2>::reset (
    this=0x6a6bb0 <generation_current>) at /usr/include/c++/6.1.1/bits/shared_ptr_base.h:1025
---Type <return> to continue, or q <return> to quit---
#17 0x0000000000485107 in init_game () at /home/amProgram received signal SIGSEGV, Segmentation fault.
0x00007ffff6b6fe36 in _int_free () from /usr/lib/libc.so.6
(gdb) bt
#0  0x00007ffff6b6fe36 in _int_free () from /usr/lib/libc.so.6
#1  0x000000000046175e in __gnu_cxx::new_allocator<int>::deallocate (this=0x6dd800, __p=0x6f3410)
    at /usr/include/c++/6.1.1/ext/new_allocator.h:110
#2  0x00000000004602f7 in std::allocator_traits<std::allocator<int> >::deallocate (__a=..., __p=0x6f3410, 
    __n=213) at /usr/include/c++/6.1.1/bits/alloc_traits.h:442
#3  0x000000000045eb0a in std::_Vector_base<int, std::allocator<int> >::_M_deallocate (this=0x6dd800, 
    __p=0x6f3410, __n=213) at /usr/include/c++/6.1.1/bits/stl_vector.h:178
#4  0x000000000045da87 in std::_Vector_base<int, std::allocator<int> >::~_Vector_base (this=0x6dd800, 
    __in_chrg=<optimized out>) at /usr/include/c++/6.1.1/bits/stl_vector.h:160
#5  0x000000000045cd35 in std::vector<int, std::allocator<int> >::~vector (this=0x6dd800, 
    __in_chrg=<optimized out>) at /usr/include/c++/6.1.1/bits/stl_vector.h:427
#6  0x000000000046181b in std::_Destroy<std::vector<int, std::allocator<int> > > (__pointer=0x6dd800)
    at /usr/include/c++/6.1.1/bits/stl_construct.h:93
#7  0x00000000004603f5 in std::_Destroy_aux<false>::__destroy<std::vector<int, std::allocator<int> >*> (
    __first=0x6dd800, __last=0x6ddbc0) at /usr/include/c++/6.1.1/bits/stl_construct.h:103
#8  0x000000000045ec4a in std::_Destroy<std::vector<int, std::allocator<int> >*> (__first=0x6dce70, 
    __last=0x6ddbc0) at /usr/include/c++/6.1.1/bits/stl_construct.h:126
#9  0x000000000045dc17 in std::_Destroy<std::vector<int, std::allocator<int> >*, std::vector<int, std::allocator<int> > > (__first=0x6dce70, __last=0x6ddbc0) at /usr/include/c++/6.1.1/bits/stl_construct.h:151
#10 0x000000000045cd6d in std::vector<std::vector<int, std::allocator<int> >, std::allocator<std::vector<int, std::allocator<int> > > >::~vector (this=0x6bc668, __in_chrg=<optimized out>)
    at /usr/include/c++/6.1.1/bits/stl_vector.h:426
#11 0x000000000045c8f0 in Generation::~Generation (this=0x6bc630, __in_chrg=<optimized out>)
    at /home/amu/Code/github/GoMtL/src/generation.h:10
#12 0x0000000000484bfc in std::_Sp_counted_ptr<Generation*, (__gnu_cxx::_Lock_policy)2>::_M_dispose (
    this=0x6bbe50) at /usr/include/c++/6.1.1/bits/shared_ptr_base.h:372
#13 0x000000000045dee4 in std::_Sp_counted_base<(__gnu_cxx::_Lock_policy)2>::_M_release (this=0x6bbe50)
    at /usr/include/c++/6.1.1/bits/shared_ptr_base.h:150
#14 0x000000000045cf67 in std::__shared_count<(__gnu_cxx::_Lock_policy)2>::~__shared_count (
    this=0x7fffffffe408, __in_chrg=<optimized out>) at /usr/include/c++/6.1.1/bits/shared_ptr_base.h:662
#15 0x000000000045c930 in std::__shared_ptr<Generation, (__gnu_cxx::_Lock_policy)2>::~__shared_ptr (
    this=0x7fffffffe400, __in_chrg=<optimized out>) at /usr/include/c++/6.1.1/bits/shared_ptr_base.h:928
#16 0x0000000000485e55 in std::__shared_ptr<Generation, (__gnu_cxx::_Lock_policy)2>::reset (
    this=0x6a6bb0 <generation_current>) at /usr/include/c++/6.1.1/bits/shared_ptr_base.h:1025
---Type <return> to continue, or q <return> to quit---
#17 0x0000000000485107 in init_game () at /home/amu/Code/github/GoMtL/src/main.cpp:65
#18 0x0000000000485577 in main (argc=1, argv=0x7fffffffe928)
    at /home/amu/Code/github/GoMtL/src/main.cpp:118

然而,当我选择小x和y时,比如18和12,程序运行得很好。这里有什么问题?

谢谢!

好吧,我的代码有多个问题。首先,setCell没有检查边界,违反了边界。简单的if (x > _x || y > _y)返回修复了问题。(谢谢@ascotan)

但为什么我们会遇到越界的问题呢?原来ril参数中有换行符r。这导致正则表达式出现故障,并且无法识别一些新行$字符(如果它们是新行后的第一个字符)。这导致x溢出。删除它们之后,越界情况就不会再次发生,程序也不会崩溃。