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);
Related
To immprove performance i was trying to implement a aligned_malloc() function to allocate new memory with an aligned address , i know the "new" operator returns always an aligned address but i want to write my own function for better understanding , this is my try :
#include <iostream>
#include <stdlib.h>
/*
in purpose let's make our struct not aligned
*/
struct s{
char foo[3];
};
s * array = NULL;
template <class t>
t* aligned_malloc(size_t array_size)
{
t* array = NULL;
char * ptr = (char*) malloc((array_size+1)*sizeof(t)); // array_size+1 to not get out of memory when incrementing pointer
while((((uintptr_t)ptr)%sizeof(t)) != 0 )
++ptr;
return ((t*)ptr);
}
int main()
{
struct s * array = aligned_malloc<s>(10);
/*
let's test for crashs
*/
for (int c=0;c<10;c++)
{
array[c].foo[3] = 'f';
}
std::cout<<(((int)array)%sizeof(s))<<std::endl; // allways show '0' ,like the operator "new"
system("pause");
}
An other way to do it , is by creating a memory manager that allocates a big memory block and returns the aligned address for each request .
Note : im not assuming that this is the correct way to do it , i wrote this for learning purposes , not assuming & not claiming .
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
I want to copy data to a struct member given a double pointer to that structure.
I cannot change the signature of copyFoo().
The member cnt is assigned the return value of GetCnt() as expected, but memcpy creates access violations when I use it like this.
Could someone elaborate how memcpy is to be used when I have a double pointer to a struct and a void pointer member? Thank you very much!
struct mystruct
{
void * data;
unsigned int cnt;
};
void copyFoo( myObj * inBar, mystruct **outFoo)
{
memcpy((*outFoo)->data, inBar->GetData(), inBar->GetLength() );
(*outFoo)->cnt= inBar->GetCnt();
}
int main(void){
myObj *in = getObj();
mystruct *out= new mystruct;
copyFoo(in, &out));
delete in;
delete out;
}
memberfunction GetData() of inbar returns a void pointer, GetCnt() returns unsigned int and GetLength() returns an int.
A memory block with appropriate size should be allocated before you try to copy the data into it:
void copyFoo(myObj *inBar, mystruct **outFoo)
{
(*outFoo)->data = malloc(inBar->GetLength()); // <-- THIS
memcpy((*outFoo)->data, inBar->GetData(), inBar->GetLength());
(*outFoo)->cnt= inBar->GetCnt();
}
in case the data member of mystruct is not yet initialized or points to the memory, which has already been freed, the copyFoo function invokes the undefined behavior.
What is the difference between the two copy functions below? I do not seem to see a difference between them. Specifically the void*& vs the void*.
So what is the difference between T*& and T*? When would I use one over the other? Also, if I made them accept const parameters, what would happen? What would the difference be?
#include <iostream>
void Copy(void* Source, void* Destination, int Size)
{
//memcpy(Destination, Source, Size);
char* S = static_cast<char*>(Source);
char* D = static_cast<char*>(Destination);
*D = *S;
}
void Copy2(void* &Source, void* &Destination, int Size)
{
char* S = static_cast<char*>(Source);
char* D = static_cast<char*>(Destination);
*D = *S;
}
int main()
{
int A = 2;
int B = 5;
int C = 7;
void* pA = &A;
void* pB = &B;
void* pC = &C;
Copy(pA, pB, 1);
Copy2(pA, pC, 1);
std::cout<< B <<std::endl;
std::cout<< C <<std::endl;
}
Both of the above print "2". Both are the same no?
One is a pointer, the other is a reference to a pointer.
Google both and pick up a C++ basics book.
Think of passing by pointer as passing a memory address by value (ie, a copy). In the receiving function, you have a copy of the memory address and you can change where that memory address pointer points to, and what that destination memory contents looks like. When you return from that function, the destination memory is still changed, but the original pointer is unchanged.
In contrast, a reference to a pointer allows you to change where that memory points to after you return from the function. Otherwise it is the same.
A common usage is a funciton which allocates memory such as:
SomeClass *someClass = null;
PopulateSomeClass(someClass);
...
void PopulateSomeClass(SomeCLass* &someCLass)
{
someClass = new SomeClass;
}
But really, google this for more detail - this is a more basic C++ concept.
For instance, a reference is typically implemented as a const * under the covers in the compiler. So it is a const pointer to pointer.
void func(char* buf) { buf++;}
Should I call it passing by pointer or just passing by value(with the value being pointer type)? Would the original pointer passed in be altered in this case?
This is passing by value.
void func( char * b )
{
b = new char[4];
}
int main()
{
char* buf = 0;
func( buf );
delete buf;
return 0;
}
buf will still be 0 after the call to func and the newed memory will leak.
When you pass a pointer by value you can alter what the pointer points to not the pointer itself.
The right way to do the above stuff would be
ALTERNATIVE 1
void func( char *& b )
{
b = new char[4];
}
int main()
{
char* buf = 0;
func( buf );
delete buf;
return 0;
}
Notice the pointer is passed by reference and not value.
ALTERNATIVE 2
Another alternative is to pass a pointer to a pointer like
void func( char ** b )
{
*b = new char[4];
}
int main()
{
char* buf = 0;
func( &buf );
delete buf;
return 0;
}
Please note I am not in any way advocating the use of naked pointers and manual memory management like above but merely illustrating passing pointer. The C++ way would be to use a std::string or std::vector<char> instead.
The pointer will not be altered. Pass by pointer means pass an address. If you want the pointer altered, you have to pass a double pointer a deference it once.
foo( char **b)
{
*b = NULL;
}
The pointer itself is being passed by value (the memory being pointed at is being passed by pointer). Changing the parameter inside the function will not affect the pointer that was passed in.
To implement reference semantics via "passing a pointer", two things must happen: The caller must take the "address-of" the thing to be passed, and the callee must dereference a pointer.
Parts of this can be obscured by the use of arrays, which decay to a pointer to the first element - in that sense, the array content is always "passed by reference". You can use an "array-of-one" to obscure the dereferencing, though.
This is the straight-forward apporoach:
void increment_me(int * n) { ++*n; } // note the dereference
int main() { int n; increment_me(&n); } // note the address-of
Here's the same in disguise:
void increment_me(int n[]) { ++n[0]; } // no visible *
int main() { int n[1]; increment_me(n); } // or &