How to declare child pointer with parent from different structs in C++ - c++

I want to connect child on line no->rodzic = tz; to pointer tz which points to "parent", but those are 2 different structs. Is it possible to do like I think? My ERROR is: cannot convert... etc in assignment
struct lotwarta {
int wartosc,x,y;
lotwarta *parent;
};
struct lzamknieta {
int wartosc,x,y;
lzamknieta *parent;
lzamknieta *tz;
};
lzamknieta *nz;
nz = new lzamknieta; // do listy zamknietej dodajemy 1 element
nz->wartosc = 0;
nz->x = startx;
nz->y = starty;
nz->parent = NULL;
lzamknieta* tz = nz;
lotwarta *no;
no = new lotwarta;
no->wartosc = 0;
no->x = startx;
no->y = starty;
no->parent = NULL;
cout << no->rodzic << endl;
lotwarta *to = no;
if( (y!=1) && (G[y-1][x]!=5) )
{
no = new lotwarta;
no->wartosc = euklides(x,y-1);
no->x = x;
no->y = y-1;
no->parent = tz; <- here I have this error
}

I don't really know what this code should do,
but you can assign a pointer of a type to another type by simply casting its value:
no->rodzic = reinterpret_cast<lzamknieta*>(tz); //in this case tz would be casted to a pointer of type lzamknieta
But it is not always a good idea, to cast a pointer to another type, it depends on the context.

Related

How to fix memory leak

I am working on the project which using pointer (new ext...) and I don't know how to fix it, I couldn't use the delete syntax because it will break the code literally.
list<Virus*> DoClone()
{
list<Virus*> l;
Dengue *d1 = new Dengue(1), *d2 = new Dengue(1);
for (int i = 0; i < 4; i++)
d1->m_protein[i] = m_protein[i];
d1->m_dna = m_dna;
d1->m_resistance = m_resistance;
for (int i = 0; i < 4; i++)
d2->m_protein[i] = m_protein[i];
d2->m_dna = m_dna;
d2->m_resistance = m_resistance;
l.emplace_back(d1);
l.emplace_back(d2);
//delete d1;
//delete d2;
return l;
}
void DoDie()
{
this->m_dna = NULL;
memset(this->m_protein, 0, 4);
this->m_resistance = 0;
delete this->m_dna;
}
Smart pointers to the rescue:
list<std::unique_ptr<Virus>> DoClone()
{
list<std::unique_ptr<Virus>> l;
auto d1 = std::make_unique<Dengue>(1);
auto d2 = std::make_unique<Dengue>(1);
for (int i = 0; i < 4; i++)
d1->m_protein[i] = m_protein[i];
d1->m_dna = m_dna;
d1->m_resistance = m_resistance;
for (int i = 0; i < 4; i++)
d2->m_protein[i] = m_protein[i];
d2->m_dna = m_dna;
d2->m_resistance = m_resistance;
l.emplace_back(std::move(d1));
l.emplace_back(std::move(d2));
return l;
}
void DoDie()
{
m_dna.reset();
memset(this->m_protein, 0, 4);
this->m_resistance = 0;
}
It would be best if you learn to use smart pointers ASAP. Here is good lecture on topic.
Also see:
C++ Core Guidelines
R.20: Use unique_ptr or shared_ptr to represent ownership
Reason
They can prevent resource leaks.
Example
Consider:
void f()
{
X x;
X* p1 { new X }; // see also ???
unique_ptr<X> p2 { new X }; // unique ownership; see also ???
shared_ptr<X> p3 { new X }; // shared ownership; see also ???
auto p4 = make_unique<X>(); // unique_ownership, preferable to the explicit use "new"
auto p5 = make_shared<X>(); // shared ownership, preferable to the explicit use "new"
}
This will leak the object used to initialize p1 (only).
Enforcement
(Simple) Warn if the return value of new or a function call with return value of pointer type is assigned to a raw pointer.
Extra:
small refactor:
std::unique_ptr<Dengue> createDengue(int x)
{
auto d = std::make_unique<Dengue>(x);
d->m_protein = m_protein; // someone claims this is an std::array so loop is not needed
d->m_dna = m_dna;
d->m_resistance = m_resistance;
return d;
}
list<std::unique_ptr<Virus>> DoClone()
{
list<std::unique_ptr<Virus>> l;
l.emplace_back(createDengue(1));
l.emplace_back(createDengue(1));
return l;
}
void DoDie()
{
m_dna.reset();
this->m_protein = {}; // someone claims this is an std::array so this is fine
this->m_resistance = 0;
}
list<Virus*> DoClone()
{
//Why are you using a list of pointers?
//Are you handing these out?
list<Virus*> l; // Replace list<Virus> l or use smart pointers
Dengue *d1 = new Dengue(1), *d2 = new Dengue(1);
for (int i = 0; i < 4; i++){
d1->m_protein[i] = m_protein[i];
}
//if the move semantics of any of them are wrong your code will crash,
//but you don't show us what these are.
d1->m_dna = m_dna;
d1->m_resistance = m_resistance;
for (int i = 0; i < 4; i++)
d2->m_protein[i] = m_protein[i];
d2->m_dna = m_dna;
d2->m_resistance = m_resistance;
l.emplace_back(d1);
l.emplace_back(d2);
//You definitely shouldn't be deleting these you jsut gave them to a container to hold!
//delete d1;
//delete d2;
return l;
}
void DoDie(ist<Virus*>& myList)
{
//You set this to nullptr, but try to delete it in 4 lines time. This looks like a leak
//Also the fact it was a pointer means you definitely copied it wrong above
//use std::shared_ptr or std::weak_ptr if you want to share things.
this->m_dna = NULL;
memset(this->m_protein, 0, 4);
this->m_resistance = 0;
delete this->m_dna;
//Lastly you need to free the memory in your container
for(auto* item : myList){
delete item;
}
myList.clear();
}

How to affect memory allocated by new and casted to an array od class objects?

I had hard time describing it in the title, but basically I have to turn some code from C based on structures into C++ one based on objects. At the beginnig it was more or less (I'll try to simplify since it's a part of a big library-like project):
typedef struct Thing{
int param;
char* name;
void* data; //Either some arrays or more structures, hence void*
};
Thing* Initialise(void){
Thing* thing;
thing = (Thing*)malloc(sizeof(*thing));
param = 0;
name = NULL;
data = NULL;
return thing;
}
Thing* thing1 = malloc(bytesofdata);
Thing** smallthings = (Thing**) thing1->data; //Basically if "data" is a structure of other things
for ( i = 0; i < numberofsmallthings; i++ ) {
size_t k;
for ( k = 0; k < fieldsperthing; k++ ) {
smallthings[i*fieldsperthing+k] = Initialise();
}
}
Then I turned the structure into a class and the function into its method which resulted in:
class Thing{
private:
int param;
char* name;
void* data; //Either some arrays or more structures, hence void*
public:
int Initialise(void);
};
int Thing::Initialise(void){
this->param = 0;
this->name = NULL;
this->data = NULL;
}
thing1->data = new Thing;
this->data = new char [bytesofdata];
Thing** smallthings = (Thing**)this->data;
for (i = 0; i < numberofsmallthings; i++) {
size_t k;
for (k = 0; k < fieldsperthing; k++) {
smallthings[i*fieldsperthing + k]->Initialise();
}
}
And in this version, no matter if I try initialising the memory of not I am greeted by "access violation".
Is there any way to make this work? Casting to structure seemed to work fine so my guess is that something about objects makes it not work but I have no idea how to potentially bypass this. I would like to avoid making more objects since due to this part being buried pretty deep in functions, deleting those would be quite hard (especially since it's supposed to be a data reading function so exact structure of "data" might be not known).
When you do this:
smallthings[i*fieldsperthing + k]->Initialise();
You're attempting to dereference an unintialized pointer. You first need to assign something to it, then you can initialize it:
smallthings[i*fieldsperthing + k] = new Thing;
smallthings[i*fieldsperthing + k]->Initialise();
Better yet, change Initialise to a constructor. Then you won't have to do creation and initialization in separate steps. So now you have:
int Thing::Thing(){
this->param = 0;
this->name = NULL;
this->data = NULL;
}
...
thing1 = new Thing();
this->data = (void *)new Thing *[numberofsmallthings];
Thing** smallthings = (Thing**)this->data;
for (i = 0; i < numberofsmallthings; i++) {
size_t k;
for (k = 0; k < fieldsperthing; k++) {
smallthings[i*fieldsperthing + k] = new Thing();
}
}

C++ got wrong value from array of struct

The problem is as described above. When I try to read values from loaded *.so file (using libdl), whih are in struct I am getting wrong values
Code of application:
#include <dlfcn.h>
#include <iostream>
/* For face data type reproduction */
#define GET_FACE_XYZ_SIZE 1
/* For face_array reproduction */
#define GET_FACE_ARRAY_SIZE 2
#define GET_OBJECT_DATA 3
typedef struct face {
float x[1000];
float y[1000];
float z[1000];
int vertices;
} face;
int main()
{
void *hook;
int (*fn)(int request_type, void *ptr);
hook = dlopen("/root/osms/dlopen-test/lib.so", RTLD_LAZY);
if(!hook)
{
std::cout << "Couldn't find lib.so" << std::endl;
}
fn = dlsym(hook, "object_info");
int face_array_size = fn(GET_FACE_ARRAY_SIZE, NULL);
std::cout << "FACE_ARRAY_SIZE: " << face_array_size << std::endl;
face pointer[face_array_size];
fn(NULL, pointer);
dlclose(hook);
std::cout << "pointer[0].z[1]: " << pointer[0].z[1] << std::endl;
return 0;
}
and code of lib.so:
/* For face data type reproduction */
#define GET_FACE_XYZ_SIZE 1
/* For face array reproduction */
#define GET_FACE_ARRAY_SIZE 2
#define GET_OBJECT_DATA 3
typedef struct face {
float x[1000];
float y[1000];
float z[1000];
int vertices;
} face;
extern "C" int object_info(int request, void *ptr)
{
face face_array[2];
face_array[0].x[0] = 1.1;
face_array[0].y[0] = 0.5;
face_array[0].z[0] = 1.2;
face_array[0].x[1] = 1.6;
face_array[0].y[1] = -0.11;
face_array[0].z[1] = -12;
face_array[0].x[2] = -0.12;
face_array[0].y[2] = 0.24;
face_array[0].z[2] = -0.12;
face_array[0].vertices = 3;
face_array[1].x[0] = -1.1;
face_array[1].y[0] = 0.15;
face_array[1].z[0] = -1.2;
face_array[1].x[1] = -1.6;
face_array[1].y[1] = 0.11;
face_array[1].z[1] = 1.2;
face_array[1].x[2] = 0.12;
face_array[1].y[2] = -0.24;
face_array[1].z[2] = 0.12;
face_array[1].vertices = 3;
if(request == GET_FACE_ARRAY_SIZE)
{
return 2;
}
else
{
ptr = face_array;
}
}
The expected output is pointer[0].z[1]: -12 but I am getting pointer[0].z[1]: -0.12. What's wrong in my code ?
Thanks in advance
Accessing
pointer[0].z[1]
Has undefined behaviour, because it has an indeterminate value.
object_info never modifies the array pointed by ptr. It simply modifies a local array, and assigns the local ptr to point to that local array.
A solution: Don't declare a local array, and instead modify the array pointed by the argument. In other words, repace face face_array[2]; with:
face* face_array = (face*)ptr;
And get rid of the ptr = face_array; that does nothing meaningful.
object_info is declared to return int, but not all code paths return a value. When the function reaches the end of object_info without a return statement, the behaviour is undefined.
A solution: Always return a value if the function is not void.
face_array_size is not a compile time constant value, so face pointer[face_array_size]; will declare a variable length array. VLA are not allowed in C++.
Either use C (VLA are supported since C99, but only optionally supported since C11) instead or use a dynamic array: std::vector<face> or make peace with the fact that your program is not standard compliant.
The variable "face_array" in function object_info and the variable "pointer" in main are not the same variable.
The statement "ptr = face_array" does not change the content of "pointer".
extern "C" int object_info(int request, face *face_array)
{
if(request == GET_FACE_ARRAY_SIZE)
return 2;
face_array[0].x[0] = 1.1;
face_array[0].y[0] = 0.5;
face_array[0].z[0] = 1.2;
face_array[0].x[1] = 1.6;
face_array[0].y[1] = -0.11;
face_array[0].z[1] = -12;
face_array[0].x[2] = -0.12;
face_array[0].y[2] = 0.24;
face_array[0].z[2] = -0.12;
face_array[0].vertices = 3;
face_array[1].x[0] = -1.1;
face_array[1].y[0] = 0.15;
face_array[1].z[0] = -1.2;
face_array[1].x[1] = -1.6;
face_array[1].y[1] = 0.11;
face_array[1].z[1] = 1.2;
face_array[1].x[2] = 0.12;
face_array[1].y[2] = -0.24;
face_array[1].z[2] = 0.12;
face_array[1].vertices = 3;
}

Pointers and pointers to reference

Having a structure
struct Person{
Person( int i):id(i){};
Person * next;
int id;
};
class Test{
public:
void addList( Person *&f , Person *&l , int i){
Person *tmp = new Person(i);
if( f == nullptr ){
f = tmp;
l = tmp;
return;
}
first -> next = tmp;
last = tmp;
}
void addArr( int *arr , int i ){
arr[index++] = i;
}
void print( ){
for( int i = 0; i < index; i ++)
cout << arr[i] << " ";
cout << endl;
}
Person *first = nullptr;
Person *last = nullptr;
int index = 0;
int *arr = new int[10];
};
function addList add node into linked list and addArr adds element into arr.
My question is about pointer and reference pointer.
in
void addList( Person *&f , Person *&l , int i){
Person *tmp = new Person(i);
if( f == nullptr ){
f = tmp;
l = tmp;
return;
}
first -> next = tmp;
last = tmp;
}
I need to pass pointer as reference. Otherwise , the local copy of pointer would be changed not outer. I assume compilator creates something like
Person *temporary = new Person(*f);
But would I not have to pass array by reference?
I am quite confused by this fact.
But would i do not have to pass array by reference?
Not in this case, by passing your Person pointer by reference in the addList function, you are able to alter the pointer itself. That is like saying, "Pointer, use a different address". This is possible, as it was passed by reference.
Whereas in your addArr function, you are not altering the pointer to the array itself. Rather, you are altering the data that is pointed to. "Pointed to data, use a different value". This data arr is pointing to is the same data outside the scope of the function.
So, no, you don't have to pass the array by reference.

unable to reach memory error in a struct in a class

I have this class for save receipt :
class Recept {
int Ingr_size;
char *Name;
char *Type;
char *Recipe;
struct Ingridient {
char *aName;
float Mas;
} *List_ingr;
when i trying to save ingredient name or mass by using this function:
void Recept::setIngr(const char * p, float mass) {
struct Ingridient * temp = new struct Ingridient[Ingr_size + 1];
if (Ingr_size) {
for (int i = 0; i < Ingr_size; i++)
temp[i] = List_ingr[i];
delete List_ingr;
List_ingr = temp;
}
List_ingr[Ingr_size].aName = new char[strlen(p) + 1];
strcpy(List_ingr[Ingr_size].aName, p);
List_ingr[Ingr_size].Mas = mass;
}
I get an error that "Unable to reach aName memory" & "Unable to reach Mas memory".
I can't find the problem where or why.
Thank you.
I get an error that "Unable to reach aName memory" & "Unable to reach Mas memory".
this is a runtime exception, you have not initiaized your class variables, you need at least a constructor which will do basic default initailizations:
Recept() : Ingr_size(0), List_ingr(nullptr){}
also, in case List_ingr is nullptr you should not try iterating it inside setIngr.
[edit]
If you have constructor as above in your class (which is not in the question), then you have other errors, see comments below:
void Recept::setIngr(const char * p, float mass) {
struct Ingridient * temp = new struct Ingridient[Ingr_size + 1];
if (Ingr_size) {
for (int i = 0; i < Ingr_size; i++)
temp[i] = List_ingr[i];
delete List_ingr;
List_ingr = temp;
}
else {
// !!! in case of Ingr_size you still need to set List_ingr,
List_ingr = temp;
}
List_ingr[Ingr_size].aName = new char[strlen(p) + 1];
strcpy(List_ingr[Ingr_size].aName, p);
List_ingr[Ingr_size].Mas = mass;
// !!! You need to increment size
Ingr_size++;
}