C++ on Arduino: Struct constructor calls own Destructor and destroys itself - struct

I want to create a class to manage data using serial communications, I re-wrote and was able to repeat the same issue.
Issue
I have a structure of data that can allocate memory on the constructor and de-allocate on the destructor. Before the next call of dataHelper.parse(), the newly created data struct instance in nextData will be passed as a pointer to a callback function to use the data. This will not work though because the destructor of the newly created data gets called right after the constructor and nextData becomes a dangling pointer. This behavior is confusing and I cannot figure out the issue here. Thanks for any help.
Struct
struct Data
{
uint8_t len;
uint16_t dataId;
uint8_t *dat;
Data()
:len(0), dataId(0), dat(nullptr)
{
}
Data(uint16_t newDataId, void *newData, uint8_t length)
:len(length), dataId(newDataId), dat(nullptr)
{
Serial.println("Called Constructor");
dat = (uint8_t *)malloc(length);
if (dat == nullptr)
{
len = 0;
return;
}
memmove(dat, newData, length);
}
~Data()
{
Serial.println("Called destructor");
free(dat);
}
};
...
Class to help with Data
...
class DataHelper
{
private:
Data* nextData = nullptr;
uint16_t exampleGetID(uint8_t bytes[])
{
return 0x000A;
}
public:
DataHelper()
{
}
void parse()
{
// Check Size IDB2 IDB1 DB1-2 DB1
// | | | | | |
uint8_t raw[TEST_SIZE] = { 0x01, 0x01, 0x00, 0x0A, 'F', 'F'}; //Example raw data. Last two are characters representing data in hex.
if (raw[0] != 0x01)
{
return; //Bad data
}
uint8_t sizeInBytes = raw[1]; //<- Size of data in bytes, not how many characters of hex.
uint16_t dataId = exampleGetID(&raw[2]); //<- Turning two bytes to one uint16_t.
if (nextData != nullptr)
{
Serial.println("Destroying old unwanted data...");
nextData->~Data(); //<- Destroying old data.
}
Serial.println("Allocating memory for new empty data...");
nextData = (Data *)malloc(sizeof(Data)); //<- Allocating space for next new data.
Serial.println("Assigning new data...");
// Data size as chars, 1 byte is 2 Hex-chars
// |
*nextData = Data(dataId, &raw[4], sizeInBytes * 2); //<- Calls destructor at end of constructor?
Serial.println("Assigned new data.\n\n\n");
}
};
...
DB1 & DB1-2 is a byte represented in hex format which is to be saved into the new instance of nextData as a hex c-string, with no null terminator.
Output
-> Allocating memory for new empty data...
-> Assigning new data...
-> Called Constructor
-> Called destructor
-> Assigned new data.
->
->
->
-> Destroying old unwanted data...
-> Called destructor
-> Allocating memory for new empty data...
-> Assigning new data...
-> Called Constructor
-> Called destructor <- Why is this called right after constructor?
-> Assigned new data.

Related

Assign string object via std::istream in C++

I'd like to assign std::string *ptr via std::string::operator >> in c++.
I have a class below.
class A{
public:
A(){
ptr = new std::string();
}
A(std::string& file){
ptr = new std::string();
std::ifstream ifs(file);
std::stringstream ss;
ss << ifs.rdbuf();
*ptr=ss.str();
ifs.close();
}
~A(){
delete ptr;
}
void output(std::ostream& stream) const{
stream << *ptr;
}
void input(std::istream& stream) const{
stream >> *ptr;
}
private:
std::string *ptr;
};
int main(void){
std::string file="./file";
std::string dfile="./dump";
std::ofstream ofs(file);
A a(file);
a.output(ofs);
std::ifstream ifs(dfile);
A b();
b.input(ifs);
return 0;
}
Assume "./file" contains a text below:
The first form (1) returns a string object with a copy of the current contents of the stream.
The second form (2) sets str as the contents of the stream, discarding any previous contents.
I confirmed the content of "./dump" is same as "./file".
However, the string object I get(b's *ptr) from b.input("./dump") is just a small string delimitered at space, which is just
The
How can I obtain whole text?
Thanks
stream >> *ptr; reads a single whitespace-delimited word.
To read a whole line, use std::getline:
std::getline(stream, *ptr);
Also note that there's no point in allocating your string dynamically (in fact, in its current state your class will leak memory and cause double-deletes if copied, as pointed out by #aschepler in the comments). The member could be a plain std::string str;.

Qt4: how to send QString inside a struct via QSharedMemory

I have a struct
struct control_data{
int column_number;
QString cell;
};
I need to send it to another thread with the help of QShareMemory. I read that you can't do this because QString contains pointers inside. Any other ways?
You have to serialize your struct to a Byte array. You can always convert your QString to a const char* like this:
myString.toStdString().c_str();
But serializing a QString should work.
The first step is to serialize your struct to a QDatastream using Qt, example here.
Then once your struct can be read and written you can pass it to a shared memory.
A complete example of using QSharedMemory can be found here.
Here is the relevant code:
// First, test whether a shared memory segment is already attached to the process.
// If so, detach it
if (sharedMem.isAttached())
{
sharedMem.detach();
}
...
QBuffer buffer;
buffer.open( QBuffer::ReadWrite );
QDataStream out( &buffer );
out << youStruct;
int size = buffer.size(); // size of int + size of QString in bytes
if ( !sharedMem.create( size ) ) {
return;
}
// Write into the shared memory
sharedMem.lock();
char *to = (char*)sharedMem.data();
const char *from = buffer.data().data();
memcpy( to, from, qMin( sharedMem.size(), size ) );
sharedMem.unlock();

memory corruption while executing my code

# include "stdafx.h"
# include <iostream>
#include <ctype.h>
using namespace std;
class a
{
protected:
int d;
public:
virtual void assign(int A) = 0;
int get();
};
class b : a
{
char* n;
public:
b()
{
n=NULL;
}
virtual ~b()
{
delete n;
}
void assign(int A)
{
d=A;
}
void assignchar(char *c)
{
n=c;
}
int get()
{
return d;
}
char* getchart()
{
return n;
}
};
class c : b
{
b *pB;
int e;
public:
c()
{
pB=new b();
}
~c()
{
delete pB;
}
void assign(int A)
{
e=A;
pB->assign(A);
}
int get()
{
return e;
}
b* getp()
{
return pB;
}
};
int _tmain(int argc, _TCHAR* argv[])
{
c *pC=new c();
pC->assign(10);
b *p=pC->getp();
p->assignchar("a");
char *abc=p->getchart();
delete pC;
cout<<*abc<<endl;
getchar();
}
i'm a noob at c++ and was experimenting when i got to this point. I don't understand why i keep getting a memory corruption message from VS2010. I am trying to replicate a problem which is at a higher level by breaking it down into smaller bits, any help would be appreciated.
From a cursory glance, you are passing a static char array to AssignChar that cannot be deleted (ie when you type "A" into your code, its a special block of memory the compiler allocates for you).
You need to understand what assignment of a char* does (or any pointer to type). When you call n=c you are just assigning the pointer, the memory that pointer points to remains where it is. So, unless this is exactly what you meant to do, you will have 2 pointers pointing to the same block of memory.. and you need to decide which to delete (you can't delete it twice, that'd be bad).
My advice here is to start using C++, so no more char* types, use std::string instead. Using char* is C programming. Note that if you did use a std::string, and passed one to assignChars, it would copy as you expected (and there is no need to free std::string objects in your destructor, they handle all that for you).
The problem occurs when you're trying to delete pC.
When ~c() destructor calls ~b() destructor - you're trying to delete n;.
The problem is that after assignchar(), n points to a string literal which was given to it as an argument ("a").
That string is not dynamically allocated, and should not be freed, meaning you should either remove the 'delete n;' line, or give a dynamically-allocated string to assignchar() as an argument.

QThread crashes the program?

I implement QThread like this, but get program crashed when it runs.
I've searched and seen posts saying it is not the correct way to use QThread.
But I cannot find any reason for the crashes of my program, what I do is only
triggering 'on_Create_triggered()' and I guarantee the mutex is locked and unlocked properly.
I have tested the program for two days(testing only by 'std::cerr << ...;' prints results), but still cannot find reason. What I guess is that the thread may wait for the lock too long and cause program to crash. (not sounds reasonable...) :)
My codes:
Background.h
class Background : public QThread
{
Q_OBJECT
public:
Background(int& val,DEVMAP& map, QQueue<LogInfoItem*>& queue, QList<DEV*>& devlist, QList<IconLabel*>& icllist,QMutex& m)
:val_i(val),DevMap(map), LogInfoQueue(queue), DevInfoList(devlist), IconLabelList(icllist),mutex(m)
{}
~Background();
protected:
void run(void);
private:
DEVMAP& DevMap;
QQueue<LogInfoItem*>&LogInfoQueue;
QList<DEV*>& DevInfoList;
QList<IconLabel*>& IconLabelList;
int& val_i;
QMutex& mutex;
void rcv();
};
Background.cpp
#include "background.h"
Background::~Background()
{
LogFile->close();
}
void Background::run(void)
{
initFile();
while(1)
{
msleep(5);
rcv();
}
}
void Background::rcv()
{
mutex.lock();
...
...//access DevMap, LogInfoQueue, DevInfoList, IconLabelList and val_i;
...
mutex.unlock();
}
MainWindow:(MainWindow has Background* back as property)
void MainWindow::initThread()
{
back = new Background(val_i, dev_map, logDisplayQueue, devInfoList, iconLabelList, mutex);
back->start();
}
void MainWindow::on_Create_triggered()
{
mutex.lock();
...
...//access DevMap, LogInfoQueue, DevInfoList, IconLabelList and val_i;
...
mutex.unlock();
}
I have found the reason, which is more subtle.
(I use some codes written by others but believe it is not broken, what I got totally wrong! :) )
The broken codes:
#define DATABUFLEN 96
typedef struct Para//totally 100bytes
{
UINT8 type;
UINT8 len;
UINT8 inType;
UINT8 inLen;
UINT8 value[DATABUFLEN];//96 bytes here
}ERRORTLV;
class BitState
{
public:
UINT8 dataBuf[DATABUFLEN];
......
};
And the function using it:
bool BitState::rcvData() //the function crosses bound of array
{
UINT8 data[12] =
{
0x72, 0x0A, 0x97, 0x08,
0x06, 0x0A, 0x0C, 0x0F,
0x1E, 0x2A, 0x50, 0x5F,
}; //only 12 bytes
UINT32 dataLen = 110;
memcpy(this->dataBuf, data, dataLen); //copy 110 bytes to dataBuf //but no error or warning from compiler, and no runtime error indicates the cross
}
bool BitState::parseData(BitLog* bitLog)//pass pointer of dataBuf to para_tmp, but only use 0x08 + 4 = 12 bytes of dataBuf
{
Para* para_tmp;
if(*(this->dataBuf) == 0x77)
{
para_tmp = (ERRORTLV*)this->dataBuf;
}
if(para_tmp->type != 0x72 || para_tmp->inType != 0x97 || (para_tmp->len - para_tmp->inLen) != 2) // inLen == 0x08
{
return false;
}
else
{
//parse dataBuf according to Para's structure
this->bitState.reset();
for(int i = 0; i < para_tmp->inLen; i++) // inLen == 0x08 only !!!
{
this->bitState[para_tmp->value[i]-6] = 1;
}
if(this->bitState.none())
this->setState(NORMAL);
else
this->setState(FAULT);
QString currentTime = (QDateTime::currentDateTime()).toString("yyyy.MM.dd hh:mm:ss.zzz");
string sysTime = string((const char *)currentTime.toLocal8Bit());
this->setCurTime(sysTime);
this->addLog(sysTime, bitLog);
}
return true;
}
bool BitState::addLog(std::string sysTime, BitLog* bitLog)// this function is right
{
bitLog->basicInfo = this->basicInfo;//not in data Buf, already allocated and initialized, (right)
bitLog->bitState = this->bitState; //state is set by setState(..)
bitLog->rcvTime = sysTime; //time
return true;
}
Generally speaking, the program allocates 96 bytes to a byte array, but use 'memcpy(...)' to copy 110 bytes to the array, later uses only 12 bytes of the array.
All kinds of crashes appear, which are confusing and frustrating...:( :( :(

Message queue msgsnd mtext field

When using msgsnd the structure mentioned in man page is
struct mymsg {
long mtype; /* message type */
char mtext[1]; /* body of message */
};
But if you use it like
func(char *array, int sizeofarray)
{
struct mymsg {
long mtype; /* message type */
char *ptr; /* body of message */
};
msgq.mtype = 1;
msgq.ptr = array;
msgsnd(msqid, &msgq, sizeofarray, 0);
}
Assign ptr to some local array[200] (array could be got as a parameter in function), the message received on the other side is junk. Why is this?
It's junk because the structure you have specified is not of the form that msgsnd wants. It expects the data to be copied to immediately follow the mtype value in memory, not be in an array somewhere else.
If you want to send an array of length 200, you need to do something like:
struct mymsg {
long mtype;
char mtext[200];
} foo;
foo.mtype = 1;
memcpy(foo.mtext, array, 200);
msgsnd(msqid, &foo, 200, 0);
Even if this wasn't wrong for the reasons caf points out, let's say you did something like:
func(char *array)
{
struct mymsg
{
long mtype; /* message type */
char *ptr; /* body of message */
};
msgq.mtype = 1;
msgq.ptr = array;
msgsnd(msqid, &msgq, sizeof(ptr), 0);
}
If a different process is reading the queue, what would ptr mean to it? What would it point to, if anything, in a different address space?

Resources