Disappearing struct in pointer

I am fairly new to C++ and have been coding Java for over 4 years. The memory management of C++ is new to me and I want to make sure I understand it correctly.

My problem seems to be that a variable is passed to a function, stored in a pointer, and said variable goes out of scope.

Here is a small example.

1
2
3
4
5
6
7
8
9
10
11
12
13
void Function(){
    Struct1 s{};
    Struct2 s2{s};
}  

struct Struct2{
    Struct2(Struct& sin){
    sp = &sin;
}
 
private:
    Struct1* sp;
};


Is it correct that when Function ends, ms goes out of scope and any subsequent access to sp will be to bad memory? Is it also correct that if I pass s by reference and store the value instead of the pointer that when s goes out of scope, sp will still be valid?

Now my problem is that Struct has virtual methods and it is the base struct for structs that need to be stored for saving to a file later, therefore, I need to store s as a pointer to avoid slicing off of the subclass members. I was planning on adding an enum to keep track of the type. This seems kind of convoluted though and I am wondering if there is a better way.

How do I go about solving this? Will I need to have some management class that stores references to every available type before they go out of scope?
Last edited on
Your naming scheme is strange. What's with all the leading m's? Sometimes that scheme is used for member variables, but not for everything!

Your spacing is also terrible. Indentation should be 4 spaces, and consistent.

The way you've written it, msp is never valid. You are saving the address of the ctor's parameter, which is essentially a local variable. It goes out of scope at the end of the ctor. To fix it you can either pass in the address, or accept it as a reference.

godspeed

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#include <iostream>

class Object {
public:
    void print() const {
        std::cout << "hello\n";
    }
};

class Object2 {
    Object* po;
public:
    Object2(Object& o) {
        po = &o;
    }
    void print() const {
        po->print();
    }
};

void func() {
    Object o;
    Object2 o2(o);
    o2.print();
}  

int main() {
    func();
}

Last edited on
Thank you for your reply.

I tried passing by reference and the pointer still ends up becoming corrupted.

In my program o is in main(), o2 is in func() like you have, and I need to access o2 in o after func() is called. Keep in mind that Object is a virtual class.
Last edited on
Is it correct that when mFunction ends, ms goes out of scope and any subsequent access to msp will be to bad memory?
Yes.

Is it also correct that if I pass ms by reference and store the value instead of the pointer that when ms goes out of scope, msp will still be valid?
If you're making a copy, yes it will still be valid. But to avoid confusion, show a specific example if you're not sure if it's valid or not.

Show a complete, but minimal program that reproduces your issues.

If you're coming from Java, note that C++ has different practices in various ways. If you explain the actual problem you're trying to solve, someone might be able to tell you a more C++-esque solution.
Last edited on
I need to access o2 in o after func() is called

I don't understand what you mean.
o2 is not "in" o.
A pointer to o is in o2.

Modify this example to show what you mean:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
#include <iostream>

class Base {
public:
    virtual void print() const = 0;
};

class Object : public Base {
public:
    void print() const override {
        std::cout << "hello\n";
    }
};

class Object2 {
    Object* po;
public:
    Object2(Object& o) {
        po = &o;
    }
    void print() const {
        po->print();
    }
};

void func(Object& o) {
    Object2 o2(o);
    o2.print();
}  

int main() {
    Object o;
    func(o);
}

Sorry, I was in a hurry this morning.

Here is what I'm trying to do.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
#include <iostream>

class Base {
public:
    virtual void print() const = 0;
};

class Object : public Base {
public:
    void print() const override {
        std::cout << "hello\n";
    };
};

class Object2 {
    Base* po;
public:
    Object2() {};
    void set(Base& o){
        po = &o;
    };
    void print() const {
        po->print();
    };
};

class Object3 {
public:
    Object3() : o2() {};
    Object2 o2;
};

void func1(Object3& o3){
    Object o;
    o3.o2.set(o);
}


void func2(Object3& o3) {
    o3.o2.print();
}  

int main() {
    Object3 o3;
    func1(o3);
    func2(o3);
}


To do this, I think I would need to add o to a data structure with the proper type to avoid the pointer location from becoming invalid. I also think I would need to add an enum to Object2 and cast the po before calling print(). Is this really the best way to go about it? This means having to create a container (std::map?) for each type in o3 (or a management class) and tagging o2 with a key that it would supply o3 during a callback in it's destructor.

Perhaps my Java background is putting blinders on me and there is a better way to handle this?
Last edited on
I made a mistake in my last code, forgetting to change Object* to Base*, but you fixed that .

Maybe something like this, creating the contained object with new and adding a dtor to delete it.
I changed the names a little again.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
#include <iostream>

class Base {
public:
    virtual ~Base() = default;
    virtual void print() const = 0;
};

class Object1 : public Base {
public:
    void print() const override {
        std::cout << "Object 1\n";
    };
};

class Object2 : public Base {
public:
    void print() const override {
        std::cout << "Object 2\n";
    };
};

class Container1 {
    Base* po;
public:
    Container1() : po() { };   // init po to nullptr
    ~Container1() { delete po; }
    void set(Base* o){
        if (po) delete po;
        po = o;
    };
    void print() const {
        if (po) po->print();
    };
};

class Container2 {
    Container1 o2;
public:
    void set(Base* o) { o2.set(o); }
    void print() const { o2.print(); }
};

void setter1(Container2& c2){
    c2.set(new Object1);
}

void setter2(Container2& c2){
    c2.set(new Object2);
}

void printer(const Container2& c2) {
    c2.print();
}  

int main() {
    Container2 c2;
    setter1(c2);
    printer(c2);
    setter2(c2);
    printer(c2);
}

Thank you so much!

I was not aware of the vtable details.
Last edited on
the pointer po gets deleted between calls

How do you know? (I assume you mean between the setter1 call and the printer call.)

Try adding some extra output to the print functions:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// Container1
    void print() const {
        std::cout << "Container1::print\n";
        if (po)
            po->print();
        else
            std::cout << "po is nullptr\n";
    };

// Container2
    void print() const {
        std::cout << "Container2::print\n";
        o2.print();
    }

I don't know anything about JNI.

What's the result if you try this:
 
    Container1() : po(new Object1) { };  // init po to one of the objects so that it isn't nullptr 

Last edited on
Sorry, I had more than Object2 that needed to be allocated with new.
Topic archived. No new replies allowed.