I'm having trouble passing data by reference to a given method - when the method access the data, it's corrupted, but I'm sure that when the method is called it's not (by debuggin). Here is something like the code:
//Calling code
const void* tempPointer = array.mid(readerPos,RE8K_ICDEF_HARMONICS_SIZE).constData();
const re8k_ics_harmonics* const newStruct = static_cast< const re8k_ics_harmonics* >(tempPointer);
DSInstance().updateHarmonics(*newStruct);
//method
void DataStream::updateHarmonics(const re8k_ics_harmonics &infoHarmonics, ...)
{
//Use infoHarmonics
}
So if I use the debugger and go put a breakpoint in the "calling code" in the last line and watch what is in newStruct, I see that the data is perfect as it should be. Than the method is called and I put a new breakpoint (or go "next line") till enter the first line inside updateHarmonics, and when I see the content of infoHarmonics, I see part of the data corrupted and part of it is there.
Why is the code becoming corrupted? What should I do? :x
Additional info:
array is a Qt's QByteArray
readerPos is a int that iterates over the QByteArray from the point data should be read
constData() returns a const char*
Thanks,
Momergil
QByteArray QByteArray::mid (int pos, int len = -1 ) const
This function returns object by value, so in the line
const void* tempPointer = array.mid(readerPos,
RE8K_ICDEF_HARMONICS_SIZE).constData();
you are taking a pointer to temporary data. This pointer is not valid just in the next line. You should create object on the heap or use stack allocated instance, e.g:
QByteArray midQ = array.mid(readerPos, RE8K_ICDEF_HARMONICS_SIZE);
const void* tempPointer = midQ.constData(); // pointer valid as long
// as midQ breaths
const re8k_ics_harmonics* const newStruct =
static_cast< const re8k_ics_harmonics* >(tempPointer);
DSInstance().updateHarmonics(*newStruct);
Related
I am wanting to read back data stored in a buffer. I have a function that takes a pointer to an unsigned char array as a parameter. I wanted this parameter to be populated (point to) the address of the buffer I wish to obtain.
Inside the function I can see while debugging that the parameter passed in is being updated correctly (Mock class), however once I return from this function to the calling method (Connection class), all the data is lost.
Please can anyone help me understand why this is?
Thanks in Advance
Unit Test
/// Unit test fails as expected data is not in the buffer
TEST(MemoryTest, TestWriteAndRead)
{
Connection* p_conneciton = new Connection();
/// Write
uint8_t txBuffer[_USB_PACKET_SIZE] = _CMD;
ASSERT_EQ(p_memory->Write(txBuffer), true);
/// Read
uint8_t* rxBuffer;
ASSERT_EQ(p_memory->Read((unsigned char*)&rxBuffer), true);
ASSERT_EQ(rxBuffer[0], 0xaa);
}
Connection Class
/// Information is lost here in _pu8_buffer
bool Connection::Read(uint8_t* _pu8_buffer)
{
int i_bytesRead = 0;
while(i_bytesRead != SIZE) {
i_bytesRead = read_timeout(_pu8_buffer, _PACKET_SIZE);
if ( i_bytesRead < _PACKET_SIZE) {
return false;
}
}
return true;
}
Mock Class
/// Information is copied correctly here from mpuc_data to data
int Mock:read_timeout(unsigned char* data, size_t length)
{
if (data == nullptr) {
return -1;
}
data = mpuc_data;
return 0;
}
You need to pass by reference parameters you want to modify. If you want to modify the value of a pointer, it's the pointer you need to pass by reference -that it is a reference itself (to something else) won't help.
Try
int Mock:read_timeout(unsigned char*& data, size_t length)
{
if (data == nullptr) {
return -1;
}
data = mpuc_data;
return 0;
}
this way, _pu8_buffer will actually point the same as mpuc_data after each call to read_timeout. You can do the same with the function Read.
In general, pay attention to levels of indirection. With
uint8_t* rxBuffer;
ASSERT_EQ(p_memory->Read((unsigned char*)&rxBuffer), true);
you're taking the address of a uint8_t*, obtaining a uint8_t**, pointer to a pointer. Then you cast it to unsigned char* -a simple, not double pointer! (and then implicitly to uint8_t* when it becomes a parameter) It can't end well... and it ends in trying to read an array of chars where the first 4 or 8 are in fact the bytes of your pointer, followed by other garbage.
Taking the address of a pointer is correct if you want to modify it, but then you need to expect a uint8_t** on the other side, and refer to it as *_pu8_buffer.
/// Information is lost here in _pu8_buffer
bool Connection::Read(uint8_t* _pu8_buffer)
{
int i_bytesRead = 0;
while(i_bytesRead != SIZE) {
i_bytesRead = read_timeout(_pu8_buffer, _PACKET_SIZE);
if ( i_bytesRead < _PACKET_SIZE) {
return false;
}
}
return true;
}
Calling this function gets you a copy of the pointer you passed to it. Meaning that if you change the location that the pointer is pointing to you only change the local copy.
You either change the way you set the data in read_timeout to:
*data = mpuc_data;
Or you pass a pointer to a pointer (uint8_t**) in Connection::Read and call read_timeout(&_pu8_buffer, _PACKET_SIZE);
Also, the way you currently have it &rxBuffer is not correct, it should be rxBuffer. Only pass the address if you change the signature to a uint8_t**.
Will the following code work? -
void doSomething(char* in)
{
strcpy(in,"mytext");
}
Here's how the function is being called:
doSomething(testIn);
OtherFn(testIn);
The char* in is used in other places in the code... and we are passing it by value to the function doSomething. I understand when we pass by value, a copy of the string stored in char* is copied within the function. So, when we do a strcpy, will it copy to the local copy or to the char* in that was passed in as an argument?
My understanding is we need to do: doSomething(char* &in). Is that right?
When you want to modify just the contents of what the pointer points to, use:
doSomething(char* in)
So, yes,
void doSomething(char* in)
{
strcpy(in,"mytext");
}
will work just fine as long as in points to enough memory to hold "mytest" and a terminating null character.
There are times when you want to modify where the pointer points to, for example, by allocating new memory. Then, you need to pass a reference to a pointer.
void doSomething(char*& in)
{
in = new char[200];
strcpy(in,"mytext");
}
and use it as:
char* s = NULL;
doSomething(s);
// Now s points to memory that was allocated in doSomething.
// Use s
// make sure to deallocate the memory.
delete [] s;
I am trying to program a qt widget application which deals with linked list of nodes, the node contains 3 char* data member and 2 int members and a "next" pointer of "node" type,
my issue is the char* members in nodes of the linked list are getting saved same as the third char* member, I tried using debugger and found out that
the length of all the 3 ints i.e. lentitl,lenpub,lenpub are initialized to same value, and all the 3 char* members are getting same value,
the node constructor is as follows
node::node(char* titl,char* auth,char* pub,int pri,int stockp)
{
int lentitl,lenauth,lenpub;
lenpub=strlen(pub);
lentitl=strlen(titl);
lenauth=strlen(auth);
title=new char[lentitl+1];
author=new char[lenauth+1];
publisher=new char[lenpub+1];
strcpy(title,titl);
strcpy(author,auth);
strcpy(publisher,pub);
price=pri;
stockposition=stockp;
next=NULL;
}
the node functions if called from another class function named "addbook",and addbook is called from mainwindow.cpp, the functions calls for addbook is as follows
void MainWindow::on_addbook_clicked()
{
char *titl,*auth,*pub;
int pri,stockp;
titl=ui->title->toPlainText().toLatin1().data();
auth=ui->author->toPlainText().toLatin1().data();
pub=ui->publisher->toPlainText().toLatin1().data();
pri=ui->price->toPlainText().toInt();
stockp=ui->stockposition->toPlainText().toInt();
p.addbook(titl,auth,pub,pri,stockp);
}
and the function call for node is as follows
void shop::addbook( char *titl, char *auth, char *pub, int pri, int stockp)
{
node *p=new node(titl,auth,pub,pri,stockp);
if(start==NULL)
{
start=p;
end=p;
}
else
{
p->next=start;
start=p;
}
}
the zip of whole project is here
and here is the link to the ouput
the screen shot of the output is
as you can see in the image,string entered at "publisher" textedit is getting set to all 3 char* of the node,
can anyone explain me why is this happening?
titl=ui->title->toPlainText().toLatin1().data();
This is probably the issue: toLatin1() returns a new QByteArray which owns its data. You assign the internal data pointer of that QByteArray to titl. However, the QByteArray is only a temporary variable and will get destroyed in the next line of code. When the QByteArray gets destroyed, it will free its data, which means your titl is now pointing to memory that was already freed - i.e. titl points to an invalid memory location.
Suggested solution alternatives:
Use QString instead of char* in your node class, much easier to deal with memory management issues that way
Make sure your QByteArray temporary lives as long as you need the data (until you strcpy the data):
QByteArray titl = ui->title->toPlainText().toLatin1();
QByteArray auth = ui->author->toPlainText().toLatin1();
QByteArray pub = ui->publisher->toPlainText().toLatin1();
pri=ui->price->toPlainText().toInt();
stockp=ui->stockposition->toPlainText().toInt();
p.addbook(titl.data(),auth.data(),pub.data(),pri,stockp);
I'm not expert of Qt but there is something that doesn't sound good to me in terms of C++. Mainly a function in your code is returning a "char * " pointer instead of a "const char*", I'm talking about these lines:
char *titl,*auth,*pub;
int pri,stockp;
titl=ui->title->toPlainText().toLatin1().data();
If the data was directly provided by the title class I expect to obtain a const char* pointer in order to do not be allowed to modify it. The only reason you can handle a char* ( or in other words a well known library is designed to return a non const pointer) is that there is a temporary object or a static buffer in the middle of the calls: toLatin1 or data.
Reading the docs of Qt: toLatin1 is returning a temporary object, a QByteArray.
QByteArray toLatin1 () const
for more information: http://qt-project.org/doc/qt-4.8/qstring.html
So simply modify each string request like:
QByteArray titlArray = ui->title->toPlainText().toLatin1();
titl=titlArray.data();
in that way each string will point to a still existing buffer when you are calling
p.addbook(titl,auth,pub,pri,stockp);
First of all, everything is happening in an if{} statement in a do{}while loop. I have a struct that contains some const char pointers. I'm trying to get info into a temp struct with new string values each iteration, then push this struct into a vector of said structs, so that when the function exits, the vector is populated with different struct objects.
do{
if()
{
sound_device_t newDevice; //<--- Why is this the same mem address each iteration?
//I thought it would be destroyed when it's scope was (the if block)
const char * newPath;
someFunction(&newPath); //puts a string into newPath
newDevice.firstString = newPath; //<-- This works.
QString otherPath(const char *);
//...some QString manipulation...//
newDevice.secondString = otherPath.toLocal8Bit().data(); //<--this doesn't
vector_of_structs -> push_back(newDevice);
}
}while (...)
I was under the impression that push_back copied the argument struct's values into its own version. Why is the QString giving me problems? I am using QString because it has some good string manipulation functions (i.e. insert and section), but I'll exchange it if I need to for something that works.
I have also tried putting the QString's data into a char * and then strcpy'ing it into the struct, but that has the same result. Every iteration rewrites newDevice.secondString.
QByteArray::data() is only valid so long as the ByteArray is unchanged. Destroying the temporary is changing.
In other words after the semi colon of the line newDevice.secondString = otherPath.toLocal8Bit().data(); the QByteArray returned by toLocal8Bit is destroyed and the stored array deleted.
There are a couple of issues with your code:
if statement without condition (!)
invalid construction: QString otherPath(const char *); You probably want an "otherPath" variable there similarly to "newPath".
You are mixing qt types with std containers. You should take a loo at QStringList.
Needless pointer usage: newDevice.secondString = otherPath.toLocal8Bit().data();
The last one is especially critical since you destroy otherPath before the next iteration. The solution is to use a deep copy in there.
I would write something like this:
do {
if(cond) {
sound_device_t newDevice;
const char * newPath;
someFunction(&newPath);
newDevice.firstString = newPath;
// Get other path
QString otherPath(otherPath);
//...some QString manipulation...
newDevice.secondQString = otherPath;
// or: strcpy( newDevice.secondString, otherPath.toLocal8Bit().data());
vector_of_structs->push_back(newDevice);
}
} while (...)
That being said, depending on what you are trying to do, QtMultiMedia might be better used overall for your sound device purpose. As long as dbus goes, there is also a QtDBus add-on module.
Thanks for all the help guys. I got the original code working with just one tweak:
newDevice.secondString = otherPath.toLocal8Bit().data();
should be changed to
newDevice.secondString = strdup(otherPath.toLocal8Bit().data());
This does the buffer allocation directly, as #ratchet freak was suggesting. strcpy() doesn't work because it still connects newDevice.secondString with the QByteArray, just like toLatin1().data() does.
I've been banging my head hard over this...I create a pointer in main(), which I pass on to another function. Inside that function, the pointer is used to create a new array (using the new operator), the array is filled, and the function ends.
If I then try to access elements in the new array in the caller, I get a segfault. Since the new operator was used, I expect the new array to be on the heap and thus not cleared by it going out of scope...I really don't get this. What am I overlooking? I also don't know precisely what to google for, so no luck there yet.
I can get it to work if I let the function return the pointer (instead of passing it), but I don't want to do that because eventually I'd like my function to create a few such newly created arrays. So what am I missing here?
Here is a minimal working example:
#include <iostream>
#include <stdio.h>
bool getData(double *myData)
{
myData = new double[2];
if (!myData)
return false;
myData[0] = +4.53;
myData[1] = -3.25;
return true;
}
int main()
{
double *myData = NULL;
if (!getData(myData))
fprintf(stderr, "Could not get data.\n");
std::cout << myData[0] << std::endl;
std::cout << myData[1] << std::endl;
delete [] myData;
}
Root Cause of the Crash:
When you pass a pointer to the function by value. An copy of the pointer gets passed to the function. Further You allocate memory to the copy of pointer passed through main, this pointer is not same as the one you access in main, it is an copy. The pointer myData in main was never allocated any memory, so eventually you are dereferencing a NULL pointer which results in a Undefined Behavior and an crash.
Suggested Solution 1:
Pass the pointer by Reference:
bool getData(double *&myData)
^
And you are good to go.This is the C++ way of doing it.
Another Solution:
You could also do:
bool getData(double **myData)
^
{
*myData = new double[2];
//so on
}
while calling it as:
getData(&myData);
^
A word of caution:
new does not return NULL in case of failure to allocate memory. It throws a std::bad_alloc exception. So you need to handle that exception or in case you want to check for null you should use the nothrow version of new.
The pointer argument to getData() is passed by value, not by reference. This means you're pushing the value (== the address the pointer points to) on the stack and call getData. Inside getData you overwrite this value with the return value from new[]. This value is no longer valid after returning from the function as it only existed on the stack.
Try to pass a reference or pointer to the pointer:
bool getData(double *&myData)
{
myData = new double[2];
if (!myData)
return false;
myData[0] = +4.53;
myData[1] = -3.25;
return true;
}
You have to pass a double** as myData, to initialize correctly your array. Currently, your getData function creates an array and stores its value in the copied parameter, so myData in main is not modified. Your must pass the pointer of myData and modify it with
bool getData(double** myData)
{
*pmyData = new double[2];
...
}
and call getData in main:
getData(&myData);
The myData given as parameter to getData function is passed on stack as a copy. When modifying that value in getData function you actually modify the value from the stack.
When you return to the main function everything is as it was before (except a memory leak).
The quickest solution would be to change the getData function like this:
bool getData(double *&myData)
and you're all set.
You pass the pointer into your function by value, not reference. Try this:
bool getData(double* &myData)
{
...
}
The difference is that myData is now a reference to the pointer in main, not a copy of it that gets destroyed when the function exits.