Pre-setting Virtually Inherited Data

Good day helpful forumers...

I have a problem, and I will explain what I imply to do with WORKING code, and then I will provide segfaulting code.

Working code:

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
#include <iostream>

class B
{
public:
    int b;
};

class A : public B
{
public:
    A()
    {
        std::cout << "b_value: " << b << std::endl;
    }
};

int main()
{
    char *buffer = new char[sizeof(A)]; // Creates a buffer, needed so we can get the address before object creation.
    // What I intend to do:
    reinterpret_cast<A *>(buffer)->b = 15; // We manipulate the value in that specific part of the memory to be 15
    // As you can see, the object's constructor is NOT called whilst setting a value.
    new (buffer) A; // We then "assume" the class to the specific memory space
    return 0;
}

b_value: 15


Very well, let's try the same with virtually inherited B:
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
#include <iostream>

class B
{
public:
    int b;
};

class A : virtual public B
{
public:
    A()
    {
        std::cout << "b_value: " << b << std::endl;
    }
};

int main()
{
    char *buffer = new char[sizeof(A)]; // Creates a buffer, needed so we can get the address before object creation.
    // What I intend to do:
    reinterpret_cast<A *>(buffer)->b = 15; // We manipulate the value in that specific part of the memory to be 15
    // As you can see, the object's constructor is NOT called whilst setting a value.
    new (buffer) A; // We then "assume" the class to the specific memory space
    return 0;
}

Segmentation fault


The debugger (gdb) doesn't make me any wiser; the call stack is merely main. The segfault occurs on the reinterpret_cast.

So what do I need to do to fix this issue? (The issue of setting data in a block of memory that contains virtually inherited data in its classes)
Last edited on
What I think happens is that when you use virtual inheritance it will have to use a vtable to lookup the location of b, but the vtable pointer will not be initialized until the A constructor has been called.
Why are you trying to do this? Semantics of inheritance and polymorphism are implementation defined, most likely you're breaking stuff.

I don't think casting to A* like that will ever work.

EDIT: Yeah, as Peter said above, your implementation probably tries to use the VTABLE, which is garbage values.

I wonder if operator new will work instead of using that plain buffer.
Last edited on
L B
- How are they implementation defined? Aren't they standard C++? Also casting to A* works when there is non-virtual inheritance and you can set pretty much any data member of the buffer. Just try it out!

Why am I trying to do this? Because I plan on building an inheritance chain, and I want to simply virtually inherit a single class into all members of the chain, and initialize this data before the object lowest in the chain is created. I simply want to avoid having to send (and copy) data through constructors, making for ugly and slow programming.

Peter87
- Yes that seems to be the case, so I guess I'll need to do things manually:

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

class B
{
public:
    int b;
};

class A : virtual public B
{
public:
    A()
    {
        std::cout << "b_value: " << b << std::endl;
    }
};

int main()
{
    char *buffer = new char[sizeof(A)]; // Creates a buffer, needed so we can get the address before object creation.
    *reinterpret_cast<int *>(buffer + 8) = 15;
    new (buffer) A; // We then "assume" the class to the specific memory space
    return 0;
}

b_value: 15


Edit: in response to L B
- Is there any possible way to explicity initialize the vtable before object creation so that I can dereference some data?
Last edited on
@OP I tried some hacks for you but they didn't work. I was hoping B would be constructed before C, but apparently the VTABLE is still unuseable at this point.
http://ideone.com/jOTIBj

@Bourgond Aries: The way a compiler implements the semantics of polymorphism and virtual inheritance is implementation defined and means you cannot reliable mess with memory like that.
Bourgond Aries = OP xD

So it seems that the argument list has to be finished before the vtable becomes usable?
OP = Original Post
OPer = Original PostER
So unless you are a post...

And I don't know, it's implementation-defined.

And that means that this:

*reinterpret_cast<int *>(buffer + 8) = 15;

Will not work for all compilers or all cases, because it won't always be off by 8.

Also, what if B has its own constructor? ;p
Last edited on
Bourgond Aries wrote:
Because I plan on building an inheritance chain, and I want to simply virtually inherit a single class into all members of the chain, and initialize this data before the object lowest in the chain is created. I simply want to avoid having to send (and copy) data through constructors, making for ugly and slow programming.


Why don't you just put the stuff you want to inherit in the base class? Then it will be inherited. Base classes are initialised first, and the initialisation descends the inheritance tree.

Virtual inheritance is for helping when you have multiple inheritance (2 or more parent classes, as in the diamond problem). It looks like you only need public inheritance here.

If you need to use casting, it is generally a sign that some thing is wrong with the design.
Also, if for some reason you can't change the base class, you can always extend it with another class, do whatever in there, and then have your lowest-down classes inherit that middle class.
L B
- On the forums I've been to the definition of OP is interchangable xD
If B has its own constructor (where it actually initializes data), then what has been changed externally is overwritten.

TheIdeasMan
- I think I haven't really specified what I meant with my design. Therefore I'll give you some code:

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
#include <string>

class E // Holds a form of data, only accessed by C and A
{
protected:
    int e_data;
};

class D // Holds another form of data, accessed by C, B, and A
{
protected:
    int a;
};

class C : virtual D, virtual E // A worker that needs data in D to function properly, has its own internal data for internal use.
{
protected:
    void workFunction();
private:
    int m_data;
    std::string m_example
};

class B : virtual D // Another worker, also needs D to function properly, but needs to share the data in D with C.
{
protected:
    char someAlgorithm(int x, int y);
private:
    int m_data;
    std::string m_example;
};

class A : virtual D, B, C, virtual E // The lowest class in the inheritance chain, this one is actually created explicitly.
{
public:
    void someFunction();
private:
    int m_data;
    std::string m_example;
};

int main()
{
    // Create buffer, initialize the data inherited by A.
    char *buffer = new char[sizeof(A)];
    reinterpret_cast<A *>(buffer)->a = 5;
    reinterpret_cast<A *>(buffer)->e_data = 22;
    delete new (buffer) A;
    return 0;
}


See how I need to isolate data? For putting it in a single base class would make it "global" to all the classes, and I want to avoid that. Also, the diamond problem occurs here with the data, and therefore I want virtual inheritance - To share what needs to be shared.

L B can you provide some example of base class extension? I think I know what you mean but code is just so much more understandable :P
Last edited on
Why do you need to create the information from a buffer?

I think you should consider passing the information you want to A's constructor, which passes it to the constructors of all its base classes. Also, you don't need to extend D and E in A because C does that for you, and since it is virtual inheritance, they are direct base classes anyway.
L B:
- I want to initialize standard information because of the following problem:

You have class A, B, C,..., Z. Chronological execution commences; but Z needs a variable A creates.

What? You're gonna pass that variable all the time through every constructor? And when you need to add / delete do that for every constructor?

My answer was to create new classes that inherit a map - this map can be sent at will (so classes that do not need to pass it on, do not need to get the map). Due to this being automatic; the programmer does not need to worry about editing all those constructors. Because there's a freedom of choosing whether to pass it on or not; you retain C++ freedom of choice. You don't pay for that what you do not use!

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
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
class Vault
{
public:
     template
    <
        typename Class,
        char flag = Flag::live | Flag::skip,
        typename ...Args
    >
    static void create(Args ...args)
    { // halt denotes whether the object's creator thread will stall after first object creation.
        static_assert(std::is_base_of<Vault, Class>::value, "Class provided does not inherit from Vault!");
        char *Vault_buffer = new char[sizeof(Class)];
        reinterpret_cast<Vault *>(Vault_buffer)->m_map = new std::map<signed int, void *>;
        (*((reinterpret_cast<Vault *>(Vault_buffer))->m_map))[-1] = new Flare(flag & Flag::skip); // 01 Is inversed by Flare. true means fallthrough
        (*((reinterpret_cast<Vault *>(Vault_buffer))->m_map))[-2] = new unsigned int(1); // Object counter
        (*((reinterpret_cast<Vault *>(Vault_buffer))->m_map))[-3] = new std::mutex; // Counter mutex
        (*((reinterpret_cast<Vault *>(Vault_buffer))->m_map))[-4] = new std::mutex; // Notifier mutex (in case the object is deleted) mutexes are delete-safe
        (reinterpret_cast<std::mutex *>((*((reinterpret_cast<Vault *>(Vault_buffer))->m_map))[-4]))->lock();
        auto tthr = [=](Args ...ar) -> void
                    {
                        if (flag & Flag::kill) // 10
                            delete (new (Vault_buffer) Class(ar...));
                        else
                            new (Vault_buffer) Class(ar...);
                    };
        std::thread(tthr, args...).detach();
        (reinterpret_cast<Flare *>((*((reinterpret_cast<Vault *>(Vault_buffer))->m_map))[-1]))->wait();
        (reinterpret_cast<std::mutex *>((*((reinterpret_cast<Vault *>(Vault_buffer))->m_map))[-4]))->unlock();
    }
protected:
     template
    <
        typename Class,
        char flag = Flag::live,
        typename ...Args
    >
    void build(Args ...args)
    {
        if (std::is_base_of<Vault, Class>::value) // Sending map ONLY when this evaluates to true!
        {
            // Reference counter ///////////////////////////////////////////////////////////
            (*reinterpret_cast<std::mutex *>((*m_map)[static_cast<signed int>(-3)])).lock();
            (*reinterpret_cast<unsigned int *>((*m_map)[static_cast<signed int>(-2)]))++;
            (*reinterpret_cast<std::mutex *>((*m_map)[static_cast<signed int>(-3)])).unlock();
            /////////////////////////////////////////////////////////////////////////////////

            // Needs to be outside the thread, if the build caller deletes itself, the map is invalidated!
            char *buffer = new char[sizeof(Class)];
            reinterpret_cast<Vault *>(buffer)->m_map = this->m_map;
            //////////////////////////////////////////////////////////////////////////////////

            // Actual thread //////////////////////////////
            auto ffp = [=](Args ...args)
                        {
                            if (flag & Flag::kill)
                                delete (new (buffer) Class(args...));
                            else
                                new (buffer) Class(args...);
                        };
            std::thread(ffp, args...).detach();
        }
        else
        {
            auto ffp = [=](Args ...args)
                        {
                            if (flag & Flag::kill)
                                delete (new Class(args...));
                            else
                                new Class(args...);
                        };
            std::thread(ffp, args...).detach();
        }
    }
    // Other useful functions that manage the map.
private:
     std::map m_map;
};

class Any : Vault
{};


The static create function is there to create a first class object from a non-object. It also creates a new m_map.
The build function then spreads this same map to a new class object that is created by a class that inherits from Vault.

The thing is that in the inheritance chain; it would be nice if all classes could virtuall inherit from Vault, so that they're all initialized and can all work with their own piece of code without having to pass it through constructors.

I hope this answers your question.



Also, I know how virtual inheritance works, but it seems I'll just be stuck using non-virtual inheritance for the time being, and just acquiring the data from the map in the class that is created, and then sending that data through constructors to the virtually inherited classes...
If you need to virtually inherit 26 classes you're doing something very wrong. I hope you find the solution, since I cannot offer one.
@Bourgond Aries

Perhaps you can give us your real life example of what you are trying to do, then we can possibly offer some insight into the design.

Using a map to aid the design as well as casting & lots of code instead of normal class design seems weird IMO at this stage.

You have some reasonably complex code, I am not sure whether you know all the following stuff thoroughly already, and I want to avoid providing junior advice to someone who knows much more than me. However, I don't see any clues that you are aware of them, so here goes ....

To avoid the cast, why can't you have an interface in the base class and use that to initialise / retrieve it's members? I understand you only want inherit things some of the time - so this means you are contradicting the "IS A" relationship by having inheritance in this situation.

Also, there is the "USES A " & "HAS A" relationships.

There are other ways of doing things - like making use of the Composite Design pattern to build complex objects. This link provides an overview of all 23 of them:

http://www.vincehuston.org/dp/


I have just bought the "Gang of Four" book, which gives a much more detailed look.

HTH

L B:
- Well I'll offer a real life solution, as TheIdeasMan suggested.

TheIdeasMan:

- Let me assure you that I [think i] know exactly what I'm doing with my code. I know what I want, and I'll now try to explain what that is: A system that makes programming larger systems easier; it must eliminate some of the most common C++ programming quirks that annoy me. (Yes, very ego-centric of me)

First some key points in the design.

1. No dependencies on global variables allowed.
- A: We create a map that is local to a chain of classes that have created each other and passed the data. Any class inheriting Vault will have access to a specific map that is shared with a few other classes that inherit Vault. Thus the "create" function comes in the playing field, it creates a new map and thus starts a new chain of data flow.

2. The ability to dynamically add or remove classes without too much work.
- A: Imagine class A, B, C,... Z. Z requires data stores by A, but A is destroyed (deleted) when it builds B (through delete this;). A stores its item as a pointer in the map. Class X2 needs to be added, standard procedure would be to pass the map ("Global-local" data) through the constructors. This is extremely tedious and doesn't give me any breathing space. Therefore, we make every class inherit from Vault. Every class then uses a build function which automagically passes the map WITHOUT you doing anything but inherit from Vault! The map is accessible from any Vault-inheriting class (just like in parameter passing), that is actually "built" (build function) by a class that has a Vault.

3. Cohesion
- A: The reinterpret casts are only performed to dereference map items. If a class Z needs to access data in A, then there will be coupling if Z knows through A what type the object needs to be. Luckily, we only need to reinterpret_cast once from the map's void ptr to Z's internal data pointer (which has a type). I put this in a templated protected member functions like so:

1
2
3
4
5
6
7
8
9
10
11
12
13
    // This one takes a pointer and stores an address in it, does not require explicit template arguments.
    template <typename POINTER_TYPE, typename KEY_TYPE>
    void fetch(POINTER_TYPE &ptr, KEY_TYPE key)
    {
        ptr = reinterpret_cast<POINTER_TYPE>((*m_map)[std::abs(static_cast<signed int>(key))]);
    }

    // This one returns the pointer, needs explicit template argument for POINTER_TYPE
    template <typename POINTER_TYPE, typename KEY_TYPE>
    POINTER_TYPE fetch(KEY_TYPE key)
    {
        return reinterpret_cast<POINTER_TYPE>((*m_map)[std::abs(static_cast<signed int>(key))]);
    }


These functions are inherited by inheriting Vault, this means anything that doesn't inherit Vault has no access whatsoever to the map.

Q: Why the heck do you use std::abs in a signed int map?!
A: -1, -2,... contain system objects (Flare for signalling, object counter, mutexes..)

4. Allowing an inheritance chain to share the data as well:
- A: Virtual inheritance, all object handle themselves yet they are intertwined. I really like that concept.




Anywaysze,.. I've slept over the design and came up with using a proxy class. This solves my virtual inheritance problem whilst not having to pass object through constructors!

I needed to change the create and build function. Proxy class definition is all the way down.

(Post's too long, even tho it's under 8192 chars.)
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
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
// Declaration:
template <typename Class>
class Paroxy;

class Vault
{
    enum Flag : char
    {
        // NULL is standard
        halt = 0, // 0000 0000
        skip = 1, // 0000 0001
        live = 0, // 0000 0000
        kill = 2 // 0000 0010
    };

    /**
    \brief Creates a new Vault chain.

    Creates a new Vault object inside the
    provided class. The class will spread its
    Vault by calling build. Create is only for
    creating new Vaults.

    \param args accepts any amount of arguments,
    which will be passed on to the created class.
    */
    template
    <
        typename Class,
        char flag = Flag::live | Flag::skip,
        typename ...Args
    >
    static void create(Args... args)
    {
        static_assert(std::is_base_of<Vault, Class>::value, "Class provided does not inherit from Vault!");
        std::map<signed int, void *> *temp_map = new std::map<signed int, void *>;
        (*temp_map)[-1] = new Flare(flag & Flag::skip); // 01 Is inversed by Flare. true means fallthrough
        (*temp_map)[-2] = new unsigned int(1); // Object counter
        (*temp_map)[-3] = new std::mutex; // Counter mutex
        (*temp_map)[-4] = new std::mutex; // Notifier mutex (in case the object is deleted) mutexes are delete-safe
        (reinterpret_cast<std::mutex *>((*temp_map)[-4]))->lock();
        auto tthr = [=](Args ...ar) -> void
                    {
                        if (flag & Flag::kill) // 10
                            delete (new Paroxy<Class>(temp_map, ar...));
                        else
                            new Paroxy<Class>(temp_map, ar...);
                    };
        std::thread(tthr, args...).detach();
        (reinterpret_cast<Flare *>((*temp_map)[-1]))->wait();
        (reinterpret_cast<std::mutex *>((*temp_map)[-4]))->unlock();
    }

protected:
	Vault();
	Vault(std::map<signed int, void *> *map_position);
    virtual ~Vault();

    /**
    \brief resumes the suspended thread.

    The thread that has been suspended by create
    will continue execution when this function
    is called.
    */
    void fall();

    /**
    \brief Spreads the Vault object to another class.

    If the provided class inherits from Vault:
    Builds a class object and provides it with the
    caller's Vault object.

    If the provided class does not inherit from Vault:
    Threadedly builds a class and leaves it like that.

    \param args accepts any amount of arguments,
    which will be passed on to the created class.
    */
    template
    <
        typename Class,
        char flag = Flag::live,
        typename ...Args
    >
    void build(Args ...args)
    {
        if (std::is_base_of<Vault, Class>::value)
        {
            // Reference counter ///////////////////////////////////////////////////////////
            (*reinterpret_cast<std::mutex *>((*m_map)[static_cast<signed int>(-3)])).lock();
            (*reinterpret_cast<unsigned int *>((*m_map)[static_cast<signed int>(-2)]))++;
            (*reinterpret_cast<std::mutex *>((*m_map)[static_cast<signed int>(-3)])).unlock();
            /////////////////////////////////////////////////////////////////////////////////

            // Actual thread //////////////////////////////
            auto ffp = [m_map](Args ...args)
                        {
                            if (flag & Flag::kill)
                                delete (new Paroxy<Class>(m_map, args...));
                            else
                                new Paroxy<Class>(m_map, args...);
                        };
            std::thread(ffp, args...).detach();
        }
        else
        {
            auto ffp = [=](Args ...args)
                        {
                            if (flag & Flag::kill)
                                delete (new Class(args...));
                            else
                                new Class(args...);
                        };
            std::thread(ffp, args...).detach();
        }
    }
// Utility functions...
private:
    std::map<signed int, void *> *m_map;
};

// Definition
template <typename Class>
class Paroxy : virtual Vault, Class
{
public:
    template <typename ...Args>
    Paroxy(std::map<signed int, void *> *map_position, Args ...args)
    :
    Vault(map_position),
    Class(args...)
    {}
    ~Paroxy()
    {}
};

I left the Utility functions out on purpose, there are so many.

I 'm nearing the char limit for a post so I'm gonna round it up;
The 4 points need to be answered, and they are now answered by using a proxy class "Paroxy" (Yeah, Proxy was already in the namespace .-.).
Now a new problem has occurred; the need for non-virtual inheritance when the class created does not virtually inherit Vault! Let's think about it... Template parameters?


One last thing; Made this some time ago, maybe it can help in explaining:
http://mclo3.deviantart.com/art/Design-Patterns-Conveyor-Pattern-348272434
Last edited on
Topic archived. No new replies allowed.