1
votes

I have an application that uses boost::asio::ip::tcp::iostream to connect to another application via tcp.

My server code is:

static auto const flags = boost::archive::no_header | boost::archive::no_tracking;
boost::asio::io_service ios;
boost::asio::ip::tcp::endpoint endpoint
= boost::asio::ip::tcp::endpoint(boost::asio::ip::tcp::v4(), 4444);
boost::asio::ip::tcp::acceptor acceptor(ios, endpoint);
boost::asio::ip::tcp::iostream stream;

//program stops here until client connects.
acceptor.accept(*stream.rdbuf());

and my client is:

std::string ip = "127.0.0.1";

    boost::asio::ip::tcp::iostream stream(ip, "4444");

    if (!stream)
        throw std::runtime_error("can't connect");

If the server is launched first, this works great. But if the client is launched first, it will throw the error and crash. What I would like to do is be able to launch either side first, and have it wait for the connection. The client is obviously the issue, so i am trying:

 bool bConnected;

    std::string ip = "127.0.0.1";
    boost::asio::ip::tcp::iostream* stream;

    while (!bConnected)
    {
        stream = new boost::asio::ip::tcp::iostream(ip, "4444");
        if (!stream)
        {
            std::cout << "cannot find datastream" << std::endl;
            std::this_thread::sleep_for(std::chrono::milliseconds(50));
            //throw std::runtime_error("can't connect");
        }

        if (stream)
        {
            bConnected = true;
        }

    }

This will not compile, giving me an error on boost::asio::ip::tcp::iostream* stream, with Error C4703 potentially uninitialized local pointer variable 'stream' used. I have tried:

boost::asio::ip::tcp::iostream* stream = nullptr; boost::asio::ip::tcp::iostream* stream = NULL;

both compile, but crash. How can I have the client wait for the server, in this situation?

1
I doubt you get an error, but rather a warning. It's impossible to say though, because you haven't shown us the actual output of the build which we really need (in full and complete).Some programmer dude
What you do use uninitialized and which is most likely the reason for the warning (and the crash) is the variable bConnected. The value of uninitialized local variables is indeterminate (and will seem random) and using them in any way without initialization is undefined behavior.Some programmer dude
updated with the actual warning that is stopping compilation. Error C4703 potentially uninitialized local pointer variable 'stream' usedanti
What @Someprogrammerdude said. Try bool bConnected = false; (and stream=nullptr for good measure). Reason: if bConnected happens to be true, the whole while-block is skipped and stream is and the following code will access the uninitialized streamdjf
Now you have another problem, and that is with the condition checking the stream variable. It is a pointer so if (!stream) doesn't check the success of the connection, but check if the pointer is a null pointer or not. The condition !stream is equal to stream == nullptr (and plain stream in a condition is equal to stream != nullptr). To solve this, think about how you can get the object a pointer is pointing to.Some programmer dude

1 Answers

4
votes

Never use new¹. Because as you commented, if (!*stream) compiles but it leaks resource like there's no tomorrow.

In this case:

Live On Coliru

#include <boost/asio.hpp>
#include <iostream>
#include <thread>

using boost::asio::ip::tcp;

int main() {
    tcp::iostream stream;

    do {
        std::cout << "Connecting...\n";

        stream.clear();
        stream.connect("127.0.0.1", "4444");

        std::this_thread::sleep_for(std::chrono::milliseconds(500));
    } while (!stream);

    std::cout << "Connected! " << stream.rdbuf();
}

Which prints:

Connecting...
Connecting...
Connecting...
Connecting...
Connecting...
Connecting...
Connected! Hello world

¹ unless you're writing a low-level resource wrapper for your library interface.