为什么Linux无法捕获C ++运行时错误,例如使用浅拷贝构造函数?

Yan*_*ang 2 c++ linux

我正在研究c ++复制构造函数。我编写了使用浅拷贝构造函数的代码,该构造函数会导致运行时错误进行研究。我的意图是使运行时错误。

#include <iostream>
#include <cstring>
using namespace std;

class Person{ //define Person class                                                                  
  char *name;
  int id;
public:
  Person(int id, const char *name);//constructer                                                     
  ~Person();//distructer                                                                             
  Person(Person& p){
    this->name = p.name;
    this->id = p.id;
  }
  void changeName(const char *name);
  void show(){
    cout << id <<',' << name <<endl;
  }
};

Person::Person(int id, const char *name){
  this -> id = id;
  int len = strlen(name);
  this->name = new char[len+1];
  strcpy(this->name,name);
}
Person::~Person(){
  if(name)
    delete []name;
}

void Person::changeName(const char *name){
  if(strlen(name) > strlen(this->name))
    return;
  strcpy(this->name,name);
}

int main(){
  Person father(1,"Kitae");
  Person daughter(father);

  cout << "after object daughter maked ---" << endl;
  father.show();
  daughter.show();

  daughter.changeName("Grace");
  cout <<"daughter name changed ---"<<endl;
  father.show();
  daughter.show();

  return 0;
}
Run Code Online (Sandbox Code Playgroud)

当我在Windows 10(由Visual Studio 2017编译)上编译并运行它时,它运行良好(发生运行时错误),但在linux(由g ++ 7.3.0编译)上却无法正常运行(运行时错误不会发生)。linux显示没有错误发生。

因此,我在Linux上调试了该代码。我用过gdb。

after object daughter maked ---
1,Kitae
1,Kitae
daughter name changed ---
1,Grace
1,Grace
[Inferior 1 (process 3297) exited normally]
Run Code Online (Sandbox Code Playgroud)

像这样的代码使用浅表复制构造函数可以吗?如果不是,为什么Windows和Linux显示不同的结果?

J. *_*rez 5

浅表副本仅间接导致错误。导致错误的真正原因是指针由于浅拷贝被删除了两次。并且由于双重删除而发生的错误取决于编译器和操作系统。

如果您想在Linux上捕获类似的错误,则有一个非常好的工具valgrind。赶紧跑:

$ valgrind ./my_program
Run Code Online (Sandbox Code Playgroud)

它会告诉您是否存在内存泄漏或两次释放。

或在编译程序时使用另一个评论者提到的地址清理器。(它的确使代码运行速度变慢,但是对于调试版本是可以的)。

话虽这么说,并不是所有浅表副本都是坏的,并且浅表副本构造函数有完全有效(且安全)的用例。例如,假设我正在编写自己的shared_ptr课程。实现非常简单:

template<class T>
class shared_ptr {
    T* ptr;
    int* counter;
    void increment_counter() {
        int& count = *counter; 
        ++count; 
    }
    int decriment_counter() {
        int& count = *counter; 
        return --count; 
    }
   public:
    explicit shared_ptr(T* ptr) 
      : ptr(ptr)
      , counter(new int(1))
    {}
    // Make shallow copy, but increment the counter
    shared_ptr(shared_ptr const& other)
      : ptr(other.ptr)
      , counter(other.counter)
    {
        increment_counter(); 
    }
    ~shared_ptr() {
        int new_count = decriment_counter(); 
        // Only delete the pointer if this was the last copy
        if(new_count == 0) {
            delete ptr; 
            delete counter; 
        }
    }
};
Run Code Online (Sandbox Code Playgroud)

在这里,shared_ptr跟踪该指针有多少个实例,并且仅当指针是最后一个副本时才删除该指针。