Convert (void **) to object in C++ - c++

I am trying to convert a (void**) object into a queue in C++.
In one file HashTableVoid.cc I use the method find to:
bool HashTableVoid::find( const char * key, void ** data)
{
// Add implementation here
int i = hash(key);
HashTableVoidEntry * node = _buckets[i];
while(node){
if(strcmp(node->_key,key) == 0)
{
*data = node->_data;
return true;
}
node = node->_next;
}
return false;
}
And in IRCServer.cc I used
void IRCServer::sendMessage(int fd, const char * user, const char * password, const char * args)
{
//Get user's room
//Write to room messages
char * temp;
temp = strdup(args);
void ** q;
queue<char*> data;
const char * room = //Found Room;
communication.find(room, q);
data = (queue<char*>) ((char *)q);
data.push(temp);
//Make sure only 100 elements or less in the list
while(data.size() > 100)
data.pop();
}
I am creating void ** q to pass as a parameter to communication. The variable communication is a HashTable where the key is the room name and the value is a unique queue of messages. I am having trouble converting the void object to a queue. I can't change the find method.

Two problems that I can see directly:
First you call find without initializing q, so it doesn't actually point anywhere. So in the find function when you dereference do *data you dereference an unknown pointer leading to undefined behavior. I think what you're supposed to do is to declare q to be a single pointer, and then pass the address of that to the find function (emulating pass by reference). Like
void *q;
...
communication.find(room, &q);
However, since you're programming in C++ I don't see a reasong to use double-pointer to emulate pass by reference, since C++ have it built-in:
bool HashTableVoid::find( const char * key, void *& data);
The above declares the argument data as a reference to a pointer.
The second problem is your assignment from the pointer q to the variable data:
data = (queue<char*>) ((char *)q);
What you have now (without the changes above), q is a pointer to a pointer, and you try to use it as a single pointer, which you then try to cast to a value. A pointer is not a value, and can never be.
Maybe you mean
data = *reinterpret_cast<std::queue<char*>*>(q); // After change detailed above

Related

Reading to char * always has same address

I have a struct like these:
struct Node {
void *data;
Node *l, *r;
}
And I should use function:
void push(Queue *q, void *data, int priority) {
Node *n = new Node;
n->data = data;
// place node in queue
}
I'm trying to read strings in loop, but after that I got queue where all values in nodes are similar.
void read_input(Queue *q) {
string s;
int p;
cin >> s >> p;
// problem is here
push(q, (void *) s.c_str(), p);
}
void main() {
Queue *q = create();
for (int i = 0; i < 5; i++) {
read_input(q);
}
}
How can I fix that? Why string s always has the same address?
Like Trantor said, you using s.c_str() which is a private pointer of string s; and is valid only inside read_input function.
Every call to read_input will use this pointer that is destroyed every time you reach read_input end (out of scope).
You see the same pointer, probably because its on the stack. Its a coincidence.
To fix your issue, you need to create a copy of the characters and store them in node->data. However you will also need to think where to delete it. E.g. OnNodeDestroy event or similar.
The problem is, you are saving (temporary) pointers to the private internals of temporary objects of class std::string in your queue push call. They become invalid after leaving read_input, and may be even reused internally, so the pointer seems not to change.
Instead you should work with copies, allocate your own memory for the strings.
When you have created a string object compiler will allocate the memory from stack and all the time that string object will pointing to that particular memory location (static memory allocation in this case) only. In your structure void *data pointer will also always pointing to that same memory location. Hence the last value entered into string object will reflect in all the node in your stack. To fix this you have to dynamically allocate memory each time so that the data pointer should pointing to different memory location and you will get different value.
void read_input(Queue *q) {
//string s;
char *s = (char *)malloc(50);
int p;
cin >> s >> p;
push(q, (void *) s, p);
}

Pass by pointer not updating memory address

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**.

Memory corruption when passing data to method

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);

C++ (compiler?) freeing memory allocated in function

I am currently doing some University work in C+ (really C, just swap malloc and free for new and delete). The problem is that compiler deallcoates memory allocated in a function, even though a pointer is pointing to that memory space, causing a segmentation fault when trying to access said structures field. (Simplified example) Code below:
P.S.: I am compiling to C++ 2003 standard with -Og.
main.cpp:
#include <cstdlib>
#include <iostream>
#include <cstring>
using namespace std;
struct Usu{
long unsigned int DNI;
char Correo[30];
char Nombre[30];
char Foto[20][20];
char *publicaciones;
long unsigned int *amigos;
struct Usu *next;
};
typedef struct Usu Usuario;
void RegistrarU(Usuario *);
void InsertarUsuario(Usuario *, char *, char *, long unsigned int, Usuario *);
int main (int argc, char *argv[]) {
Usuario * baseDatos = NULL;
RegistrarU(baseDatos);
}
void RegistrarU(Usuario * baseDatos)
{
long unsigned int AuxDNI = 34212345;
char AuxNombre[30] = "Hello";
char AuxCorreo[30]= "World";
Usuario *aux = NULL;
InsertarUsuario(baseDatos, AuxCorreo, AuxNombre, AuxDNI, aux);
cout<<baseDatos->DNI; //Doesn't work here
system("pause");
}
void InsertarUsuario(Usuario * baseDatos , char * AuxCorreo,char * AuxNombre,long unsigned int AuxDNI, Usuario * aux)
{
baseDatos = new Usuario;
baseDatos->DNI = AuxDNI;
strcpy(baseDatos->Nombre,AuxNombre);
strcpy(baseDatos->Correo,AuxCorreo);
baseDatos->next = NULL;
cout<<baseDatos->DNI; //Works Here
system("pause");
return;
}
It doesn't not work because you are passing a pointer by value. This means that inside InsertarUsuario you are just setting the local variable baseDatos to the memory allocated by new, without effectively giving anything useful to the caller.
You want to allocate memory in the called function and be able to reference the allocated object from the caller. To do this you need to pass the pointer by addres itself. So you pass a pointer to a pointer to a Usuario. Something like:
Usuario * baseDatos = NULL;
RegistrarU(&baseDatos);
void RegistrarU(Usuario ** baseDatos) {
..
InsertarUsuario(baseDatos, AuxCorreo, AuxNombre, AuxDNI, aux);
}
void InsertarUsuario(Usuario ** baseDatos , char * AuxCorreo,char * AuxNombre,long unsigned int AuxDNI, Usuario * aux) {
Usuario *tmpUsuario = new Usuario;
*baseDatos = tmpUsuario;
..
}
The compiler doesn't free memory: you simply never change the value of baseDatos. InsertarUsuario receives a copy of the pointer value (initially NULL) and locally changes it, but changes to the straight-up value of an argument aren't reflected in the calling function. This means that once InsertarUsuario returns, baseDatos is NULL again.
You either need to return baseDatos from InsertarUsuario (and stop accepting it as a parameter), or accept a pointer to the Usuario pointer (a double pointer) or a reference to that pointer.
You are passing baseDatos into InsertarUsuario by value, not reference (or pointer to pointer), so its value in the RegistrarUsuario function is not changing.
Try changing the prototype of InsertarUsuario to
void InsertarUsuario(Usuario ** baseDatos , char * AuxCorreo,char * AuxNombre,long unsigned int AuxDNI, Usuario * aux)
and call it as
InsertarUsuario(&baseDatos, AuxCorreo, AuxNombre, AuxDNI, aux);

invalid read size of 1 valgrind

I've been scratching my hair out but can't seem to find what is wrong with the following code. Here is the small snippet of valgrind output that it generates
Invalid read of size 1 at 0x4c22d82: strlen (mc_replace_strmem.c:242)
by 0x5E65CA: Application::readConfigurationFile() (char_traits.h:262)
by 0x5694BD: main Address 0xafc9660 is 24 bytes inside a block of size
39 free'd at 0x4C20E0D: operator delete(void*)
(vg_replace_malloc.c:342) by 0x635618:
Configurator::getParameterValue(char const*, char**) by 0x5E65B2:
Application:readConfigurationFile() (Application.cpp:77) by 0x5694BD:
main
bool Configurator::getParameterValue(const char *p_pParameterName, char** p_pParameterValue)
{
bool blReturnValue = false;
QDomElement element;
QDomNode node;
QDomNodeList list;
list = doc.elementsByTagName(p_pParameterName);
if (!list.isEmpty())
{
node = list.item(0);
element = node.toElement();
QString qs = element.text().toUtf8();
*p_pParameterValue = (char *)(qs.toStdString().c_str());
blReturnValue = true;
}
else
{
char sMessage[200];
sprintf(sMessage, "<Configurator::getParameterValue> Error! Parameter %s could not be found\n", p_pParameterName);
m_outputFunction(sMessage);
}
return blReturnValue;
}
bool Configurator::parseFile()
{
bool blReturnValue = false;
QString errorStr;
int errorLine;
int errorColumn;
if (!doc.setContent((QIODevice*)(&file), true, &errorStr, &errorLine, &errorColumn))
{
char aTemp[512];
sprintf(aTemp, "<Configurator::parseFile> error! can not read the file row: %d, column: %d:\n",errorLine, errorColumn);
m_outputFunction(aTemp);
}
else
{
closeFile();
blReturnValue = true;
}
return blReturnValue;
}
bool Application::readConfigurationFile()
{
bool blReturnValue = false;
m_outputFunction("<Application::readConfigurationFile> Reading configuration..\n");
if(m_configurator.parseFile())
{
blReturnValue = true;
m_configurator.writeParameters();
char *pTemp = 0;
if(!m_configurator.getParameterValue("center_no", m_bCenterNo))
m_bCenterNo = 1;
if(m_configurator.getParameterValue("highway_header", &pTemp))
m_strHighwayHeader.assign(pTemp);
else
m_strHighwayHeader.assign("... HIGHWAY"); // Default value
}
return blReturnValue;
}
Can somebody please tell me why I see invalid reads, I don't even use malloc/calloc in this code snippet.
*p_pParameterValue = (char *)(qs.toStdString().c_str());
Why you did so? QString is local variable and toStdString return new std::string
std::string QString::toStdString () const
So, returned std::string will be deleted. c_str() returns pointer to const char*. Quote from n3337 draft:
const charT* c_str() const noexcept;
const charT* data() const noexcept;
1 Returns: A pointer p such that p + i == &operator[](i) for
each i in [0,size()]. 2 Complexity: constant time. 3 Requires: The
program shall not alter any of the values stored in the character
array.
if(m_configurator.getParameterValue("highway_header", &pTemp))
m_strHighwayHeader.assign(pTemp);
Wrong. Since value in pTemp was deleted, when temporary object qs.toStdString() was deleted.
You are in effect returning a pointer to a local variable. In getParameterValue the variable qs is local inside a block, and you assign that strings pointer to p_pParameterValue. When getParameterValue the stack space formerly occupied by qs is now reclaimed and the pointer pTemp now points to unused memory. This is undefined behavior, and can cause lots of bad stuff to happen.
The temporary string object returned from qs.toStdString() allocates memory for the string, which is freed when the temporary is destroyed (after evaluation of the full expression). If you are compiling with optimization, it is likely that the std::string d'tor is inlined into your function, so it doesn't show up in your call stack.
When you want to continue using the string data after the function is done, you need to make it persist. The (in my opinion) sanest way is to return a std::string object rather than a char *, so the last parameter could be a std::string ** (which is filled by new std::string(qs.toStdString())), or a std::string & which is assigned to.
If you have the Boost libraries, you can also use boost::optional<std::string> as the return type, which provides a "string with a valid flag" data type.