【问题标题】:C++ crash when summarazing class instances汇总类实例时 C++ 崩溃
【发布时间】:2015-07-29 06:24:02
【问题描述】:

这是一个简单的Hello World代码,应该使用复制构造函数来汇总对象

下面是它生成的代码和输出

我猜崩溃是因为析构函数调用了它不应该调用的地方(或者我的 C++ 学习书的作者没有预料到),但也许你可以给我一些建议

我使用带有额外选项的默认 GNU GCC 代码块编译器 -std=c++11 -fno-elide-constructors(无论如何在这种情况下它们都无关紧要)

#include <iostream>
#include <string>
#include <cstring>
#include <sstream>

using namespace std;

class MyString
{
private:
  char* Buffer;

  MyString(): Buffer(NULL)
  {
    cout << "Default constructor called" << endl;
  }

public:
  MyString( const char* InitialInput )
  {
    cout << "Constructor called for: " << InitialInput << endl;
    if(InitialInput != NULL)
    {
      Buffer = new char [strlen(InitialInput)+1];
      strcpy( Buffer, InitialInput );
    }
    else
      Buffer = NULL;
  }

  MyString operator+ (const MyString& AddThis)
  {
    cout << "operator+ called for '" << Buffer << "' to add: " << AddThis.Buffer << endl;
    MyString NewString;
    if (AddThis.Buffer != NULL)
    {
      NewString.Buffer = new char[GetLenght() + strlen( AddThis.Buffer ) + 1];
      strcpy( NewString.Buffer, Buffer );
      strcat( NewString.Buffer, AddThis.Buffer );
    }
  }

  MyString& operator= (const MyString& CopySource)
  {
    cout << "Copy assignment operator for '" << Buffer << "' to copy from: " << CopySource.Buffer << endl;
    if ((this != &CopySource) && (CopySource.Buffer != NULL))
    {
      if (Buffer != NULL)
        delete[ ] Buffer;
      // гарантирует глубокую копию с предварительным
      // резервированием собственного буфера
      Buffer = new char [strlen(CopySource.Buffer) + 1];
      // копирование оригинала в локальный буфер
      strcpy(Buffer, CopySource.Buffer);
    }
    return *this;
  }

  MyString( const MyString& CopySource )
  {
    cout << "Copy constructor for '" << Buffer << "' to copy from: " << CopySource.Buffer << endl;
    if(CopySource.Buffer != NULL)
    {
      Buffer = new char [strlen(CopySource.Buffer)+1];
      strcpy(Buffer,CopySource.Buffer);
    }
    else
      Buffer = NULL;
  }

  ~MyString()
  {
    cout << "Destructor called for: " << Buffer << endl;
    if( Buffer != NULL )
      delete [] Buffer;
  }

  int GetLenght()
  {
    return strlen(Buffer);
  }

  operator const char*()
  {
    return Buffer;
  }
};

int main( )
{
  MyString Hello("Hello ");
  MyString World("World");
  MyString CPP(" of C++");

  MyString sayHelloAgain ("overwrite this");
  sayHelloAgain = Hello + World + CPP;

  return 0;
}

输出是

构造函数调用:你好
构造函数调用:World
构造函数调用:C++
构造函数调用:覆盖 this
operator+ 要求添加“Hello”:World
调用的默认构造函数
调用的析构函数:Hello World
运算符+ 调用 '├РРРРР■ ' 来添加:C++
调用的默认构造函数
调用的析构函数:C++ 的├РРРРР■
将“覆盖此”的赋值运算符移动到:
崩溃
进程返回 -1073741819 (0xC0000005) 执行时间:37.566 s
按任意键继续。

【问题讨论】:

  • 输出看起来与代码不一致:我没有在代码中找到输出的“移动分配..”。
  • 编译时出现警告。这将表明 operator + 应该返回一个值
  • 这个输出是从哪里来的? Move assignment operator for 'overwrite this' to move from: 请分享此代码。

标签: c++ c++11 constructor crash copy


【解决方案1】:

你的错误在你的copy constructor这一行

cout << "Copy constructor for '" << Buffer << "' to copy from: " << CopySource.Buffer << endl;

当对象在缓冲区中有 NULL 时,您正在尝试打印 buffer

【讨论】:

  • 感谢这是导致崩溃的原因,但之所以调用析构函数是因为我忘记了从 operator+ 返回值,正如“黑暗”所说的那样
【解决方案2】:

谢谢大家 如果有人感兴趣,下面是固定代码(添加了复制使用的移动构造函数)

#include <iostream>
#include <string>
#include <cstring>
#include <sstream>

using namespace std;

class MyString
{
private:
  char* Buffer;

  MyString(): Buffer(NULL)
  {
    cout << "Default constructor called" << endl;
  }

public:
  MyString( const char* InitialInput )
  {
    cout << "Constructor called for: " << InitialInput << endl;
    if(InitialInput != NULL)
    {
      Buffer = new char [strlen(InitialInput)+1];
      strcpy( Buffer, InitialInput );
    }
    else
      Buffer = NULL;
  }

  MyString operator+ (const MyString& AddThis)
  {
    cout << "operator+ called: " << AddThis.Buffer << endl;
    MyString NewString;
    if (AddThis.Buffer != NULL)
    {
      NewString.Buffer = new char[GetLenght() + strlen( AddThis.Buffer ) + 1];
      strcpy( NewString.Buffer, Buffer );
      strcat( NewString.Buffer, AddThis.Buffer );
    }
    return NewString;
  }

  MyString& operator= (const MyString& CopySource)
  {
    cout << "Copy assignment operator to copy from: " << CopySource.Buffer << endl;
    if ((this != &CopySource) && (CopySource.Buffer != NULL))
    {
      if (Buffer != NULL)
        delete[ ] Buffer;
      Buffer = new char [strlen(CopySource.Buffer) + 1];
      strcpy(Buffer, CopySource.Buffer);
    }
    return *this;
  }

  MyString( const MyString& CopySource )
  {
    cout << "Copy constructor to copy from: " << CopySource.Buffer << endl;
    if(CopySource.Buffer != NULL)
    {
      Buffer = new char [strlen(CopySource.Buffer)+1];
      strcpy(Buffer,CopySource.Buffer);
    }
    else
      Buffer = NULL;
  }

  MyString( MyString&& MoveSource)
  {
    cout << "Move constructor to move from: " << MoveSource.Buffer << endl;
    if(MoveSource.Buffer != NULL)
    {
      Buffer = MoveSource.Buffer;
      MoveSource.Buffer = NULL;
    }
  }

  MyString& operator= (MyString&& MoveSource)
  {
    cout << "Move assignment operator to move from: " << MoveSource.Buffer << endl;
    if ((this != &MoveSource) && (MoveSource.Buffer != NULL))
    {
      if (Buffer != NULL)
        delete[ ] Buffer;
      Buffer = new char [strlen(MoveSource.Buffer) + 1];
      strcpy(Buffer, MoveSource.Buffer);
    }
    return *this;
  }

  ~MyString()
  {
    if( Buffer != NULL )
      delete [] Buffer;
  }

  int GetLenght()
  {
    return strlen(Buffer);
  }

  operator const char*()
  {
    return Buffer;
  }
};

int main( )
{
  MyString Hello("Hello ");
  MyString World("World");
  MyString CPP(" of C++");

  MyString sayHelloAgain ("overwrite this");
  sayHelloAgain = Hello + World + CPP;

  return 0;
}

出来

构造函数调用:你好
构造函数调用:World
构造函数调用:C++
构造函数调用:覆盖 this
运算符+调用:世界
调用的默认构造函数
移动构造函数以移动:Hello World
运算符+调用:C++
调用的默认构造函数
移动构造函数以从:Hello World of C++
将赋值运算符移至从:Hello World of C++

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2010-09-08
    • 2013-05-31
    • 2019-03-29
    • 2011-10-18
    • 1970-01-01
    • 1970-01-01
    • 2012-02-27
    • 1970-01-01
    相关资源
    最近更新 更多