Shoot by Nikon FM2, 28/2.8, Film
I am trying to use the C++11 to support the smart pointer, but I find there is no shard_array in <memory>, so I try to use it in this way, and I know this maybe WRONG:
shared_ptr<int> sp(new int[10]);
Then run it, it coredumped as I guessed:
$ smart_ptr/Test_shared_array Destructing a Foo with x=0 *** Error in `smart_ptr/Test_shared_array': munmap_chunk(): invalid pointer: 0x0000000001d58018 *** [1] 14128 abort (core dumped) smart_ptr/Test_shared_array
Use GDB to see more information:
(gdb) run Starting program: /home/nasacj/projects/woodycxx/smart_ptr/Test_shared_array Destructing a Foo with x=0 *** Error in `/home/nasacj/projects/woodycxx/smart_ptr/Test_shared_array': munmap_chunk(): invalid pointer: 0x0000000000603018 *** Program received signal SIGABRT, Aborted. 0x00007ffff7530cc9 in __GI_raise (sig=sig@entry=6) at ../nptl/sysdeps/unix/sysv/linux/raise.c:56 56 ../nptl/sysdeps/unix/sysv/linux/raise.c: No such file or directory. (gdb) bt #0 0x00007ffff7530cc9 in __GI_raise (sig=sig@entry=6) at ../nptl/sysdeps/unix/sysv/linux/raise.c:56 #1 0x00007ffff75340d8 in __GI_abort () at abort.c:89 #2 0x00007ffff756df24 in __libc_message (do_abort=do_abort@entry=1, fmt=fmt@entry=0x7ffff767c6c8 "*** Error in `%s': %s: 0x%s ***\n") at ../sysdeps/posix/libc_fatal.c:175 #3 0x00007ffff7578c87 in malloc_printerr (action=<optimized out>, str=0x7ffff767ca48 "munmap_chunk(): invalid pointer", ptr=<optimized out>) at malloc.c:4996 #4 0x0000000000400d9f in _M_release (this=0x603050) at /usr/include/c++/4.8/bits/shared_ptr_base.h:144 #5 ~__shared_count (this=<optimized out>, __in_chrg=<optimized out>) at /usr/include/c++/4.8/bits/shared_ptr_base.h:546 #6 ~__shared_ptr (this=<optimized out>, __in_chrg=<optimized out>) at /usr/include/c++/4.8/bits/shared_ptr_base.h:781 #7 ~shared_ptr (this=<optimized out>, __in_chrg=<optimized out>) at /usr/include/c++/4.8/bits/shared_ptr.h:93 #8 test () at Test_shared_array.cpp:30 #9 0x0000000000400bc9 in main () at Test_shared_array.cpp:36 (gdb) quit
Then I realize that in Boost, user should provide a deleter to shared_ptr:
Then I find this in stackoverflow:
By default, shared_ptr
will call delete
on the managed object when no more references remain to it. However, when you allocate using new[]
you need to call delete[]
, and not delete
, to free the resource.
In order to correctly use shared_ptr
with an array, you must supply a custom deleter.
template< typename T > struct array_deleter { void operator ()( T const * p) { delete[] p; } };
Create the shared_ptr as follows
std::shared_ptr<int> sp( new int[10], array_deleter<int>() );
Now shared_ptr
will correctly call delete[]
when destroying the managed object.
With C++11, you can also use a lambda instead of the functor.
std::shared_ptr<int> sp( new int[10], []( int *p ) { delete[] p; } );
Also, unless you actually need to share the managed object, a unique_ptr
is better suited for this task, since it has a partial specialization for array types.
std::unique_ptr<int[]> up( new int[10] ); // this will correctly call delete[]
Now there come the shared array STD version in practice:
//#include "shared_array.h" #include <memory> #include <iostream> using namespace std; struct Foo { Foo() : x(0) {} Foo( int _x ) : x(_x) {} ~Foo() { std::cout << "Destructing a Foo with x=" << x << "\n"; } int x; /* ... */ }; template< typename T > struct array_deleter { void operator ()( T const * p) { delete[] p; } }; //typedef woodycxx::smart_prt::shared_array<Foo> FooArray; typedef shared_ptr<Foo> FooArray; void test() { FooArray(new Foo[10], array_deleter<Foo>()); } int main() { test(); return 0; }
The Output:
$ ./Test_shared_array Destructing a Foo with x=0 Destructing a Foo with x=0 Destructing a Foo with x=0 Destructing a Foo with x=0 Destructing a Foo with x=0 Destructing a Foo with x=0 Destructing a Foo with x=0 Destructing a Foo with x=0 Destructing a Foo with x=0 Destructing a Foo with x=0
Using incomplete classes for implementation hiding
The “Pimpl” idiom
Using abstract classes for implementation hiding
Preventing delete px.get()
Using a shared_ptr
to hold a pointer to an array
Encapsulating allocation details, wrapping factory functions
Using a shared_ptr
to hold a pointer to a statically allocated object
Using a shared_ptr
to hold a pointer to a COM object
Using a shared_ptr
to hold a pointer to an object with an embedded reference count
Using a shared_ptr
to hold another shared ownership smart pointer
Obtaining a shared_ptr
from a raw pointer
Obtaining a shared_ptr
(weak_ptr
) to this
in a constructor
Obtaining a shared_ptr
to this
Using shared_ptr
as a smart counted handle
Using shared_ptr
to execute code on block exit
Using shared_ptr<void>
to hold an arbitrary object
Associating arbitrary data with heterogeneous shared_ptr
instances
Using shared_ptr
as a CopyConstructible mutex lock
Using shared_ptr
to wrap member function calls
Delayed deallocation
Weak pointers to objects not managed by a shared_ptr