Network connection setup in constructor: good or bad? - c++

I'm working on a class that handles interaction with a remote process that may or may not be available; indeed in most cases it won't be. If it's not, an object of that class has no purpose in life and needs to go away.
Is it less ugly to:
Handle connection setup in the constructor, throwing an exception if the process isn't there.
Handle connection setup in a separate connect() method, returning an error code if the process isn't there.
In option 1), the calling code will of course have to wrap its instantiation of that class and everything else that deals with it in a try() block. In option 2, it can simply check the return value from connect(), and return (destroying the object) if it failed, but it's less RAII-compliant,
Relatedly, if I go with option 1), is it better to throw one of the std::exception classes, derive my own exception class therefrom, roll my own underived exception class, or just throw a string? I'd like to include some indication of the failure, which seems to rule out the first of these.
Edited to clarify: The remote process is on the same machine, so it's pretty unlikely that the ::connect() call will block.

I consider it bad to do a blocking connect() in a constructor, because the blocking nature is not something one typically expects from constructing an object. So, users of your class may be confused by this functionality.
As for exceptions, I think it is generally best (but also the most work) to derive a new class from std::exception. This allows the catcher to perform an action for that specific type of exception with a catch (const myexception &e) {...} statement, and also do one thing for all exceptions with a catch (const std::exception &e) {...}.
See related question: How much work should be done in a constructor?

Regarding throwing exceptions, its perfectly fine to create your own classes. As a hypothetical user I'd prefer if they derived from std::exception, or perhaps std::runtime_error (which allows you to pass an error string to the ctor).
Users who want to can catch your derived type, but the common idiom of:
try {
operation_that_might_throw ();
} catch (std::exception& e) {
cerr << "Caught exception: " << e.what() << endl;
}
will work for your new exception types as well as anything thrown by the C++ runtime. This is basically the Rule of Least Surprise.

If your connection object is effectively non-functional if the connection fails then it doesn't make sense to have the object exist if all its other methods will always do nothing or throw exceptions. For this reason I would perform the connect in a constructor and fail by throwing an exception (derived from std::exception) if this method fails.
However, you are right that clients of the class may need to be aware that the constructor might block or fail. For this reason I might choose to make the constructor private and use a static factory method (named constructor idiom) so that clients have to make an explicit MakeConnection call.
It is still the client's responsibility to determine if not having a connection is fatal to it, or whether it can handle an offline mode. In the former case it can own a connection by value and let any connection failure propogate to its clients; in the latter it can own the object via a pointer, preferably 'smart'. In the latter case it might choose to attempt construction of the owned connection in its constructor or it might defer it until needed.
E.g. (warning: code all completely untested)
class Connection
{
Connection(); // Actually make the connection, may throw
// ...
public:
static Connection MakeConnection() { return Connection(); }
// ...
};
Here's a class that requires a working connection.
class MustHaveConnection
{
public:
// You can't create a MustHaveConnection if `MakeConnection` fails
MustHaveConnection()
: _connection(Connection::MakeConnection())
{
}
private:
Connection _connection;
};
Here's a class that can work without one.
class OptionalConnection
{
public:
// You can create a OptionalConnectionif `MakeConnection` fails
// 'offline' mode can be determined by whether _connection is NULL
OptionalConnection()
{
try
{
_connection.reset(new Connection(Connection::MakeConnection()));
}
catch (const std::exception&)
{
// Failure *is* an option, it would be better to capture a more
// specific exception if possible.
}
}
OptionalConnection(const OptionalConnection&);
OptionalConnection& operator=(const OptionalConnection&);
private:
std::auto_ptr<Connection> _connection;
}
And finally one that creates one on demand, and propogates exceptions to the caller.
class OnDemandConnection
{
public:
OnDemandConnection()
{
}
OnDemandConnection(const OnDemandConnection&);
OnDemandConnection& operator=(const OnDemandConnection&);
// Propgates exceptions to caller
void UseConnection()
{
if (_connection.get() == NULL)
_connection.reset(new Connection(Connection::MakeConnection()));
// do something with _connection
}
private:
std::auto_ptr<Connection> _connection;
}

Don't connect from the constructor, a constructor that blocks is unexpected and bad API design.
Write a connect method and mark your class noncopyable. If you rely on instances being connected already, make the constructor private and write a static factory method to get pre-connected instances.

If the connection would take a long time, it is more reasonable to put the code in another method. Still, you can (and you should) use exceptions to inform the caller whether your connect() method has been successful or not, instead of returning error codes.
It is also more advisable to create a new exception class derived from std::exception instead of throwing plain data or even throwing other STL exceptions. You may also derive your exception class from a more specific description of your error (for example, deriving from std::runtime_error), but this approach is less common.

I think Option 1 is a better approach but you need to think how would you expect the consumer of the class to use this? Just the fact that they have wired it up is good enough to go ahead and connect (Option 1) or the fact they should have the option to call Connect() when they are good and ready (Option 2)?
RAII also supports the DRY principle (don't repeat yourself). However with Option 1 you need to ensure you Exception handling is spot on and you don't get into race conditions. As you know, if there is an exception thrown in the constructor the destructor wont be called to clean up. Also be vary of any static functions you might have as you will need locks around those as well - leading you down a spiral path.
If you haven't seen this post yet its a good read.

I would go with the second one, since I believe that the constructor should not do any other thing than initialize the private members. Besides that, it's easier to deal with failures (such as not connecting). Depending on what you're exactly going to do, you could keep the object alive and call the connect method when you need it, minimizing the need of creating another object.
As for the exceptions, you should create your own. This will allow the caller to take specific rollback actions when needed.

Under the RAII mind of thought, isn't this by definition good? Acquisation is Initialization.

Another thing that was unclear in my original post is that the client code doesn't have any interaction with this object once it's connected. The client runs in its own thread, and once the object is instantiated and connected, the client calls one method on it that runs for the duration of the parent process. Once that process ends (for whatever reason), the object disconnects and the client thread exits. If the remote process wasn't available, the thread exits immediately. So having a non-connected object lying around isn't really an issue.
I found another reason not to do the connection in the constructor: it means that I either have to handle teardown in the destructor, or have a separate disconnect() call with no separate connect() call, which smells funny. The teardown is non-trivial and might block or throw, so doing it in the destructor is probably less than ideal.

I believe there is a pattern we can use here that addresses some of the points made in other answers. The question is pretty old but this was my first google result.
If the class is useless without a connection, then instantiating it conceptually appears to be half true. The object is not really ready to be used.
The user needs to separately call a connect() method. This just feels like bureaucracy.
Conversely, it is also true that a blocking operation is unconventional, and as other answers point out, may cause confusion. Not to mention annoyances in unit testing and threading.
I believe the pattern for this that addresses our problems is:
We can separate our functionality into more classes. The ready-to-go connection, the class that uses the connection and a factory.
The constructor needs the connection because it can't work without it.
Use a factory that sets up the connection to save the caller some work.
Our factory can be instantiated as empty (which makes sense). Then we can retrieve our class using it.
For example an FTPServer (not in C++ sorry)
class FTPServerFactory:
def get_with_environ_variables() -> FTPServer:
# create your connection here e.g. with FTP login details
class FTPServer:
def __init__(ftp_host: FTP_Host): #logged in an ready to go
There are two distinct benefits of this
Testing - we can easily mock a logged-in ftp_host to return whatever we want. This is way less confusing than having to reach into the class's constructor or the connect() method. We won't need to
Defining different ways of connecting using methods e.g. with env variables or user input

Related

Is it OK to store information regarding an error in an Exception object?

I've been reading about exceptions in C++, the pros and cons, and I've yet to encounter anyone mention the two things I really like about them: They allow me to extend the definition of an error (to something that is more than just an error message as a string), and, they allow me to define a contract between the exception handler and the thrower:
"If I'm going to handle this particular type of error, I'm going to
need this, this and that from you."
I've not seen this mentioned in any of the articles, forums and blog posts, as a pro or a con. And that has made me suspect that my mindset on exceptions and how they should be used may be wrong.
To clarify, here's an example of my usage of exceptions:
A program communicates with a USB device (it sends commands to the device and expects a certain response from it). This USB device can sometimes behave in an unexpected way when responding to a command. In this case, the program will throw an UnexpectedResponseFromDevice exception. The handler for this exception needs more than just an error message in order to do its job. For example, it may need to know of the command that we were sending to the device when the error occurred, and/or the state the device was in. I use the definition of my UnexpectedResponseFromDevice class to explicitly set out what is required to handle the exception. See below for a rough idea.
class UnexpectedResponseFromDevice : public std::exception
{
private:
Command command;
DeviceState deviceState;
std::string msg;
public:
UnexpectedResponseFromDevice(std::string msg, Command command, DeviceState deviceState, ...)
Command getCommand();
DeviceState getDeviceState();
};
This is what I meant by "define a contract between the exception handler and the thrower". In order to throw the exception, these things (in this case a Command, a DeviceState and a message) need to be provided.
Is this an acceptable use case for exceptions? Is it OK for me to store this other information, that is required for the handling of the exception, in the exception object? Is it acceptable but a bad idea? If so, please explain why.
Is this an acceptable use case for exceptions? Is it OK for me to store this other information, that is required for the handling of the exception, in the exception object?
Yes, that's how the exceptions in the standard library do too. One example is std::system_error that derives from std::runtime_error but adds a std::error_code member to carry extra information. One that adds a lot more is std::filesystem::filesystem_error that adds two std::filesystem::path objects.
Is it acceptable but a bad idea? If so, please explain why.
It's only a bad idea if you risk throwing another exception (like a std::bad_alloc) while throwing your exception - or if you use exceptions as something else than exceptions, like choosing between common branches in your program flow. Throwing should preferably be a rare event.
If your have all the info you need in a std::string, or even in something like a std::stack<std::string>>, member variable in the object that is a about to throw you can probably std::move that member object into the exception object to minimize the risk - if you don't need that data anymore in the object that is throwing that is.
I don't know how big your std::string, Command and DeviceState objects are, but you may not want to construct the exception object by taking the parameters by value. Try to make construction noexcept. The getters should also probably return by const&. That's not as critical - but making them so minimizes the risk of an exception in your exception handler.
Yes, a parameter is handed over. By means of it information is made available.
catch(const exception& e) { e....; }

Can i have boost asio socket references in two different class instances?

I want to std::move(my_asio_socket) to the instance of some class. What if I do the same for an instance of some other class?
My purpose is to read_async in one class instance (let's say class A), and to execute write_async in the other (let's say class B). Because of some functionality implementations, I should do it this way.
Any suggestion would be nice.
UPDATED
it's not working properly as i expected.
The VS2015(vc14 compiler) shows me a kind of exception while debugging:
Microsoft C++ exception: boost::exception_detail::clone_impl<boost::exception_detail::error_info_injector<boost::system::system_error> > at memory location 0x02D8E3BC.
And after i hit continue in VS it show me that:
Run-Time Check Failure #0 - The value of ESP was not properly saved across a function call. This is usually a result of calling a function declared with one calling convention with a function pointer declared with a different calling convention.
As i said, i'm trying to boost::move (or std::move) the socket to other class instance. Here is a snippet of code of what i'm doing:
boost::shared_ptr<connection> new_connection_;//it's a field in my class,
//that's why i should reset it later
new_connection_.reset(new connection(std::move(socket_), io_service_));
new_connection_->start();
Now here is my connection ctor:
connection::connection(boost::asio::ip::tcp::socket sock, boost::asio::io_service& io_ptr)
: socket_(boost::move(sock)),
io_ptr_(io_ptr),
remote_ep(socket_.remote_endpoint()),
//request_handler_(new request_handler(boost::move(socket_))),
work(new boost::asio::io_service::work(io_ptr))
{
boost::shared_ptr<request_handler> req_ptr(new request_handler(boost::move(socket_)));
request_handler_.swap(req_ptr);
}
As you can see, i've tried initializing in the commented line, but it shows me the same result.
Here is the ctor for request_handler:
request_handler::request_handler(boost::asio::ip::tcp::socket sock):
socket_(boost::move(sock)){ }
And here is my method connection::start where the problem detects:
void connection::start()
{
boost::asio::ip::tcp::socket::keep_alive kl(true);
boost::asio::ip::tcp::socket::enable_connection_aborted eca(true);
// here it breaks, when trying to set an option
socket_.set_option(eca);
socket_.set_option(kl);
socket_.async_read_some(boost::asio::buffer(buffer_),
boost::bind(&connection::handle_read, shared_from_this(),
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred));
}
This problem appears only when i use to move socket into the new instance of request_handler. If i'm not - then all goes okey. I can't understand what reason it could be, but seems like my socket_ (i declare it everywhere without any & or *) field from connection class is lost or kind of. But the debugger isn't showing me smthing like null, so i don't know what is it.
In general it is not guaranteed:
Move assignment operators typically "steal" the resources held by the argument (e.g. pointers to dynamically-allocated objects, file descriptors, TCP sockets, I/O streams, running threads, etc.), rather than make copies of them, and leave the argument in some valid but otherwise indeterminate state. For example, move-assigning from a std::string or from a std::vector may result in the argument being left empty. However, this behaviour should not be relied upon.
But according to the documentation for tcp::socket it is left in the same state:
Following the move, the moved-from object is in the same state as if constructed using the basic_stream_socket(io_service&) constructor.

Is it good practice to throw an exception in the constructor of a C++ class?

I've got this constructor which throws an exception
GenericSocket::GenericSocket(const string& hostname,
const string& servname):
_hostname(hostname),
_servname(servname)
{
initHints();
int rv;
if((rv = getaddrinfo(_hostname.c_str(),
_servname.c_str(),
&_hints,
&_servinfo)) != 0) {
throw GenericSocketException();
}
}
initHints() does a memset of _hints and sets some variables.
I test it with the google test framework like this:
TEST(CreateObject2, getaddrinfoException)
{
mgs_addrinfo_return = 1;
ASSERT_THROW(new GenericSocket("testhost", "4242"), GenericSocketException);
}
The test fails with a core dump:
[ RUN ] CreateObject2.getaddrinfoException
socket creation failed
terminate called after throwing an instance of 'common::GenericSocketException'
what(): Socket creation failed
[1] 43360 abort (core dumped) ./bin/test_common
Besides the fact that I dont know exactly what goes wrong, I suspect some uninitialised object gets deleted(?), a lot seems to happen under the hood, so I started to wonder if it is good practice to throw an exception in a constructor. Is it maybe better to put this functionality in another function which I can call after the creation of the object, and handle the exception afterwards?
IMHO, throwing an exception in a constructor is the best way to handle a situation like this - do you really want a usable object if there is no socket? it doesn't make sense to me. If it's failing to resolve that address, there's a reason for that and that is worthy of an exception (as long as you handle it correctly!)
In your particular case, you should test the return value and make the exception more useful... (for example, HostNotFound - which I'd guess is the case here)
Yes it is. You actually have no choice: constructors have no return values.
But take care of exception safety. See http://www.drdobbs.com/184403429 for instance, or google "strong exception guarantee". Indeed, an object whose constructor has thrown will not be destructed (it has never existed) and must be left in a state which doesn't leak resources.
Of course, the only reasonable thing to do when you can't construct an object is to throw exception, otherwise you would end up with some zombie objects. And answering your other question, no, you can't destroy an object that wasn't created.
Yes, throwing an exception is the most direct way to report that the constructor encountered problems, since they do not return values.
Destructors, on the other hand, should not throw exceptions, since they will be called in the stack unwinding phase of exception handling, and throwing another exception at this point would result in an abort.
There are already at least two discussions about this on SO. On both throwing exceptions from constructors and two-phase initialization:
1) When is it right for a constructor to throw an exception?
2) Throwing exceptions from constructors
If you learn at construction that you won't be able to create a valid object then throwing an exception is arguably your best option. The user of the class is thus forbidden from carrying on in case of error, unless they can handle it. That's usually the correct behaviour of a program.
function()
{
// 1. acquire resources.
// 2. perform action.
// 3. release resources.
}
If you can't fulfil step one then the other steps are futile. That's what we use RAII for: we acquire all the resources we need first, somewhat analogous to the old C style of programming with respect to stack variables. With RAII if any of the resources fail to acquire -- via an exception in the constructor -- then all previously acquired resources will release automatically and the second step will never be attempted. All done behind the scenes, automatically, but this assumes you throw an exception in the constructor if you can't create the object. It also assumes the destructor will do the clean-up.
struct Connection {
Connection() {
if( ! connect() ) throw ConnectionError();
}
~Connection() { // may not throw under any circumstances
try { disconnect(); }
catch( ... ) { }
}
void send(const std::string& message);
// ...
private:
bool connect();
// ...
};
void post(const std::string& message)
{
// step one is easy for the user:
Connection c;
// step two is the bulk of the work:
c.send("HELO");
// step three is automatically done for the user.
}

Minimalistic destructors?

We have some issue with my friend. Assume, we have a class which implements database connection, like this:
class DB
{
void Connect();
void Disconnect();
// ...
~DB();
};
In my opinion, destructor should be minimalistic, which means destructor should not call Disconnect method when connection was established. I think, that this should be done by separate method (disconnect() in this example). Am I correct, or my friend is?
PS. Community Wiki?
Your destructor should be enough to clean up all the resources that were acquired during the object lifetime. This might or might not include ending connnections. Otherwise who will do the cleanup if an exception is thrown?
The RAII idioms says: acquire in the constructor and release in the deconstructor. You must guarantee that your deconstructor will NOT throw anything. Otherwise you will have core dump (or undefined behaviour) if your object deconstructor will throw an exception during the stack-unwind.
Also in your specific case I will probably implement a reference counting mechanism, and call the disconnect just when you haven't any more object using the connection.
According to the syntax it looks like C++. Am I correct? Because if so, you can (and it is highly recommended to) use the RAII idiom. That means that you aquire the DB connection on construction, free it (disconnect) on destruction.
Good reference: What's RAII All About?
From the class user point of view, I believe it is better to try and disconnect the database connection when it should instead of assuming the destructor will do the job.
However, bad things happen, most notably exceptions, and you must guarantee that cleanup will occur regardless of what happened. This is why your destructor should nevertheless disconnect if necessary (i.e: if it hasn't been explicitly called by the user).

Constructor abort constructing

I would like to have the constructor abort object construction whenever it encounters certain error code (e.g. if the following is encountered):
CudaObj::CudaObj(InsertionSim *theSim)
{
// Setup
if(cublasInit() == CUBLAS_STATUS_NOT_INITIALIZED) {
printf("CUBLAS init error.\n");
return -1; // abort here rather than return a value
}
...
}
What would be the easiest way for this to be accomplished? Would it be exception handling?
I think the idiomatic way is to throw an exception from the constructor to emphasize that the object is not in a valid state.
Exception handling would definitely be my choice, especially in the case shown above, which really is an exception to the proper flow of the program. Alternatively, you could let the constructor return, and have a function 'IsInitilized()' or some such which would allow you/the user to verify it was completed appropriately. This however does impose an additional burden on the user of your class, that being said you might as well go with exception handling as it is a well-accepted way of imposing this burden (they have to catch the exception).
If you'd rather not use exceptions (although admittedly, I do in this situation), you could make a static method of the class in which you ask "Can I construct an object with these parameters?" and require that that method be called before you construct. So effectively, your constructor would become
CudaObj::CudaObj(InsertionSim *theSim)
{
// Setup
ASSERT(cublasInit() == CUBLAS_STATUS_NOT_INITIALIZED)
...
}
And then you'd need
BOOL CudaObj::CanConstruct(InsertionSim *theSim)
{
// Check if we can construct
return TRUE; // Or FALSE
}
So your code would be
if (CudaObj::CanConstruct(pSim))
{
pObj = new CudaObj(pSim);
}
else
{
// Handle invalid parameter
...
}
You could also provide a convenience method to do both (using OUT arguments, for instance).
Use an exception, unless you have some reason that you aren't using exceptions in your program. The reason is that by using an exception, you prevent the constructor of the object from EVER thinking the object is valid.
Your other choices are to have an 'IsInitialized' method (which will return false if the constructor failed), or a trivial (empty) constructor, and a separate 'Initialize' method, which can return an error code. These strategies are good ones if you are avoiding exceptions, and may be useful in situations where you are incorporating C++ code into older C code.
While I prefer exceptions unless I have a VERY good reason not to, exceptions may have some drawbacks. This article lists some of the drawbacks and several alternatives to exception handling.
Even if you use only exceptions for your error handling, I still recommend reading it.
One other thing: IMO you should not limit your considerations to constructor errors. maintaining two different error handling infrastructures in one system is hard and error prone. Try to select an error handling method for the whole system.
although constructor error handling is a big factor in this decision making, it is not the only one.