I've been working on a server written in C++ and using SFML networking for the sockets and all. However, I've ran into a bit of a dead end for me. SFML Sockets are non-copyable and thus cannot be stored into most(all the ones that I know of) stl containers.
So, I quickly jumped to the idea of using a pointer and then it hit me that I should use RAII, but I hate smart pointers and needed to store more information than just the pointer to the Socket class.
I wrote a Client class that wraps the socket and deletes it when the destructor on the Client class gets called, which is fine and dandy..until I remembered that the stl containers will copy my class, delete the pointer and then I'd be left with a dangling pointer.
So, is there anyway I can get around non-copyables? I need the pointer to be stored within the class and I need the class to destroy the allocated memory.
I figured I could use a copy constructor to set the copied classes' pointer to null, but I cannot find a way to do that.
For Reference:
Client.cpp
Client::Client()
{
};
Client::Client(sf::TcpSocket* in_Connection)
{
m_Connection = in_Connection;
m_IPAddress = m_Connection->getRemoteAddress().toString();
m_AccountName = "NOACCOUNT";
m_CharacterName = "NOCHARACTER";
};
Client::~Client()
{
m_Connection->disconnect();
delete m_Connection;
};
//getters
sf::TcpSocket* Client::getConnection()
{
return m_Connection;
};
std::string Client::getIPAddress()
{
return m_IPAddress;
};
std::string Client::getAccountName()
{
return m_AccountName;
};
std::string Client::getCharacterName()
{
return m_CharacterName;
};
//setters -- Account Name and Character Name are the only two that can be changed during a connection.
void Client::setAccountName(std::string in_AccountName)
{
m_AccountName = in_AccountName;
};
void Client::setCharacterName(std::string in_CharacterName)
{
m_CharacterName = in_CharacterName;
};
//Copy Constructor <--This defintely won't work and I know that, haha.
Client::Client(const Client& that)
{
m_Connection = new sf::TcpSocket();
*m_Connection = *that.m_Connection; // Cannot copy non-copyable
m_IPAddress = that.m_IPAddress;
m_CharacterName = that.m_CharacterName;
m_AccountName = that.m_AccountName;
};
Server Accept Function
void Server::AcceptConnections()
{
sf::TcpSocket* Socket = new sf::TcpSocket();
if( m_Listener.accept(*Socket) == sf::Socket::Done)
{
if(Socket != NULL )
{
std::string IPAddress = Socket->getRemoteAddress().toString();
if( m_Connections.find( IPAddress ) == m_Connections.end() )
{
std::cout << IPAddress;
std::cout << " Has Connected.";
std::endl( std::cout );
m_Connections.insert( std::make_pair(IPAddress, Client(Socket) ) );
}
}
}
};
First of all, whether you can use C++11 or not is a game changer.
In C++11, you have the concept of move. Unlike copying, moving is not about duplicating but about transferring. All Standard containers were adapted to non-copyable classes that are movable.
An example of a movable class:
class Client {
public:
Client(Client const&) = delete; // non copyable
Client& operator=(Client const&) = delete; // non copy assignable
Client(Client&&) = default; // movable
Client& operator=(Client&&) = default; // move assignable
private:
std::unique_ptr<sf::TcpSocket> _socket;
};
And your problem is solved.
If you are stuck in C++03 land, you are in for a bit of trouble. The simplest solution would be to use a manager class:
the manager owns the instance
users of the instance only ever manipulates references/pointers to it
Related
I have a functional object that I'm using as body for multifunction_node:
class module
{
private:
bool valid;
QString description;
bool hasDetectionBranch;
tDataDescription bufData;
void* dllObject; //<-- This is a pointer to an object constructed with help of the external dll
qint64 TimeOut;
public:
module(const QString& _ExtLibName);
virtual ~module();
void operator() (pTransmitData _transmitData, multi_node::output_ports_type &op);
};
'dllObject' is created at construction time of the object 'module':
module::module(const QString& _ExtLibName) :
valid(true), hasDetectionBranch(false)
{
GetObjectDescription = (tGetObjectDescription)QLibrary::resolve(_ExtLibName, "GetObjectDescription");
CreateObject = (tCreateObject)QLibrary::resolve(_ExtLibName, "CreateObject");
DestroyObject = (tDestroyObject)QLibrary::resolve(_ExtLibName, "DestroyObject");
if (!CreateObject || !DestroyObject || !GetObjectDescription)
valid = false;
else
{
description = QString(GetObjectDescription());
dllObject = CreateObject();
}
}
And this is when 'dllObject' is destroyed:
module::~module()
{
if (valid)
{
DestroyObject(dllObject);
}
}
I've built a little graph:
void MainWindow::goBabyClicked(void)
{
module mod(QString("my.dll")); //<-- Here is OK and mod.dllObject is correct
if (!mod.isValid())
{
qDebug() << "mod is invalid!\n";
return;
}
first fir(input);
folder fol(QString("C:/out"), 10000);
graph g;
source_node<pTransmitData> src(g, fir, false);
multi_node mnode(g, tbb::flow::serial, mod); //<-- WTF? ~module() is executed!
function_node<pTransmitData> f(g, tbb::flow::serial, fol);
make_edge(src, mnode);
make_edge(mnode, f);
src.activate();
g.wait_for_all();
}
So I have 2 questions:
1) Why ~module() is executed and how to prevent this?
2) How to keep pointer for nested object correctly?
UPDATE Added some dummy code to prevent destroying dllObject at first time like:
bool b = false;
module::~module()
{
if (valid && b)
{
DestroyObject(dllObject);
}
if (!b)
b = true;
valid = false;
}
Now it works as expected but looks ugly :/
Max,
I assume you have a typedef of multi_node which is similar to the one in the reference manual example.
The constructor for the multifunction_node has the following signature:
multifunction_node( graph &g, size_t concurrency, Body body );
The body object is copied during the parameter passing and also during the construction of the node, so there are two copies of mod created during construction (actually three, as an initial copy of the body is also stored for re-initializing the body when calling reset() with rf_reset_bodies). The destructor calls you are seeing are probably those used to destroy the copies.
The body object should also have a copy-constructor defined or be able to accept the default-copy-constructor to make copies of the body. I think the QString has a copy-constructor defined, but I don't know about fields like tDataDescription. (I thought we had covered the basic requirements for Body objects in the Reference Manual, but I am still looking for the section.) In any case, the Body class must be CopyConstructible, as it is copied multiple times.
Regards,
Chris
Consider the following code:
// A non-copyable, non-movable aggregate
struct Strange
{
const int & i;
char & c;
};
class Container
{
private:
int my_i;
char my_c;
Strange thing;
public:
// Valid, because both `my_i´ and `my_c´ are non-const
// objects to which both references can be bound.
explicit
Container
( )
noexcept
: thing{ my_i , my_c }
{ }
// How could this be implemented?
auto &
operator=
( const Container & that )
noexcept
{
this->my_i = that->my_i;
this->my_c = that->my_c;
// What to do with `thing´?
return *this;
}
};
Possible solutions
Dynamically allocate the Strange object
class Container
{
private:
int my_i;
char my_c;
Strange * thing;
public:
// Note that it isn't exception safe.
explicit
Container
( )
: thing(new Strange{ my_i , my_c })
{ }
auto &
operator=
( const Container & that )
noexcept
{
this->my_i = that->my_i;
this->my_c = that->my_c;
delete this->thing;
this->thing = new Strange { this->my_i , this->my_c };
return *this;
}
};
Concerns:
Not efficient.
Not safe: allocation may fail and throw.
Dangerous: great care has to be taken not to leak memory.
Using a smart pointer (i.e. std::unique_ptr) would solve only the last point, aside from making the code more readable.
Use placement new
class Container
{
private:
int my_i;
char my_c;
Strange thing;
public:
explicit
Container
( )
noexcept
: thing{ my_i , my_c }
{ }
auto &
operator=
( const Container & that )
noexcept
{
this->my_i = that.my_i;
this->my_c = that.my_c;
// Placement new is exception safe, and so is
// construction of `Strange´.
this->thing.~Strange();
new(&this->thing) Strange { this->my_i , this->my_c };
return *this;
}
};
Concerns:
Will Strange's destructor free the memory taken by thing?
I think that, just as constructors, destructors are not responsible for memory management. Moreover, my code seems to work fine. However, I would like clarification on this.
What about memory alignment?
My guess is that, since it replaces an existing object of the same type, memory would already be aligned. Is this correct?
Would Container's destructor take care of destructing thing?
Questions
Aside from corroborating and/or refuting the concerns I explained above, I would like to know if there are other alternatives. If so, please, give an example implementation.
This question arose when working on a class that ought to offer an interface similar to that of std::unordered_map. Instead of reimplementing it, my class encapsulates such container, and just acts as a proxy for most methods: its iterators envelop those provided by the map, and its pair is an aggregate structure with appropiately named members (which are references to the actual data), represented in the examples provided as Strange. Since iterators are required to return references and pointers to the actual data, my custom iterators contain a pair. The problem was modifying it (when incrementing or assigning the iterator). I acknowledge that this probably isn't a good idea, and that those references will impact performance, but am anyway interested in the matter.
Edit
I have just realized that, instead of returning references and pointers to a member custom pair pointing to the actual data (that of the encapsulated map) from my custom iterator, I could return in-place constructed custom pairs (i.e. Strange objects). Often, we do not see that we are in a cave, and instead of exiting it, continue forward :). Excuse me for the noise, I'll mark the question as "Closed".
(If we're talking about moving objects and using the auto keyword, you should add the c++11 tag to your question).
I'm not sure I really understand your question; the example you gave doesn't seem well thought to me; it would be much better to use pointers in Strange.
For example, this compiles and works absolutely fine, and is functionally equivalent to what you want to do I think.
struct Strange
{
Strange()
: i(nullptr), c(nullptr) {}
Strange( const int *_i, const char *_c )
: i(_i), c(_c) {}
const int *i;
const char *c;
};
class Container
{
int my_i;
char my_c;
Strange thing;
public:
Container()
: thing(&my_i,&my_c)
{ }
Container( int i, char c )
: my_i(i), my_c(c), thing(&my_i,&my_c)
{ }
Container( int i, char c, const Strange& s )
: my_i(i), my_c(c), thing(s) // use default copy-constructor
{ }
Container &
operator=
( const Container & that )
{
my_i = that.my_i;
my_c = that.my_c;
thing = that.thing;
return *this;
}
};
int main()
{
Container a(12,24);
Container b(25,42);
b = a;
}
Note that referencing memory within objects is generally dangerous.
For example, using memcpy on this would be a catastrophy.
(Compiled with clang and g++)
Assuming the following code:
class ChannelHandle;
class SessionHandle;
typedef ChannelHandle& ChannelHandleRef;
typedef SessionHandle& SessionHandleRef;
class RemoteChannelHandle
{
public:
RemoteChannelHandle(
ChannelHandleRef pChannelHandle, SessionHandleRef pSessionHandle);
RemoteChannelHandle(RemoteChannelHandle&&);
~RemoteChannelHandle();
void CloseChannel();
#ifndef _MSC_VER
RemoteChannelHandle& operator=(RemoteChannelHandle&&) = delete;
RemoteChannelHandle(RemoteChannelHandle const&) = delete;
RemoteChannelHandle& operator=(RemoteChannelHandle const&) = delete;
#endif
private:
LIBSSH2_CHANNEL* channel;
ChannelHandleRef channelHandle;
SessionHandleRef sessionHandle;
};
RemoteChannelHandle::RemoteChannelHandle(
ChannelHandleRef pChannelHandle, SessionHandleRef pSessionHandle)
: channel(nullptr), channelHandle(pChannelHandle), sessionHandle(pSessionHandle)
{
// OPEN SSH CHANNEL
}
RemoteChannelHandle::~RemoteChannelHandle()
{
try
{
CloseChannel();
}
catch (...)
{ }
}
void RemoteChannelHandle::CloseChannel()
{
if (channel == nullptr)
{
return;
}
// CLOSE SSH CHANNEL. THROW IF SOMETHING GOES WRONG
channel = nullptr;
}
RemoteChannelHandle opens an SSH channel, but the cleanup requires
two steps (close + free). The first step is performed in
~RemoteChannelHandle(), but the second will be performed in
ChannelHandle's dtor; hence the data member channelHandle, since
we'll need to inject channel into it. This reference could be
eliminated by performing both steps in ~RemoteChannelHandle().
sessionHandle holds the LIBSSH2_SESSION* necessary to open the SSH
channel. Since I don't want to pass LIBSSH2_SESSION* around, this
reference can't be eliminated.
The problem happens when I define a move ctor for RemoteChannelHandle. I need to clear the members of the "moved from" instance. However, there's no way to clear the reference. So, what to do here?
Use (const) std::shared_ptr instead of references? I could even use
naked pointers, as there's no ownership involved. I realize there's some debate
regarding the use of references as data members, but apart from the
move ctor, I foresee no other scenario where I would need to reseat
the handles (which is why I used references in the first place).
Leave the references as they are, and create a "state" data member
specifically to check if the object is in a valid state (I can use channel != nullptr
for this purpose)?
Any other idea?
I've searched for alternatives to this, and found no clear answer. Which could mean there's actually no clear answer, of course.
Thanks for your time.
Edit (in reply to Mankarse):
ChannelHandle exists solely to perform step 2 of cleanup. Here's a simplified definition:
class ChannelHandle
{
public:
ChannelHandle();
ChannelHandle(ChannelHandle&&);
~ChannelHandle();
#ifndef _MSC_VER
ChannelHandle& operator=(ChannelHandle&&) = delete;
ChannelHandle(ChannelHandle const&) = delete;
ChannelHandle& operator=(ChannelHandle const&) = delete;
#endif
LIBSSH2_CHANNEL* GetChannel() { return channel; }
void SetChannel(LIBSSH2_CHANNEL* pChannel) { channel = pChannel; }
void FreeChannel();
private:
LIBSSH2_CHANNEL* channel;
};
SessionHandle is an RAII encapsulation for a LIBSSH2_SESSION*. It calls libssh2_session_init() on ctor and libssh2_session_free() on dtor. Other similar classes take care of other steps of the SSH session's init/cleanup, but this is where we get the LIBSSH2_SESSION* from libssh2, and SessionHandle owns it. Once again, a simplified definition:
class SessionHandle
{
public:
SessionHandle();
SessionHandle(SessionHandle&&);
~SessionHandle();
void CloseSession();
LIBSSH2_SESSION* GetSession() { return session; }
#ifndef _MSC_VER
SessionHandle& operator=(SessionHandle&&) = delete;
SessionHandle(SessionHandle const&) = delete;
SessionHandle& operator=(SessionHandle const&) = delete;
#endif
private:
LIBSSH2_SESSION *session;
};
You've answered the question yourself:
I could even use naked pointers, as there's no ownership involved.
I'm quite new to C++ and I am trying to store objects inside a std::vector like this:
Event.h:
//event.h
class Event
{
public:
Event();
Event(std::string name);
~Event();
void addVisitor(Visitor visitor);
private:
std::vector<Visitor> m_visitors;
};
Event.cpp:
//event.cpp
Event::Event() :
m_name("Unnamed Event")
{
}
Event::Event(std::string name) :
m_name(name)
{
}
void Event::addVisitor(Visitor visitor)
{
this->m_visitors.push_back(visitor);
}
void Event::listVisitors()
{
std::vector<Visitor>::iterator it;
for(it = this->m_visitors.begin();it != this->m_visitors.end(); ++it)
{
std::cout << it->getName() << std::endl;
}
}
Visitor.h:
//visitor.h
class Visitor
{
public:
Visitor();
Visitor(std::string name);
~Visitor();
std::string getName() const;
void listVisitors();
private:
std::string m_name;
};
Visitor.cpp:
//visitor.cpp
Visitor::Visitor() :
m_name("John Doe")
{
}
Visitor::Visitor(std::string name) :
m_name(name)
{
}
std::string Visitor::getName() const
{
return m_name;
}
main.cpp:
//main.cpp
int main()
{
Event *e1 = new Event("Whatever");
Visitor *v1 = new Visitor("Dummy1");
Visitor *v2 = new Visitor("Dummy2");
e1->addVisitor(*v1);
e1->addVisitor(*v2);
}
If I do it like this I would have to add a copy constructor which would make a deep copy so the object gets copied properly into the vector. I'm looking for a way around it by only storing pointers to the objects in a vector.
I already tried it with std::vector<std::unique_ptr<Visitor> > m_visitors, but then I got some errors when calling addVisitor in main.cpp. Of course I changed the declaration of the class members accordingly.
How would an appropriate declaration of the members and the member function look like to make it work?
Stylistically, if you are passing pointers, just accept pointers as the function arguments.
What's happening in the example code above is that the visitors are getting copied to become function arguments and the pointers you had are unreferenced by anything outside of the main function.
I can't speak to what the errors are that you're seeing as you didn't describe them but it probably has to do with incompatible types.
Just get rid of the news because for these data structures they're unnecessary.
int main()
{
Event e1("Whatever");
Visitor v1("Dummy1");
Visitor v2("Dummy2");
e1.addVisitor(v1);
e1.addVisitor(v2);
}
I would suggest that if you don't know how to use pointers you couldn't possibly want to store them instead (they're a hassle IMO to store in the vector when copying by value works just fine).
The compiler generated copy constructor should work just fine.
No manual deep copy required, because you are quite correctly using std::string, which supports RAII.
However, your main function has three memory leaks — there is no need to use new there anyway, so simply don't.
General rule of thumb:
If, at any time T, you're thinking of introducing more pointers into your code, then you're probably going in the wrong direction.
I just got burned by a bug that is partially due to my lack of understanding, and partially due to what I think is suboptimal design in our codebase. I'm curious as to how my 5-minute solution can be improved.
We're using ref-counted objects, where we have AddRef() and Release() on objects of these classes. One particular object is derived from the ref-count object, but a common function to get an instance of these objects (GetExisting) hides an AddRef() within itself without advertising that it is doing so. This necessitates doing a Release at the end of the functional block to free the hidden ref, but a developer who didn't inspect the implementation of GetExisting() wouldn't know that, and someone who forgets to add a Release at the end of the function (say, during a mad dash of bug-fixing crunch time) leaks objects. This, of course, was my burn.
void SomeFunction(ProgramStateInfo *P)
{
ThreadClass *thread = ThreadClass::GetExisting( P );
// some code goes here
bool result = UseThreadSomehow(thread);
// some code goes here
thread->Release(); // Need to do this because GetExisting() calls AddRef()
}
So I wrote up a little class to avoid the need for the Release() at the end of these functions.
class ThreadContainer
{
private:
ThreadClass *m_T;
public:
ThreadContainer(Thread *T){ m_T = T; }
~ThreadContainer() { if(m_T) m_T->Release(); }
ThreadClass * Thread() const { return m_T; }
};
So that now I can just do this:
void SomeFunction(ProgramStateInfo *P)
{
ThreadContainer ThreadC(ThreadClass::GetExisting( P ));
// some code goes here
bool result = UseThreadSomehow(ThreadC.Thread());
// some code goes here
// Automagic Release() in ThreadC Destructor!!!
}
What I don't like is that to access the thread pointer, I have to call a member function of ThreadContainer, Thread(). Is there some clever way that I can clean that up so that it's syntactically prettier, or would anything like that obscure the meaning of the container and introduce new problems for developers unfamiliar with the code?
Thanks.
use boost::shared_ptr
it is possible to define your own destructor function, such us in next example: http://www.boost.org/doc/libs/1_38_0/libs/smart_ptr/sp_techniques.html#com
Yes, you can implement operator ->() for the class, which will recursively call operator ->() on whatever you return:
class ThreadContainer
{
private:
ThreadClass *m_T;
public:
ThreadContainer(Thread *T){ m_T = T; }
~ThreadContainer() { if(m_T) m_T->Release(); }
ThreadClass * operator -> () const { return m_T; }
};
It's effectively using smart pointer semantics for your wrapper class:
Thread *t = new Thread();
...
ThreadContainer tc(t);
...
tc->SomeThreadFunction(); // invokes tc->t->SomeThreadFunction() behind the scenes...
You could also write a conversion function to enable your UseThreadSomehow(ThreadContainer tc) type calls in a similar way.
If Boost is an option, I think you can set up a shared_ptr to act as a smart reference as well.
Take a look at ScopeGuard. It allows syntax like this (shamelessly stolen from that link):
{
FILE* topSecret = fopen("cia.txt");
ON_BLOCK_EXIT(std::fclose, topSecret);
... use topSecret ...
} // topSecret automagically closed
Or you could try Boost::ScopeExit:
void World::addPerson(Person const& aPerson) {
bool commit = false;
m_persons.push_back(aPerson); // (1) direct action
BOOST_SCOPE_EXIT( (&commit)(&m_persons) )
{
if(!commit)
m_persons.pop_back(); // (2) rollback action
} BOOST_SCOPE_EXIT_END
// ... // (3) other operations
commit = true; // (4) turn all rollback actions into no-op
}
I would recommend following bb advice and using boost::shared_ptr<>. If boost is not an option, you can take a look at std::auto_ptr<>, which is simple and probably addresses most of your needs. Take into consideration that the std::auto_ptr has special move semantics that you probably don't want to mimic.
The approach is providing both the * and -> operators together with a getter (for the raw pointer) and a release operation in case you want to release control of the inner object.
You can add an automatic type-cast operator to return your raw pointer. This approach is used by Microsoft's CString class to give easy access to the underlying character buffer, and I've always found it handy. There might be some unpleasant surprises to be discovered with this method, as in any time you have an implicit conversion, but I haven't run across any.
class ThreadContainer
{
private:
ThreadClass *m_T;
public:
ThreadContainer(Thread *T){ m_T = T; }
~ThreadContainer() { if(m_T) m_T->Release(); }
operator ThreadClass *() const { return m_T; }
};
void SomeFunction(ProgramStateInfo *P)
{
ThreadContainer ThreadC(ThreadClass::GetExisting( P ));
// some code goes here
bool result = UseThreadSomehow(ThreadC);
// some code goes here
// Automagic Release() in ThreadC Destructor!!!
}