-1

I have some working code, but the error handling is fairly crude at the moment - it generally sends an error string to standard error and exits. So I would like it to throw an exception and allow the user to deal with it as they choose with a typical handler.

However, having added a try catch block to the code it is giving me a compiler error that I don't understand at all.

My code looks like this:

// -------------------------------------------------------------------------
sockets::TCPSocket::TCPSocket(const char* address, const int port)
{
    this->address    = address;
    this->port       = port;
    this->bufferSize = sockets::TCPSocket::DEF_BUFFER;
    sockets::TCPSocket::init();
}

// -------------------------------------------------------------------------
sockets::TCPSocket::~TCPSocket()
{
    freeaddrinfo(this->addressInfoList);
    close(this->filedes);
}

// -------------------------------------------------------------------------
void sockets::TCPSocket::init()
{
    memset(&(this->addressInfo), 0, sizeof this->addressInfo);

    addressInfo.ai_family   = AF_UNSPEC;      // Either IPv4 or IPv6
    addressInfo.ai_socktype = SOCK_STREAM;    // Uses TCP
    addressInfo.ai_flags    = AI_PASSIVE;     // Accept any IP

    // get the address info
    int status = getaddrinfo(
        this->address,
        std::to_string(this->port).c_str(),
        &(this->addressInfo),
        &(this->addressInfoList)
    );

    if (status != 0)  // any error- segfault if addressInfoList not allocated
    {
        throw GetAddrinfoException();
    }

    // create socket
    this->filedes = socket(
        this->addressInfoList->ai_family,
        this->addressInfoList->ai_socktype,
        this->addressInfoList->ai_protocol
    );

    if (this->filedes == -1)
    {
        std::cerr << "Create socket error: " << strerror(errno) << std::endl;
        exit(EXIT_FAILURE);
    }
}

// -------------------------------------------------------------------------

As you see I am calling a (private) init() function from my constructor. And I throw a GetAddrinfoException in my init() function. If I wrap the call to init() in a try catch wihtin the constructor it works fine. But when I call it from my main - expecting the stack to unwind - I get a compiler error.. like this:

int main()
    {
        using namespace std;

        // Test as client
        const char* TEST_ADDR = "www.google.com";
        try
        {
            sockets::TCPSocket socket = sockets::TCPSocket(TEST_ADDR, 80);
        }
        catch (sockets::GetAddrinfoException e) { /* do something */ }

    return 0;
}

The compiler error lists each of the member functions of TCPSocket and gives this message:

TCPSocket/test.cpp: In function ‘int main()’:
TCPSocket/test.cpp:22:12: error: request for member ‘doConnect’ in ‘socket’, which is of non-class type ‘int(int, int, int) throw ()’
     socket.doConnect();
            ^
TCPSocket/test.cpp:23:12: error: request for member ‘doSend’ in ‘socket’, which is of non-class type ‘int(int, int, int) throw ()’
     socket.doSend("GET / HTTP/1.1\r\nHost: www.redway-soft.com\r\n\r\n");
            ^
TCPSocket/test.cpp:24:20: error: request for member ‘doRecv’ in ‘socket’, which is of non-class type ‘int(int, int, int) throw ()’
     cout << socket.doRecv() << endl;
                    ^
TCPSocket/test.cpp:34:12: error: request for member ‘restart’ in ‘socket’, which is of non-class type ‘int(int, int, int) throw ()’
     socket.restart();
            ^
TCPSocket/test.cpp:35:30: error: request for member ‘doListen’ in ‘socket’, which is of non-class type ‘int(int, int, int) throw ()’
     string received = socket.doListen();
                              ^

Despite searching through multiple tutorials and guides I cannot find any reason for this problem. Any help would be much appreciated.

EDIT:

The class definition looks like this:

#ifndef __TCPSOCKET_HPP__
#define __TCPSOCKET_HPP__

#include <cstring>
#include <sys/socket.h>
#include <netdb.h>
#include <unistd.h>
#include <string>
#include <vector>
#include <iostream>
#include <cerrno>
#include <exception>


namespace sockets
{

    class GetAddrinfoException: std::exception
    {
        public:
            virtual const char* what() const throw()
            {
                return "getAddressinfo() failure";
            }
    };



    /**
    * @class TCPSocket, creates a HTTP/TCP Socket. TCPSocket is designed with the idea
    * that it should usually be instantiated in its own thread for most use cases.
    * @param const char* address, e.g. www.google.com
    * @param int port, which port defaults 80
    */
    class TCPSocket
    {
        private:

            /**
            * Instance vars
            */
            struct addrinfo  addressInfo;
            struct addrinfo* addressInfoList;
            int              filedes;
            const char*      address;
            int              port;
            int              bufferSize;

            /**
            * @function init, allows socket to be re-assigned a new address and port
            */
            void init();

        public:

            /**
            * pulbic class vars
            */
            static const int DEF_BUFFER   = 2000;
            static const int DEF_PORT     = 5556;
            static const int DEF_TIMEOUT  = 200000;
            static const int DEF_NUMTRIES = 5;

            /**
            * @constructor
            * @param address, to connect to default is NULL siffnifying server socket
            * @param port, port to connect/listen on
            */
            TCPSocket(const char* address = NULL, const int port = DEF_PORT);
            /**
            * @destructor
            */
            ~TCPSocket();

            /**
            * public getters
            */
            inline const char*            getAddress()         {return this->address;}
            inline const int&             getPort()            {return this->port;}
            inline const struct addrinfo& getAddressInfo()     {return this->addressInfo;}
            inline const int&             getFiledes()         {return this->filedes;}
            inline const struct addrinfo* getAddressInfoList() {return this->addressInfoList;}

            /**
            * @function setBuffer, set bufferSize to custom size
            * @param buffer, the size to set the read in buffer
            */
            inline void setBuffer(int buffer) {this->bufferSize = buffer;}

            /**
            * @function restart, cleans up and then re-initialises the socket with new params
            * @param address, to connect to
            * @param port, port to connect
            */
            void restart(const char* address = NULL, const int port = DEF_PORT);

            /**
            * @function doConnect, connect to target address
            */
            void doConnect();

            /**
            * @function doSend - sends specific message,
            * @param message e.g. "GET / HTTP/1.1\r\nHost: www.google.com\r\n\r\n"
            * would send a simple get request, or a html string could be sent back
            * in the case of send from a server socket which is responding to a
            * request.
            */
            void doSend(const char* message);

            /**
            * @function doRecv, gets return data from server
            * @param timeout, length of time to wait (micros) for data def = 100 000
            * @param numtries, number of attempts at reading data if none recv
            * @return message that has been received
            */
            std::string doRecv(int timeout = DEF_TIMEOUT, int numtries = DEF_NUMTRIES);

            /**
            * @function doListen, listens at given port and accepts a connection
            * note that this function is blocking and so any implementation should
            * probably normally be on its own thread/process, a server class should
            * be in charge of managing individual threads and sockets.
            */
            std::string doListen();


            /**
            * @function doClose, closes the filedescripter.
            */
            void doClose();
    };
}

#endif
Sam Redway
  • 7,605
  • 2
  • 27
  • 41
  • What's _`catch (GetAddrinfoException e) { /* do something */ }`_ actually?? – πάντα ῥεῖ Jul 05 '15 at 15:55
  • It looks like the origin of the error is somewhere in your class definition of `sockets::TCPSocket`. – ikrabbe Jul 05 '15 at 15:55
  • I shall add the class header file. what do you mean πάντα ῥεῖ ? I presume you know what a try {} catch(){} block is... – Sam Redway Jul 05 '15 at 15:57
  • 1
    Off-topic, but you're using a [reserved identifier](http://stackoverflow.com/questions/228783/what-are-the-rules-about-using-an-underscore-in-a-c-identifier) for your include guard. – chris Jul 05 '15 at 16:10

1 Answers1

1

My crystal ball is telling me that you're using socket beyond the catch block, but its scope is until the end of the try block. Do what you need to with socket in the try block.

The reason it doesn't say that socket is not declared is because it is a function, such as this one for Linux or this one for Windows. Inside your try block, the local variable shadows the function.

chris
  • 60,560
  • 13
  • 143
  • 205