Shared Pointer Swap Strangness

I have a template function that I'm passing a shared pointer to. Within the function I swap the contents of the member variable (also a shared pointer of the base class of the calling pointer) with the passed in value. Inside the function, the debugger clearly shows that the shared pointers have swapped their values. When the debugger returns to the calling the function, the passed in pointer has reverted to the values it had before the call to the function. Here's the code

template <typename T>
void get_security(std::shared_ptr<T>& security) {
std::shared_ptr<T> tmp = reinterpret_cast<std::shared_ptr<T>&>(m_sa);
security.swap(tmp);
/// At this point in the debugger, the pointers hold the correct swapped values
}

in the calling function...

std::shared_ptr<mystruct> tmp = std::make_shared<mystruct>();

get_security(mystruct);

at the line after the call, the shared pointer is reverted to the values from the default constructor. Is there something wrong with the way I'm swapping?

Here's some sample code:

#include <iostream>
#include <string>
#include <memory>

///////////////////////////////////////////////////
/// base class to use in container for generic
/// pointer of derived classes
///////////////////////////////////////////////////
class mybase {
public:

mybase() {}

virtual ~mybase() {}

private:

delete mybase(mybase& rhs);
delete mybase(const mybase& rhs);

}

///////////////////////////////////////////////////
/// derived class to specialize the base
///////////////////////////////////////////////////
class myderive : public mybase {

public:

// default constructor
myderive() : mybase(),
m_int(0),
m_uint(0) {}

// constructor with types
myderive(int test,
uint32_t test2) : mybase(),
m_int(test),
m_uint(test2) {}

virtual ~myderive() {}

// specialize types for this derived class
template <typename T>
T get_val();

private:

delete myderive(myderive& rhs);
delete myderive(const myderive& rhs);

int m_int;
uint32_t m_uint;
}

// specialization of GET function for INT
template <>
int get_val() {
return m_int;
}

// specialization of GET function for UINT32_T
template <>
uint32_t get_val() {
return m_uint;
}

///////////////////////////////////////////////////
/// container class to hold generic information
///////////////////////////////////////////////////
class mycont {
public:

mycont(std::shared_ptr<mybase>& baseptr) : {
m_base.swap(baseptr);
}

virtual ~mycont() {}

template <typename T>
void set_base(std::shared_ptr<T>& newbase) { m_base.swap(newbase); }

template <typename T>
void get_derived(std::shared_ptr<T>& newderived) {
// cast from base to derived class
std::shared_ptr<T> tmp = reinterpret_cast<T>(m_base);
// swap derived to derived so all members are swapped
newderived.swap(tmp);
}

private:

delete mycont(mycont& rhs);
delete mycont(const mycount& rhs);

std::shared_ptr<mybase> m_base;
}

int main() {

// the point of this code is to replace a void pointer to any type of pointer for
// multiple derived classes with a shared smart pointer which has C++ garbage
// collection functionality which relieves the user of the need to "new" and track
// memory for deletion

// create the derived class
std::shared_ptr<myderived> getmesome = std::make_shared<myderived>(100, 0xFFFFFFFF);

// create the container to hold the derived class as base class (a la void* pointer)
std::shared_ptr<mycont> getcont = std::make_shared<mycont>(getmesome);

// create the derived pointer to retrieve derived from container where it's stored as base
std::shared_ptr<myderived> tmp = std::make_shared<myderived>(10, 0xEEFFAABB);

// get the derived class
getcont->get_derived(tmp);

// returned, swapped shared pointer should now have values from first derived class
std::cout << "From derived INT : " << tmp->get_val<int>() << ", and UINT : " << tmp->get_val<uint32_t>() << std::endl;
std::cout << "From original INT : " << getmesome->get_val<int>() << ", and UINT : " << getmesome->get_val<uint32_t>() << std::endl;
}

Last edited on
You have not posted real code so I'm not sure but that reinterpret_cast looks suspicious.

I think you should use std::static_pointer_cast or std::dynamic_pointer_cast.

 
std::shared_ptr<T> tmp = std::static_pointer_cast<T>(m_sa);
Actually this is an exact copy of the code for the classes, I've just changed the names. When compiled and run in the larger program that it exists in and stepped through using GDB, the call to the container at the code "getcont->get_derived(tmp)" shows that the contents of the two shared pointers in the line AFTER the reinterpret_cast are correct with the updated values displaying in the objects. In the very next step when the debugger returns to the calling function "getcont->get_derived(tmp)", the shared_ptr "tmp" reverts back to the values it has when it's default constructed in the line before "getcont->get_derived(tmp)". So...some pseudo code...

pointer "tmp" contents on default construction:

m_int = 10;
m_uint = 0xEEFFAABB

pointer "m_base" contents before call to swap:

m_int = 100;
m_uint = 0xFFFFFFFF;

pointer contents inside "get_derived()" after the swap:

tmp:
m_int = 100;
m_uint = 0xFFFFFFFF;

m_base:
m_int = 10;
m_uint = 0xEEFFAABB;

pointer contents of tmp after return from call:
m_int = 10;
m_uint = 0xEEFFAABB;

Actually this is an exact copy of the code for the classes

Really? The code contains so many errors that I don't know where to start.


This is not correct syntax
1
2
delete mybase(mybase& rhs);
delete mybase(const mybase& rhs);
If you don't want the mybase class to have copy constructor you would normally write
 
mybase(const mybase& rhs) = delete;


All the class definitions are missing a semicolon at the end.


The specializations of myderive::get_val() are missing the scope specifier.
1
2
3
4
5
6
7
8
9
10
11
// specialization of GET function for INT
template <>
int myderive::get_val() {
	return m_int;
}

// specialization of GET function for UINT32_T
template <>
uint32_t myderive::get_val() {
	return m_uint;
}



The mycont constructor has got a colon before the {.


This line shouldn't compile
 
std::shared_ptr<T> tmp = reinterpret_cast<T>(m_base);
You posted a similar code snippet where you casted into a std::shared_ptr<T>& instead of T. That one should compile but it doesn't do what you want.


In main() you used the name myderived when the class is really called myderive.


This line will fail to compile because the mycont constructor does not match (a std::shared_ptr<mybase>& can't refer to an object of type std::shared_ptr<myderive>).
 
std::shared_ptr<mycont> getcont = std::make_shared<mycont>(getmesome);
Last edited on
Topic archived. No new replies allowed.