Destructor cannot delete the allocated memory block that was allocated

The following code compiles, but delivers an error at runtime:

# include <iostream>
# include <string.h>

class A {
public:
  A() {}
  A ( int id, char * t_name ) {
    _id = id ;
    name = new char [ strlen (t_name) + 1 ] ;
    strcpy ( name, t_name ) ;
  }

  char *name ;
  int _id ;
  ~A() { delete []  name ;}
} ;

int main () {
  A a ( 1, "123" ) ;
  A b ;
  b = a ;

  std::cout << static_cast < const void * > ( a.name ) << std::endl ;
  std::cout << static_cast < const void * > ( b.name ) << std::endl ;

  b.name = "abc" ; // b.name is directed to a different memory block 
  std::cout << static_cast < const void * > ( a.name ) << std::endl ;
  std::cout << static_cast < const void * > ( b.name ) << std::endl ;
  std::cout << a.name << std::endl ;
  std::cout << b.name << std::endl ;

  return 0 ;
}

It outputs something like:

0x7ff87bc03200
0x7ff87bc03200
0x7ff87bc03200
0x10f9bcf64
123
abc
a.out(883,0x7fff7ee3d000) malloc: *** error for object 0x10f9bcf64:
pointer being freed was not allocated
*** set a breakpoint in malloc_error_break to debug
Abort trap: 6

I do not understand why he says:

0x10f9bcf64: pointer freed

since it b.nameis obviously aimed at 0x10f9bcf64and no longer overlaps with a!

I am also wondering how to solve this problem? Thank!

+4
source share
4 answers

First, the constructor declaration should look like

A ( int id, const char * t_name )
            ^^^^^^

because you use string literals to initialize class objects, and string literals have types of constant arrays.

.

b = a ;

, . , .

.

,

A & operator = ( const A &a )
{
    if ( this != &a )
    {
        char *tmp = new char[ std::strlen( a.name ) + 1 ];
        std::strcpy( tmp, a.name );

        delete [] this->name;

        this->_id = a._id;
        this->name = tmp;
    }

    return *this;
} 

b.name = "abc"

. . .

+1

3/5/0. :

b = a;

3 ​​(5, ++, .. ++ 11 ), A .

, :

b.name = "abc";

char, new. , :

~A() { delete []  name ;}

delete[] .

name std::string:

class A {
public:
  A () {}
  A ( int id, const std::string& t_name ) {
    _id = id ;
    name = t_name;
  }

  std::string name ;
  int _id ;
} ;

int main () {
  A a ( 1, "123" ) ;
  A b ;
  b = a ;

  std::cout << static_cast < const void * > ( &a.name ) << std::endl ;
  std::cout << static_cast < const void * > ( &b.name ) << std::endl ;

  b.name = "abc" ; // b.name is directed to a different memory block 
  std::cout << static_cast < const void * > ( &a.name ) << std::endl ;
  std::cout << static_cast < const void * > ( &b.name ) << std::endl ;
  std::cout << a.name << std::endl ;
  std::cout << b.name << std::endl ;

  return 0 ;
}

std::string , 0.

+3

a b.

a , .

b , .

. ( , ++ 11)

0

I don’t understand why he says: "0x10f9bcf64: the pointer is freed is not allocated", since b.name is explicitly directed at 0x10f9bcf64 and does not intersect with anything else!

Because the bdestructor calls delete []in a static line.

I also wonder how to solve this problem.

You should have defined a copy constructor, for example:

A::A(const A& lhs) {
    _id = lhs.id;
    name = new char [ strlen (lhs.name) + 1 ] ;
    strcpy ( name, lhs.name ) ;
}

And also did nameand _id private.

0
source

Source: https://habr.com/ru/post/1664584/


All Articles