Qt serial port communication from an input file; weird behavior - c++

I am working on programming a device using Qt C++ 5.3.2.
There is a weird behavior, which I am not able to understand.
QByteArray file_data;
if (!file.atEnd()) {
file_data = file.readAll();
}
int i = 0, j = 0;
int index = 0;
QByteArray DataBuf;
j = 76;
while (true)
{
DataBuf[0] = (j + 3);
DataBuf[1] = 0x24;
DataBuf[2] = 0x24;
for (i = 0; i < j; ++i)
{
DataBuf[i + 3] = file_data[i + index];
DataBuf[1] = DataBuf[1] + file_data[i + index]; //Doubt here
}
response.clear();
serialPort->write(DataBuf, DataBuf[0]);
for (int i=0;i<6;i++) {
if (serialPort->readBufferSize()>=2) {
break;
}
wait(1); //user defined function, is same as msleep(5)
}
qa = response.toLocal8Bit();
if (qa.toHex() != "00cc") return;
index += 76;
if (j == len) break;
if (len > 76) len -= 76;
if (len <= 76) j = len;
}
This is the part of code which I am working on. The line mentioned as " Doubt here" does not work as expected.
When I run this program the value at Databuf[1] does not match the sum of the total 76 bytes of data.
The data written in Databuf[2] to Databuf[78] is totally correct, but the addition is not.
But when I change the line from DataBuf[1] = DataBuf[1] + file_data[i + index]; to DataBuf[1] = DataBuf[1] + DataBuf[i + 3]; it works properly.
What is happening here? Can anyone help please.

Related

Making a function use std::span instead of the old way

I just learned that I could use VS 2019 with C++ 20 and I'm trying to make use of it. I'm trying to make the following function use std::span, because that way data_size and key_size would be redundant.
Everything is alright except *data and data++. What is it supposed to be?
int rc4(rc4_context* context, const std::uint8_t* data, const std::size_t data_size, const std::uint8_t* key, const std::size_t key_size, std::uint8_t* output)
{
std::uint32_t i, j;
// Check parameters
if (!context || !key)
return ERROR_INVALID_PARAMETER;
// Clear context
context->i = 0;
context->j = 0;
// Initialize the S array with identity permutation
for (i = 0; i < 256; i++)
{
context->s[i] = static_cast<std::uint8_t>(i);
}
// S is then processed for 256 iterations
for (i = 0, j = 0; i < 256; i++)
{
// Randomize the permutations using the supplied key
j = (j + context->s[i] + key[i % key_size]) % 256;
// Swap the values of S[i] and S[j]
const auto temp = context->s[i];
context->s[i] = context->s[j];
context->s[j] = temp;
}
// Restore context
i = context->i;
j = context->j;
auto* s = context->s;
// Encryption loop
for (size_t x = 0; x < data_size; ++x)
{
// Adjust indices
i = (i + 1) % 256;
j = (j + s[i]) % 256;
// Swap the values of S[i] and S[j]
const auto temp = s[i];
s[i] = s[j];
s[j] = temp;
// Valid input and output?
if (data && output)
{
// XOR the input data with the RC4 stream
*output = *data ^ s[(s[i] + s[j]) % 256];
// Increment data pointers
data++;
output++;
}
}
// Save context
context->i = i;
context->j = j;
return NO_ERROR;
}
My attempt
int rc4(rc4_context* context, const std::span<uint8_t*> data, const std::span<std::uint8_t*> key, std::uint8_t* output)
{
// INITIALIZATION
std::uint32_t i, j;
// Check parameters
if (!context || !key.empty())
return ERROR_INVALID_PARAMETER;
// Clear context
context->i = 0;
context->j = 0;
// Initialize the S array with identity permutation
for (i = 0; i < 256; i++)
{
context->s[i] = static_cast<std::uint8_t>(i);
}
// S is then processed for 256 iterations
for (i = 0, j = 0; i < 256; i++)
{
// Randomize the permutations using the supplied key
j = (j + context->s[i] + key[i % key.size()]) % 256;
// Swap the values of S[i] and S[j]
const auto temp = context->s[i];
context->s[i] = context->s[j];
context->s[j] = temp;
}
// MAIN LOGIC PART
// Restore context
i = context->i;
j = context->j;
auto* s = context->s;
// Encryption loop
for (size_t x = 0; x < data.size(); ++x)
{
// Adjust indices
i = (i + 1) % 256;
j = (j + s[i]) % 256;
// Swap the values of S[i] and S[j]
const auto temp = s[i];
s[i] = s[j];
s[j] = temp;
// Valid input and output?
if (data.empty() && output)
{
// XOR the input data with the RC4 stream
*output = *data ^ s[(s[i] + s[j]) % 256];
// Increment data pointers
data++;
output++;
}
}
// Save context
context->i = i;
context->j = j;
return NO_ERROR;
}
First, the pair of parameters (const std::uint8_t* data, const std::size_t data_size) can be replaced by std::span<uint8_t>, not std::span<uint8_t*>.
Second, you don't need to bother incrementing data since you can rewrite this to be a range-based for loop:
for (uint8_t elem : data) {
// Adjust indices
i = (i + 1) % 256;
j = (j + s[i]) % 256;
// Swap the values of S[i] and S[j]
std::swap(s[i], s[j]);
// Valid output?
if (output) {
// XOR the input data with the RC4 stream
*output++ = elem ^ s[(s[i] + s[j]) % 256];
}
}

returning str vs. str.substr(0,str.size()) gives me different outputs in leetcode

I just solved https://leetcode.com/problems/push-dominoes/.
My code is
class Solution {
public:
string pushDominoes(string dominoes) {
string res(dominoes.size(), ' ');
dominoes = 'L' + dominoes + 'R';
int l = 0;
for(int r = 1; r < dominoes.size(); r++)
{
if(dominoes[r] != '.')
{
//check which case we have [L...R], [R....L] [L.....L] [R...R]
if(l != 0) res[l-1] = dominoes[l];
if(r != dominoes.size() - 1) res[r-1] = dominoes[r];
if(dominoes[l] == dominoes[r])
{
for(int i = l; i <= r; i++)
if(i > 0) res[i-1] = dominoes[r];
}
else if(dominoes[l] == 'L' && dominoes[r] == 'R')
for(int i = l+1; i < r; i++) res[i-1] = '.';
else if(dominoes[l] == 'R' && dominoes[r] == 'L')
{
if((l+r)%2 == 0)
{
auto mid = (l+r)/2;
res[mid-1] = '.';
for(int i = l+1; i < mid; i++) res[i-1] = 'R';
for(int i = mid+1; i < r; i++) res[i-1] = 'L';
}
else
{
auto mid = (l+r)/2;
for(int i = l+1; i <= mid; i++) res[i-1] = 'R';
for(int i = mid+1; i < r; i++) res[i-1] = 'L';
}
}
l = r;
}
}
return res;
// return res.substr(0, res.size());
}
};
int main( )
{
Solution soln;
cout << soln.pushDominoes(".L.R.") << endl;
}
For one of the test cases, where the input is ".L.R." leetcode states that my output is "LL.RRRLLRRLL.." when I use return res. The answer is supposed to be "LL.RR". But I printed out res and it's indeed "LL.RR" and size 5.
If I change my code to return return res.substr(0, res.size()) instead of return res, I get the correct solution. I'm perplexed as to why this is occuring when these 2 return statements should be identical?
I also ported the code over and compiled it on my computer, and I get the correct solution. This makes me wonder if there's some differences in how my code is handled between different C++ compilers, or if Leetcode might have some issues for this particular problem. Any advice?
string res(dominoes.size(), ' ');
Sets the size of res to that of dominoes and this size is never changed. res can never be larger than dominoes. With input of ".L.R.", dominoes's length is 5 . res is length 5.
dominoes = 'L' + dominoes + 'R';
Changes the size of dominoes to 7.
for (int r = 1; r < dominoes.size(); r++)
iterates r from 1 to 6.
Aside: When ever I see a <= in a for loop I stop for a longer look. It's wrong far more often than it is right.
In this case it seems to be only sort of wrong, allowing
for (int i = l; i <= r; i++)
if (i > 0) res[i - 1] = dominoes[r];
to iterate i from l to r. Since r can be 6, i can be 6. That means
if (6 > 0) res[6 - 1] = dominoes[6];
is possible. This resolves to
res[5] = dominoes[6];
and res[5] is not valid. Writing there invokes undefined behaviour, and in this case it appears to overwrite the null terminator of the c-style string backing the string.
Another aside: Avoid using l as a variable name. It looks too much like 1 and leads to bugs or misreading of the code.
To fix, you could expand the logic of if (i > 0) into if (i > 0 && i-1 < res.size()) to filter out this problem, but you're better off reworking or replacing the algorithm so that you never find yourself in this situation.

Heap Corruption detected: after Normal block(#176)

So I got this introduction to Programming assignment, I have to write a program that find the nth member of the following sequence 1, 121, 1213121, 121312141213121.. and so on. Basically, the first member is 1, and every next one is made of [the previous member] [n] [the previous member]. N < 10. So I got this problem that I do not understand, tried searching for it in the internet but didn't get anything that can help me.
#include "stdafx.h"
#include <iostream>
using namespace std;
int size(int n, int realsize);
int main()
{
int n;
cin >> n;
if (n == 1) {
cout << "1";
return 0;
}
int helper = 0;
char c = '2';
char* look;
char* say;
say = new char[size(n, 1) + 1]();
look = new char[size(n - 1, 1) + 1]();
look[0] = '1';
while (helper < n) {
for (int i = 0; i < size(helper + 1, 1); i++) {
say[i] = look[i];
}
say[size(helper + 1, 1)] = c;
for (int i = size(helper + 1, 1) + 1; i < size(helper + 1, 1) * 2 + 1; i++) {
say[i] = look[i - (size(helper + 1, 1) + 1)];
}
for (int i = 0; i < size(helper + 1, 1) * 2 + 1; i++) {
look[i] = say[i];
}
helper += 1;
}
cout << say;
delete[] say;
delete[] look;
return 0;
}
int size(int n, int realsize)
{
if (n == 1)
return realsize;
else
return size(n - 1, realsize * 2 + 1);
}
You are overwriting the capacity of your look variable. It ends out being written with the entire contents of say, so it needs to have that same size as well.
While I don't condone the below code as good code, it has minimal adjustments from your own implementation and should give a more solid base to continue towards a working outcome. I tested it with the first couple of numbers, but that's no guarantee it is perfect.
#include <iostream>
using namespace std;
int size(int n, int realsize);
int main()
{
int n;
cin >> n;
if (n == 1)
{
cout << "1";
return 0;
}
int helper = 0;
char c = '2';
char * look;
char * say;
say = new char[size(n, 1) + 1]; // Ditch the () call, which is confusing.
look = new char[size(n, 1) + 1]; // Make the same size as "say"
look[0] = '1';
while (helper < n - 1) // You're overrunning this loop I think, so I did it to n - 1.
{
for (int i = 0; i < size(helper + 1, 1); i++)
{
say[i] = look[i];
}
say[size(helper + 1, 1)] = c + helper; // You were adding '2' every time, so this will add 2, 3, 4, etc incrementally.
for (int i = size(helper + 1, 1) + 1; i < size(helper + 1, 1) * 2 + 1; i++)
{
say[i] = look[i - (size(helper + 1, 1) + 1)];
}
for (int i = 0; i < size(helper + 1, 1) * 2 + 1; i++)
{
look[i] = say[i];
}
helper += 1;
}
say[size(n, 1)] = '\0'; // Null-terminate "say" before printing it out.
cout << say;
delete[] say;
delete[] look;
return 0;
}
int size(int n, int realsize)
{
if (n == 1)
return realsize;
else
return size(n - 1, realsize * 2 + 1);
}

Websocket Server in C++ Error on sending message

I've been developing a C++ websocket server and it's working pretty good, except for one error that I don't understand.
The thing is that I can receive data and perform actions claimed by web browsers, but supposing that the server needs to send back some info, the first time it's sent succesfully, but when I repeat the same request (or another one which needs information back to browser), my server tries to send it (apparently successfully), then by itself sends it again (I don't know why) and then the connection is closed.
here's my code for sending messages:
int CSocketNode::SendMsg(const char opr, const char* cad,int length){
if (socket_conn == INVALID_SOCKET)
return -1;
int pos = 0;
int result = 0;
memset(Buffer_out, 0, BUFFER_SIZE);
if(!webSocket){
//Build header
Buffer_out[pos] = 57; //12345 % 256;
Buffer_out[pos + 1] = 48; //12345 / 256;
length++;
if((length / 256) >= 256){
int divi = length / 256;
Buffer_out[pos + 2] = length % 256;
Buffer_out[pos + 3] = divi % 256;
Buffer_out[pos + 4] = divi / 256;
} else {
Buffer_out[pos + 2] = length % 256;
Buffer_out[pos + 3] = 0;
Buffer_out[pos + 4] = length / 256;
}
Buffer_out[pos + 5] = opr;
pos = 5;
memcpy(Buffer_out + pos + 1, cad, length);
} else {
Buffer_out[pos++] = 0x81;
length++;
if(length <= 125){
Buffer_out[pos++] = length;
} else if(length <= 65535) {
Buffer_out[pos++] = 126;
Buffer_out[pos++] = (length >> 8) & 0xff;
Buffer_out[pos++] = length & 0xff;
} else {
Buffer_out[pos++] = 127;
memset(Buffer_out + pos, 0, 8);
for (int i = 7; i >= 0; i--){
Buffer_out[pos++] = (length >> 8*i) & 0xff;
}
}
Buffer_out[pos++] = opr;
memcpy(Buffer_out + pos, cad, length);
}
printf("0: %d, 1: %d, 2: %d, 3: %d, 4: %d. Pos = %d\n", Buffer_out[0], Buffer_out[1], Buffer_out[2], Buffer_out[3], Buffer_out[4], pos);
printf("%s\n", Buffer_out + pos);
result = SendBytes(Buffer_out, length + pos);
return result;
}
int CSocketNode::SendBytes(char *cad, int length){
//Send it
int err = send(socket_conn, cad, length,0);
if (err == SOCKET_ERROR ){
Error("SendBytes Error");
return -1;
}
return 0;
}
The first part of the IF sentence is for my non web browser clients, which works perfectly.
no matter what size the data frame is, less than 125 or less than 65535, the result is the same.
maybe I'm missing something. Maybe I havve to add and a FIN message at the wnd of the message. but according to the WebSocket Manual, it is the first bit of the message which indicates if it's the or not of multiple messages.
If you can tell me what it is I will be very thankful.
Solved it by myself. For some reason that I cannot guess, the memcpy makes the socket pipe not work correctly.
So I used a for loop to copy the message to the buffer. And solved.

What's wrong with this parallel algorithm?

I'm trying to write parallel algorithm in openCL for L-system Pythagoras Tree :
var:A,B;
const: (,);
axiom:A;
rules:(B->BB),(A->B[A]A)
But i can't get over 9th iteration. 10th iteration returns disordered string. Here is my kernel:
#pragma OPENCL EXTENSION cl_khr_global_int32_base_atomics : enable
#pragma OPENCL EXTENSION cl_khr_local_int32_base_atomics : enable
#pragma OPENCL EXTENSION cl_amd_printf : enable
__kernel void l_system(int string_lenght){}
__kernel void l_system_interation(int string_lenght, __global char *sentence, __local char *string, __global int * local_char_num)
{
int local_x = (int)get_local_id(0);
int local_size = (int)get_local_size(0);
int x = (int)get_global_id(0);
int size = (int)get_global_size(0);
int group = (int)get_group_id(0);
int local_mem_index;
if(x < string_lenght){
//local mem index - offset for next group, copy char to local
local_mem_index = local_x * 5;
string[local_mem_index] = sentence[x];
if(local_x == 0){
//reset counter
atomic_xchg(&local_char_num[group], 0);
//atomic_add(&local_char_num[0], group);
}
}
barrier(CLK_LOCAL_MEM_FENCE);
barrier(CLK_GLOBAL_MEM_FENCE);
if(x < string_lenght){
if(string[local_mem_index] == 'A'){
atomic_add(&local_char_num[group], 5);
string[local_mem_index] = 'B';
string[local_mem_index + 1] = '(';
string[local_mem_index + 2] = 'A';
string[local_mem_index + 3] = ')';
string[local_mem_index + 4] = 'A';
}
else if(string[local_mem_index] == 'B'){
atomic_add(&local_char_num[group], 2);
string[local_mem_index + 1] = 'B';
//reset 3rd char of local_mem
string[local_mem_index + 2] = '0';
}
else{
atomic_add(&local_char_num[group], 1);
//reset 3rd char of local_mem
string[local_mem_index + 2] = '0';
string[local_mem_index + 2] = '0';
}
}
barrier(CLK_LOCAL_MEM_FENCE);
barrier(CLK_GLOBAL_MEM_FENCE);
//1 compute unit for every char from src
if(x < string_lenght){
//local first compute unit writes to result whole group string
if(local_x == 0){
int j = 0;
//find offset for write to result string
if(x != 0){
for(int l = 1;l <= group; l++)
{
j += atomic_xchg(&local_char_num[group-l], local_char_num[group-l]);
//if(l == 0)
}
atomic_xchg(&local_char_num[99+group], local_char_num[group]);
}
for(int i = 0; i < local_size; i++){
//only valid chars
if(string_lenght > (x+i)){
local_mem_index = i * 5;
//B rule, copy (,)
if(string[local_mem_index+2] != 'A'){
sentence[j++] = string[local_mem_index];
if(string[local_mem_index] == 'B'){
sentence[j++] = string[local_mem_index+1];
}
continue;//B,(,); next index;
}
else{ // A rule
sentence[j++] = string[local_mem_index];
sentence[j++] = string[local_mem_index+1];
sentence[j++] = string[local_mem_index+2];
sentence[j++] = string[local_mem_index+3];
sentence[j++] = string[local_mem_index+4];
}//if 'A'
//sentence[j] = 0;
}//if x+i
}//for
}// lx == 0
}
barrier(CLK_GLOBAL_MEM_FENCE);
}
I think, that something overflow anywhere, but can't find where... Maybe there is something wrong with my code in main:
cl_int letter_count = 0;
cl_int next_letter_count = 1;
for (int i = 0; i < iter_count; i++)
{
//printf("%s\n", sentence_init);
letter_count = next_letter_count;
next_letter_count = STRING_LENGTH_PAR((i + 1));
printf("in count: %d out count: %d\n", letter_count, next_letter_count);
CheckOpenCLError(clSetKernelArg(kernel_iteration, 0, sizeof(cl_int), &letter_count), "clSetKernelArg: letter_count");
CheckOpenCLError(clSetKernelArg(kernel_iteration, 2, sizeof(cl_char)* (local * RULE_SIZE + 1), NULL), "clSetKernelArg: tmp_string");
CheckOpenCLError(clEnqueueNDRangeKernel(queue, kernel_iteration, 1, NULL, &global, &local, 0, NULL, &kernel_iteration_event), "clEnqueueNDRangeKernel: kernel_iteration");
CheckOpenCLError(clFinish(queue), "clFinish");
kernel_computing_time += getEventTime(kernel_iteration_event);
}
CheckOpenCLError(clEnqueueReadBuffer(queue, sentence_dev, CL_TRUE, 0, sizeof(cl_char)* (next_letter_count), sentence_result, 0, NULL, &result_iteration_event), "clEnqueueReadBuffer: result_iteration_event");
cl_int *p = (cl_int*)malloc(sizeof(cl_int)*(STRING_LENGTH_PAR(iter_count)));
CheckOpenCLError(clEnqueueReadBuffer(queue, p_dev, CL_TRUE, 0, sizeof(cl_int)* (STRING_LENGTH_PAR(iter_count)), p, 0, NULL, &result_iteration_event), "clEnqueueReadBuffer: result_iteration_event");