|
|
|
|
||||||
![]() |
|
|
LinkBack | Outils de la discussion |
|
|
#1 |
|
Messages: n/a
Hébergeur: |
In the code below , a simplified version
I need to pass a smart pointer to function f which I control .I cannot use std::auto_ptr as a parameter to f because it releases ownership on copy construction and I still need the pointer after f returns.( may be I could return the auto_ptr again ?? ) after f does its stuff , i need to pass it to g which expects a raw pointer ( I cannot change that API ) I know g does maintain its own ptr_deque which takes care of ownership etc.. , I am forced to do a get() on the shared_ptr ( instead of an ideal release() on auto_ptr which would free the ptr from smart management ) Now shared_ptr and ptr_deque desturctors cause a double delete leading to UB. How do i workaround this problem ? Thx Digz #include<boost/shared_ptr.hpp> #include<boost/ptr_container/ptr_deque.hpp> boost::ptr_deque<int> l; void f(boost::shared_ptr<int> t = boost::shared_ptr<int>()) {} void g(int* i){ l.push_back(i); } int h(){ boost::shared_ptr<int> i(new int); f(i); //need to pass aroung i, so cant use std::auto_ptr g(i.get()); //cant release from boost::shared_ptr ownership } int main(){ h(); } |
|
|
|
#2 |
|
Messages: n/a
Hébergeur: |
* digz:
> In the code below , a simplified version > I need to pass a smart pointer to function f which I control .I > cannot use std::auto_ptr as a parameter to f because > it releases ownership on copy construction and I still need the > pointer after f returns.( may be I could return the auto_ptr > again ?? ) > > after f does its stuff , i need to pass it to g which expects a raw > pointer ( I cannot change that API ) > I know g does maintain its own ptr_deque which takes care of > ownership etc.. , > > I am forced to do a get() on the shared_ptr ( instead of an ideal > release() on auto_ptr which would free the ptr from smart > management ) > Now shared_ptr and ptr_deque desturctors cause a double delete > leading to UB. > How do i workaround this problem ? > > #include<boost/shared_ptr.hpp> > #include<boost/ptr_container/ptr_deque.hpp> > > boost::ptr_deque<int> l; "l" is not a good name because it's easily confused with "1". > void f(boost::shared_ptr<int> t = boost::shared_ptr<int>()) > {} > > void g(int* i){ > l.push_back(i); > } > > int h(){ > boost::shared_ptr<int> i(new int); > f(i); //need to pass aroung i, so cant use std::auto_ptr > g(i.get()); //cant release from boost::shared_ptr ownership > } You can use std::auto_ptr for exception safety and ownership transfer. Off-the-cuff, fix errors if any: void f( int& ) {} void transferOwnershipToG( std::auto_ptr<int> p ) { int* pRaw = p.get(); p.release(); g( pRaw ); } int h() { std::auto_ptr<int> p( new int ); f( *p ); // If f throws, std::auto_ptr deallocates. transferOwnershipToG( p ); } Or, with the current boost::shared_ptr interface you can release a boost::shared_ptr by replacing its delete function. I think the function to gain access to the deleter is named get_deleter. However, this could be a bit dangerous, because with a shared_ptr at hand one expects that it will handle deallocation and can be copied and stored safely, which will not be the case in your code. Cheers, & hth., - Alf -- A: Because it messes up the order in which people normally read text. Q: Why is it such a bad thing? A: Top-posting. Q: What is the most annoying thing on usenet and in e-mail? |
|
|
|
#3 |
|
Messages: n/a
Hébergeur: |
On Jan 16, 7:35 pm, "Alf P. Steinbach" <al...@start.no> wrote:
> * digz: [...] > Off-the-cuff, fix errors if any: > void f( int& ) {} > void transferOwnershipToG( std::auto_ptr<int> p ) > { > int* pRaw = p.get(); > p.release(); > g( pRaw ); > } Generally, I would do the release after the call to g(), i.e.: g( p.get() ) ; p.release() ; Only if the call to g() succeeds can I be sure that it has taken over ownership. Otherwise, you can just call g() directly: g( p.release() ) ; (Obviously, this depends partially on g(). Normally, in the absence of other documentation, I would expect transactional semantics, which means that if g() returns via an exception, nothing has changed, and I am still responsible for the object. But it's something I'd verify anyway.) -- James Kanze (GABI Software) email:james.kanze@gmail.com Conseils en informatique orientée objet/ Beratung in objektorientierter Datenverarbeitung 9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34 |
|
|
|
#4 |
|
Messages: n/a
Hébergeur: |
* James Kanze:
> On Jan 16, 7:35 pm, "Alf P. Steinbach" <al...@start.no> wrote: >> * digz: > > [...] >> Off-the-cuff, fix errors if any: > >> void f( int& ) {} > >> void transferOwnershipToG( std::auto_ptr<int> p ) >> { >> int* pRaw = p.get(); >> p.release(); >> g( pRaw ); >> } > > Generally, I would do the release after the call to g(), i.e.: > g( p.get() ) ; > p.release() ; Yup. I had a feeling there was something. > Only if the call to g() succeeds can I be sure that it has taken > over ownership. Otherwise, you can just call g() directly: > g( p.release() ) ; Yup again -- otherwise no reason for having the transferOwnershipToG wrapper. > (Obviously, this depends partially on g(). Normally, in the > absence of other documentation, I would expect transactional > semantics, which means that if g() returns via an exception, > nothing has changed, and I am still responsible for the object. > But it's something I'd verify anyway.) Code above assumed failure reporting via exceptions. Cheers, - Alf -- A: Because it messes up the order in which people normally read text. Q: Why is it such a bad thing? A: Top-posting. Q: What is the most annoying thing on usenet and in e-mail? |
|
![]() |
| Outils de la discussion | |
|
|