0

I am kind of new at c++. I have been using a library to handle serial communication in UNIX environments called libserial. I made a very simple test to try the library writing something to a peripheral and receiving an answer. The test went pretty well...code is shown below:

#include <SerialStream.h>
#include <iostream>
#include <string>
#include <unistd.h>
#include <cstdlib>

using namespace LibSerial ;


int main(int argc, char** argv)
{
SerialStream serial_port;
/*Open the serial port for communication*/
serial_port.Open( "/dev/ttyTHS2" );

/*Setting the baud rate*/
serial_port.SetBaudRate(SerialStreamBuf::BAUD_9600);

/*Setting the character size*/
serial_port.SetCharSize(SerialStreamBuf::CHAR_SIZE_8);

/*Setting number of stop bits*/
serial_port.SetNumOfStopBits(1);

/*Setting parity type*/
serial_port.SetParity(SerialStreamBuf::PARITY_NONE);

/*Setting Flow Control managment*/
serial_port.SetFlowControl( SerialStreamBuf::FLOW_CONTROL_NONE) ;

/*WRITTING ROUTINE*/

/*Requesting the TID of the current TAG*/
serial_port.write( "\r", 1);
serial_port.write( "021400", 6);
serial_port.write( "\r", 1);

/*READING RESPONSE FROM PERIPHERAL
const int BUFFER_SIZE = 256;
char input_buffer[BUFFER_SIZE];
serial_port.read(input_buffer, BUFFER_SIZE);
std::string input(input_buffer);
std::string TID = input.substr(5,16);
std::cout << "Current TAG identifier: " << TID << "\n";

/*Closing serial port*/
serial_port.Close();
return 0;

}

Since I want to perform more than a write/read operation...I decided to use functions in order to optimize the code and make it easier to change. My new optimized version is shown below:

#include <SerialStream.h>
#include <iostream>
#include <string>
#include <unistd.h>
#include <cstdlib>

using namespace LibSerial ;
using namespace std;

/*Function declaration*/
void serial_setup();
void serial_read();

int main(int argc, char** argv)
{
    SerialStream serial_port;
    /*SETUP BAUD RATE, PARITY BITS, ETC.
    serial_setup();

     /*Requesting the TID of the current TAG*/
    serial_port.write( "\r", 1);
    serial_port.write( "021400", 6);
    serial_port.write( "\r", 1);

    /*Read response from peripheral
    serial_read();

   /*Closing serial port*/
    serial_port.Close();
    return 0;

}

void serial_setup(){
    SerialStream serial_port;

    /*Open the serial port for communication*/
    serial_port.Open( "/dev/ttyTHS2" );

    /*Setting the baud rate*/
    serial_port.SetBaudRate(SerialStreamBuf::BAUD_9600);

    /*Setting the character size*/
    serial_port.SetCharSize(SerialStreamBuf::CHAR_SIZE_8);

    /*Setting number of stop bits*/
    serial_port.SetNumOfStopBits(1);

    /*Setting parity type*/
    serial_port.SetParity(SerialStreamBuf::PARITY_NONE);

    /*Setting Flow Control managment*/
    serial_port.SetFlowControl( SerialStreamBuf::FLOW_CONTROL_NONE) ;
}

void serial_read(){
    SerialStream serial_port;

    const int BUFFER_SIZE = 256;
    char input_buffer[BUFFER_SIZE];
    serial_port.read(input_buffer, BUFFER_SIZE);
    string input(input_buffer);
    string TID = input.substr(5,16);
    cout << "Current TAG identifier: " << TID << "\n";
}

The problem is that somehow, probably there is a condition that is not verified in one of the functions and is throwing the following error when executing:

    terminate called after throwing an instance of 'std::out_of_range'
  what():  basic_string::substr: __pos (which is 5) > this->size() (which is 3)
Aborted (core dumped)

I do not think is something related to a bad usage of the library rather than a bad creation of function from my part. I have been changing several things without any luck and it will really help me if you have any idea of where the out of range condition is happening.

Daniel Lara
  • 52
  • 1
  • 7
  • You now have two `SerialStream`s: `serial_setup()` creates a stream object, opens up a port, sets the baud rates, then at the end of the function it goes out of scope and probably closes up the port. Next, `serial_read()` creates a new stream object, never connects it to a physical port, then tries to read from a non-existent port, and fails. (Strictly speaking, the class might not work like that, but the above is the most likely scenario.) – Ken Y-N Aug 22 '17 at 00:00
  • 1
    Excellent explanation Ken Y-N, it makes total sense analyzing it that way. Solve it using VTT proposal. – Daniel Lara Aug 22 '17 at 00:26

1 Answers1

1

main, serial_setup and serial_read functions work with their own local SerialStream variables so changes are not preserved. You should pass SerialStream instance from main by reference:

void serial_setup(SerialStream & serial_port){

void serial_read(SerialStream & serial_port){

Or actually wrap up SerialStream into object with serial_setup becoming constructor, serial_read becoming method and serial_port.Close(); becoming destructor.

user7860670
  • 35,849
  • 4
  • 58
  • 84