#c #arrays #segmentation-fault #uart
Вопрос:
Я получаю строковые данные из UART и преобразую их в шестнадцатеричный формат. После преобразования в шестнадцатеричный формат у меня есть два уникальных разделителя «06» и «07». Я хочу получить данные между этими двумя разделителями. Я попытался построить приведенный ниже код на основе того, что я сказал. Но после получения 6-7 выходных данных я получаю ошибку ошибки сегментации.
std::string sub_between(std::string start,std::string stop,std::string input)
{
auto start_index = input.find(start);
if (start_index != std::string::npos)
{
auto stop_index = input.find(stop,start_index start.size());
if (stop_index != std::string::npos)
{
return {input.begin() start_index start.size(), input.begin() stop_index};
}
}
// return empty string
return {};
}
int main(int argc, char ** argv)
{
int uart0_filestream = -1;
int uart2_filestream = -1;
unsigned char rx_buffer[1024];
memset(amp;rx_buffer[0], 0, 1023);
unsigned char tx_buffer[1024];
memset(amp;tx_buffer[0], 0, 1023);
std::stringstream ss;
if(uart0_filestream == -1)
{
uart0_filestream = open("/dev/ttyS0", O_RDWR | O_NOCTTY | O_NDELAY);
//uart0_filestream = open("/dev/ttyS0", O_NOCTTY );
if(uart0_filestream == -1)
{
std::cout << "UARTListener::Start Unable to open UART" << std::endl;
}
else
{
struct termios options;
tcgetattr(uart0_filestream, amp;options);
options.c_cflag = B115200 | CS8 | CLOCAL | CREAD; //<Set baud rate
options.c_iflag = IGNPAR;
options.c_oflag = 0;
options.c_lflag = 0;
//options.c_line = 'n';
//options.c_cc[VEOL] = 0;
tcflush(uart0_filestream, TCIFLUSH);
tcsetattr(uart0_filestream, TCSANOW, amp;options);
}
}
while(true)
{
memset(amp;rx_buffer[0], 0, 1024);
int rx_length = read(uart0_filestream, (void*) rx_buffer, 1023);
if(rx_length > 0)
{
rx_buffer[rx_length] = '';
//std::string txt = std::string((char*) rx_buffer);
for (int i = 0; i < rx_length ; i )
{
ss << std::setfill('0') << std::setw(2)<< std::hex << (int)rx_buffer[i];
//ss << std::hex << (int)rx_buffer[i];
}
std::string startDEL = "06";
std::string stopDEL = "07";
std::string concat = std::accumulate(std::begin(ss.str()),std::end(ss.str()),std::string(""));
std::cout << "Pulled Data : " << ss.str() << std::endl;
std::cout << "String : " << sub_between(startDEL,stopDEL,concat) << std::endl;
//std::cout << txt << std::endl;
}
}
return 0;
}
—ВЫХОД—
Pulled Data : 42
String :
Pulled Data : 426561636f6e
String :
Pulled Data : 426561636f6e283229
String :
Pulled Data : 426561636f6e28322920466f756e
String :
Pulled Data : 426561636f6e28322920466f756e645b355d
String :
Segmentation fault
Комментарии:
1. Вы пытались поймать сбой в отладчике, чтобы узнать, где в вашем коде это происходит? Когда произойдет сбой, каковы значения всех задействованных переменных?
2. Неопределенное поведение,
stringstream::str()
возвращает строку по значению, поэтомуstd::accumulate(std::begin(ss.str()),std::end(ss.str())
при итерации по строкам у вас есть висячие ссылки.3. Кстати, вы хотите продолжить и добавить в поток строк
ss
на протяжении всего цикла чтения? Мне это кажется неправильным. Возможно, вам следовало бы определитьss
в ближайшей области, прямо передfor
циклом.4. Вы
accumulate
выглядите как очень окольный и неэффективный способ копированияss.str()
. Какой в этом смысл?5. когда вы публикуете код, написанный кем-то другим, вам лучше указать правильную атрибуцию. Не поймите меня неправильно, я не жалуюсь, потому что это из моего ответа, который просто облегчил обнаружение, но в целом я довольно придирчив в этом. Речь идет не только о предоставлении кредитов тем, кому причитаются кредиты, но и о полезном контексте. Например, можно пожаловаться, что вы передаете строки по значению, но на самом деле это не ваша ошибка, а моя (почему-то я забыл исправить это в ответе).