Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

core dumped ! what's wrong with my smart pointer in c++ code

55 views
Skip to first unread message

唐彬

unread,
Dec 28, 2017, 1:42:22 AM12/28/17
to
#include <iostream>
using namespace std;


class Smart_Ptr;

class U_Ptr {
friend class Smart_Ptr;
private:
U_Ptr(int *_p): p(_p), use(1) {
cout << "U_Ptr constructor is called !" << endl;
}
~U_Ptr() {
cout << "U_Ptr destructor is called!" << endl;
delete p;
}
int use;
int *p;
};

class Smart_Ptr {
public:
Smart_Ptr(int *_p): ptr(new U_Ptr(_p)) {

cout << "Smart_Ptr constructor is called !" << endl;
}
~Smart_Ptr() {

cout << "Smart_Ptr destructor is called !" << endl;
if(--ptr->use == 0) {
delete ptr;
}
}

int get_int() const { return *ptr->p; }

private:
U_Ptr *ptr;
};

void test() {
int a = 8;
Smart_Ptr obj(&a);
cout << "int val of obj a is " << obj.get_int() << endl;
return ;
}

int main() {
cout << "now testing my Smart_Ptr:" << endl;
test();
return 0;
}

Paavo Helde

unread,
Dec 28, 2017, 5:45:00 AM12/28/17
to
You have not defined any copy constructor for your classes, so compiler
generates them automatically, but gets it wrong. Ditto for the
assignment op, move ctor and move assignment op. You should either
define them or declare them as deleted if they are not needed.

Another tell-tale of the same thing is that your code contains code for
decrementing the refcounter, but not for incrementing.

See http://en.cppreference.com/w/cpp/language/rule_of_three for details.

I also hope you are aware C++ already contains std::shared_ptr and this
is just a learning exercise.

Cheers
Paavo

Marcel Mueller

unread,
Dec 28, 2017, 5:50:33 AM12/28/17
to
On 28.12.17 07.42, 唐彬 wrote:
> class Smart_Ptr {
> public:
> Smart_Ptr(int *_p): ptr(new U_Ptr(_p)) {
> cout << "Smart_Ptr constructor is called !" << endl;
> }

First of all the copy constructor is missing. So ->use is not
incremented in this case.
This will decrement ->use multiple times on destruction. On the first
invocation the underlying object is destroyed. Any further access is
after the memory has been released, i.e. UB.

> void test() {
> int a = 8;
> Smart_Ptr obj(&a);

Secondly you taking the address of an object on the stack here and pass
it to a smart pointer that takes the ownership. The resulting call to
delete will sadly fail because the object is owned by the stack rather
than the heap. Again UB.

> cout << "int val of obj a is " << obj.get_int() << endl;
> return ;
> }

Here it crashes because the destructor invokes delete &a;


BTW. it is amazingly complex to write real safe reference counted smart
pointers, especially if multiple threads come into play. And it's more
complex to write a smart pointer which is still pretty fast. Have a look
at the implementation of std::shared_ptr to get an impression of it.
And it is even more complex to write a reference counted smart pointer
that provides strong thread safety, i.e. get access to a valid object
from a global smart pointer instance that changes asynchronously. Not
even std::shared_ptr supports this pattern.


Marcel

Ben Bacarisse

unread,
Dec 28, 2017, 5:52:10 AM12/28/17
to
唐彬 <tb731...@gmail.com> writes:

> #include <iostream>
> using namespace std;

... more code

What did you try to find out what's wrong? Did you, for example, try to
simplify the example?

Does this version make the error clearer to you:

#include <iostream>

class U_Ptr {
public:
U_Ptr(int *_p): p(_p) { }
~U_Ptr() {
std::cout << "U_Ptr destructor is called!" << std::endl;
delete p;
}
int *p;
};

int main() {
int a = 8;
U_Ptr obj(&a);
return 0;
}

If not, try to remove the class altogether whilst leaving the actions
that the class performs intact. That should make it clear!

--
Ben.

schw...@yahoo.com

unread,
Dec 28, 2017, 12:43:00 PM12/28/17
to
On Thursday, December 28, 2017 at 2:52:10 AM UTC-8, Ben Bacarisse wrote:
In your example, the failure occurs on the statement
delete p;
because p does not point to memory allocated by new.

In the OP's code, the failure occurs in ~Smart_Ptr on the statement
delete ptr;
but in this case ptr DOES point to memory allocated by new (courtesy of the initialization performed by the U_Ptr constructor). At no point is ptr modified. It seems like ~Smart_Ptr should have no trouble calling ~U_Ptr for the object ptr points to.

Yes, ~U_Ptr will fail when it tries to delete p but the current failure occurs before that destructor begins to execute.

Ben Bacarisse

unread,
Dec 28, 2017, 3:05:10 PM12/28/17
to
Not when I run it -- the failure is in U_Ptr::~U_Ptr called from
Smart_Ptr::~Smart_Ptr. Are you saying the OP's code (which as has been
pointed out does have other problems) is failing for some other reason?

--
Ben.

Barry Schwarz

unread,
Dec 28, 2017, 5:12:52 PM12/28/17
to
On Thu, 28 Dec 2017 20:04:48 +0000, Ben Bacarisse
<ben.u...@bsb.me.uk> wrote:

>schw...@yahoo.com writes:

<snip>

>> In your example, the failure occurs on the statement
>> delete p;
>> because p does not point to memory allocated by new.
>>
>> In the OP's code, the failure occurs in ~Smart_Ptr on the statement
>> delete ptr;
>> but in this case ptr DOES point to memory allocated by new (courtesy
>> of the initialization performed by the U_Ptr constructor). At no
>> point is ptr modified. It seems like ~Smart_Ptr should have no
>> trouble calling ~U_Ptr for the object ptr points to.
>>
>> Yes, ~U_Ptr will fail when it tries to delete p but the current
>> failure occurs before that destructor begins to execute.
>
>Not when I run it -- the failure is in U_Ptr::~U_Ptr called from
>Smart_Ptr::~Smart_Ptr. Are you saying the OP's code (which as has been
>pointed out does have other problems) is failing for some other reason?

My mistake. The debugger I am using will step into a destructor
called as the result of a return statement but not when called by a
delete statement. By placing breakpoints in all the destructors I was
able to verify that ~Smart_Ptr successfully calls ~U_Ptr and that
fails on the delete p statement as you previously noted.

--
Remove del for email

唐彬

unread,
Dec 29, 2017, 4:20:31 AM12/29/17
to
So how can i fix this bug?
~Smart_Ptr can successfully call ~U_Ptr, but when it comes to the statement "delete p", p points to an invalid memory..

Barry Schwarz

unread,
Dec 29, 2017, 4:36:27 AM12/29/17
to
On Fri, 29 Dec 2017 01:20:07 -0800 (PST), ?? <tb731...@gmail.com>
wrote:

>So how can i fix this bug?
>~Smart_Ptr can successfully call ~U_Ptr, but when it comes to the statement "delete p", p points to an invalid memory..

If you want ~U_Ptr() to delete the object pointed to by p, you must
insure that p always points to memory allocated by new. In the
original code, p pointed to an automatic object defined in test().

On the other hand, there is no need to delete p. Your existing code
will then work fine. If someone creates an instance of U_Ptr where p
points to allocated memory, it becomes there job to delete it. Since
the memory is allocated independent of U_Ptr(), it can be deleted
either before or after ~U_Ptr() is called.

唐彬

unread,
Dec 29, 2017, 4:53:41 AM12/29/17
to
got it ! Thanks!
BTW what does "Remove del for email" mean? English is not my mother language, and i dont understand why Remove and del are used together.

Barry Schwarz

unread,
Dec 29, 2017, 12:30:24 PM12/29/17
to
On Fri, 29 Dec 2017 01:53:22 -0800 (PST), ?? <tb731...@gmail.com>
wrote:

>got it ! Thanks!
>BTW what does "Remove del for email" mean? English is not my mother language, and i dont understand why Remove and del are used together.

That line is part of my "signature" as opposed to the message text. It
tells you how to convert the "from" data in the header to my email
address for those rare occasions when a conversation should be taken
private.
Message has been deleted
0 new messages