Thread: Casting raw ptr to shared_ptr

  1. #1
    Registered User
    Join Date
    Mar 2015
    Posts
    184

    Casting raw ptr to shared_ptr

    I have a method that takes a raw pointer and then tries to assign a member shared_ptr to that value. But it does not work, the program crashes without an error--what am I doing wrong?

    Code:
    //member data is of type std::shared_ptr<T>
    
    void load(T* Tptr){
        if (data==nullptr)
          {
            data.reset(Tptr); //but data.reset(new T) works
          }
    Explicitly initializing data to nullptr in the constructor doesn't make a difference, the crash occurs on the assignment.

  2. #2
    Registered User
    Join Date
    Oct 2006
    Posts
    3,445
    Did you try running it in a debugger to see where it's actually crashing, and inspect the values of the various things at that time?
    What can this strange device be?
    When I touch it, it gives forth a sound
    It's got wires that vibrate and give music
    What can this thing be that I found?

  3. #3
    Registered User
    Join Date
    Mar 2015
    Posts
    184
    Here is main(). just 4 lines of code...
    Code:
      double arr[6] {1,2,3,4,5,6}; //create sample data
      BImg<double> img;
      double x {5.0}; //commenting out this unrelated line makes it crash...  
      img.load(arr); //implicitly creates raw double pointer, crashes when assigning member "data"
    Here is the class Minimal Example
    Code:
    template<typename T>
    class BImg
    {
    std::shared_ptr<T> data;
    BImg(){} //empty ctor
    void load(T*); //see earlier definition
    };

    What messes me up is: when i declare & initialize some unused double x it doesn't crash.

    EDIT:
    I just noticed my shared_ptr is probably trying to delete something from the stack... guess I was too optimistic about the smarts of smart pointers sorry.
    Last edited by jiggunjer; 07-02-2015 at 12:24 PM.

  4. #4
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Well, obviously it's going to crash if you try to assign something to a smart pointer that you did not "new". That's what smart pointers are, after all. There's no sense in assigning something that belongs on the stack, though, as the stack cleans itself up automatically.
    You could also use a customer deleter if the data must be freed but does not come from new.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  5. #5
    Registered User
    Join Date
    Oct 2006
    Posts
    3,445
    Quote Originally Posted by jiggunjer View Post
    guess I was too optimistic about the smarts of smart pointers sorry.
    There is no standard way to know whether a pointer was allocated with new or not.
    What can this strange device be?
    When I touch it, it gives forth a sound
    It's got wires that vibrate and give music
    What can this thing be that I found?

  6. #6
    Registered User
    Join Date
    Mar 2015
    Posts
    184
    Hmm I should reconsider my class design then. I thought it might be easier for the client if it handled deletion, but I cant guarantee that they will only try to load data from the heap...

  7. #7
    Master Apprentice phantomotap's Avatar
    Join Date
    Jan 2008
    Posts
    5,108
    O_o

    You are already using a C++11 feature so I'll assume you don't mind more C++11 features.

    With that in mind, I'd suggest defaulting to copying the data optionally referencing the data which does require a length.

    Code:
    template <typename S> void load(S ptr, size_t size);
    You can then use `std::ref` to do the informing.

    Code:
    double arr[6] {1,2,3,4,5,6};
    BImg<double> img;
    double x {5.0};
    img.load(std::ref(arr), 6);
    If you write the relevant convenience functions, the interface is very palatable.

    Soma
    “Salem Was Wrong!” -- Pedant Necromancer
    “Four isn't random!” -- Gibbering Mouther

  8. #8
    Registered User
    Join Date
    Mar 2015
    Posts
    184
    If I don't copy, will a smart pointer to a std::ref wrapper-object delete only the wrapper if it's a reference to a stack variable, but delete the data as well if it's a ref to a heap variable?
    Last edited by jiggunjer; 07-03-2015 at 03:17 AM.

  9. #9
    Registered User cstryx's Avatar
    Join Date
    Jan 2013
    Location
    Canada
    Posts
    123
    Quote Originally Posted by Elkvis View Post
    There is no standard way to know whether a pointer was allocated with new or not.
    There's hacks, but they are most definitely platform dependent and implementation defined; not portable.

    The only way to know, is upon allocation itself, and so if he really wanted, he could create a wrapper that deals with pointers to addresses on the stack vs. heap separately through one single interface... This still relies on the caller properly differentiating between stack and heap pointers though and the implementation of this would get cumbersome to manage. Because it's still the caller's responsibility not to screw things up I would say that this is not much different than the responsibility of using smart pointers, or rather dealing with pointers properly to begin with to ensure that there's no requirement to have to deal with issues like this allocation one.

    Just my opinion... I'm sure there are many others out there, and maybe someone else can elaborate on this. I actually think that boost::shared_ptr has an implementation set up for doing such things(?)

    I read this on an article on SO:
    Code:
    template<typename T> void no_delete(T* ptr) { /* do nothing here */ }
    
    class YourDataType; // defined elsewhere
    boost::shared_ptr<YourDataType> heap_ptr(new YourDataType()); // delete at scope end
    
    YourDataType  stackData;
    boost::shared_ptr<YourDataType> stack_ptr(&stackData, &no_delete); // never deleted
    If one chooses to go down this dark path... ^^This is probably the best bet, if you don't choose the better option to just use smart pointers properly.

    I'm pretty certain that standard smart pointers operate in the same way. So it's your own responsibility to know that a pointer is pointing to something on the heap or the stack... From that point you can decide whether the smart pointer uses the default deleter, or one of your own:
    Code:
    template<class T, class D = default_delete<T>> class unique_ptr;
    The default deleter's as far as the standard is concerned, means that either delete or delete[] is called for the stored pointer.

    The default type for the template parameter D is default_delete. A client-supplied template argument D shall be a function object type(20.9), lvalue-reference to function, or lvalue-reference to function object type for which, given a value d of type D and a value ptr of type unique_ptr<T, D>:: pointer, the expression d(ptr) is valid and has the effect of disposing of the pointer as appropriate for that deleter.
    Last edited by cstryx; 07-05-2015 at 01:56 PM.

  10. #10
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    What I'd do is first decide whether or not the class should share ownership of the pointer or not. If not, then the caller is responsible for keeping the pointer alive until the class is destroyed. In that case, take a raw pointer (and don't delete it!). If you want to share ownership, then just take shared pointer.

    If you absolutely must have both ways, then you can internally wrap the raw pointer in a no-op shared_ptr. Hence you can have a shared_ptr member in your class as a member to take care of the deletion.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  11. #11
    Registered User
    Join Date
    Mar 2015
    Posts
    184
    I'd also have to determine if to delete or to delete[]... I think I'll just leave it to the user to delete their data .

  12. #12
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    If the user is responsible for deleting the data, then you don't have to worry about that. If you take a shared_ptr, then the user is responsible for providing a correct deleter, which should be automatically determined by the type of T. Still, I'd always use a std::vector or std::array as the type which means you should always use delete.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  13. #13
    Registered User
    Join Date
    Oct 2006
    Posts
    3,445
    Quote Originally Posted by cstryx View Post
    There's hacks, but they are most definitely platform dependent and implementation defined; not portable.
    Which is exactly why I included the word "standard" in my reply. As a general rule, we only discuss standard C++ here, unless the OP asks about a specific library or implementation-defined feature.
    What can this strange device be?
    When I touch it, it gives forth a sound
    It's got wires that vibrate and give music
    What can this thing be that I found?

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. ~shared_ptr() block until shared_ptr::unique is true
    By CodeMonkey in forum C++ Programming
    Replies: 10
    Last Post: 12-17-2014, 09:28 PM
  2. Using shared_ptr instead of raw pointers
    By gopu in forum C++ Programming
    Replies: 5
    Last Post: 08-27-2009, 06:51 AM
  3. intrusive_ptr vs shared_ptr
    By KIBO in forum C++ Programming
    Replies: 0
    Last Post: 08-24-2009, 03:14 AM
  4. When to use shared_ptr?
    By hpesoj in forum C++ Programming
    Replies: 15
    Last Post: 07-22-2008, 04:33 AM
  5. Is shared_ptr dangerous?
    By Elysia in forum C++ Programming
    Replies: 19
    Last Post: 04-07-2008, 02:02 AM