Solving the circular dependency conundrum "elegantly" - c++

So I am developing a programming language which compiles to bytecode for VM execution and also to C as an intermediate language for compiling to native binary. I chose C because it is low level enough and portable, saving a tremendous amount of effort by reusing existing compilers and not having to write compilers to assembly for each and every different platform and its oddities.
But existing compilers come with their drawbacks, one of which is the circular dependency issue. I want to solve circular dependencies in an elegant way (unlike C/C++) without awkward forward declarations, without having to use pointers and extra indirection and wasted memory, without having to separate declarations from definitions and so on... In other words, take this issue away from the developer like some programming languages do.
The way I see it, current C/C++ compilers' main problem with this is they cannot "look into the future" even though it is not really future, since the programmer intent is already expressed in code, my compiler does not have that issue, it is not unaware of anything beyond some certain point of parsing progress, it knows the sizes of objects with circular dependencies and can calculate the appropriate offsets and such.
I've already implemented "faked" inheritance which simply does "inline expansion" of inherited structures' members, so I am thinking I can also use the same approach to actually fake aggregation as well. In the most basic and simple example:
typedef struct {
int a;
} A;
typedef struct {
A a;
int b;
} B;
becomes:
typedef struct {
int A_a;
int b;
} B;
and the compiler does a bit of "translation":
B b;
b.a.a = 7;
becomes:
b.A_a = 7;
And in the same fashion all structures are collapsed down to a single root structure which only contains primitive types. This way there are absolutely no types used in structures whose sizes are not known in advance so the order of definition becomes irrelevant. Naturally, this mess is hidden away from the user and is only for the compiler's "eyes to see" while the user side is being kept structured and readable. And it goes without saying, but the binary footprint is preserved for compatibility with regular C/C++ code, the collapsed structure is binary identical to a regular structure that would use aggregation or inheritance.
So my question is: Does this sound like a sound idea? Anything that could go wrong I am missing?
EDIT: I only aim to solve the C/C++ related difficulties with circular dependencies, not the "chicken or egg" logical paradox. Obviosly it is impossible for two objects to contain each-other without leading to some form of infinite loop.

You cannot safely use pointers to the substructures because you cannot get pointers to "compatible types" by pointing to the primitive members. E.g. after
struct Foo {
short a;
int b;
};
struct Bar {
struct Foo foo;
};
struct Bar bar;
the pointers &bar.foo and &bar.foo.a have different types and cannot be used interchangeably. They also cannot be cast to each other's types without violating the strict aliasing rule, triggering undefined behavior.
The problem can be avoided by inlining the entire struct definition each time:
struct Bar {
struct { short a; int b; } foo;
};
Now &bar.a is a pointer to struct {short; int;} which is a compatible type for struct Foo.
(There may also be padding/alignment differences between struct-typed members and primitive members, but I couldn't find an example of these.

Related

How to indicate absence of aliasing for a struct member?

If you write statements like:
a[i] = b[i] + c[i];
...you might want to indicate to the compiler that a[i], b[i] and c[i] point to different places in memory, thus enabling various optimizations (e.g. vectorization). This can be done by adding a special keyword in their declaration:
float * __restrict__ a; // same for b and c
However, what do you do if instead of float you are using a more complex object, say:
struct item {
float foo, bar;
};
Consider the following code:
float *a, *b;
item *c;
// ...
for (int i = 0; i < 42; ++i) {
a[i] = b[i] * c[i].foo + c[i].bar;
}
In the loop, the compiler does not care about c[i] but rather about c[i].foo and c[i].bar. How can an equivalent assertion about pointer independence be declared in this case with respect to individual fields of the structure?
For now, I have managed to solve the problem using:
#pragma GCC ivdep
However, this turns off the dependency checking completely. I would still be interested in more selective solution.
The Standard does not require compilers to accommodate the possibility that a[anything] and b[anything] might be used to access any part of a struct item. It lists the types of lvalues that implementations must always allow to be used to access a structure such as struct item, and non-character member types such as int are not among them. No special permission would be required to let a compiler assume that neither a nor b will alias a struct item.
Of course, it would be rather unhelpful for a compiler to allow code to take the address of a struct or union member of non-character type, but never actually allow the resulting pointer to be used to access the member even in cases that don't involve aliasing(*). The Standard makes no distinction between cases that involve aliasing and those that don't, however, and leaves the question of when to allow structures to be accessed using member-type lvalues entirely up to implementers' judgment. The authors of gcc and clang may have decided that the easiest way to support the use of pointers to struct members in non-aliasing scenarios was to support them in all scenarios, but the Standard hardly requires such treatment, and I don't think the authors wanted it to.
The Standard gives implementations room to benefit from an assumption that neither a not b will alias c, and yet still support most programs that would need to work with pointers to structure or union members. While there are some cases where more qualifiers similar to __restrict would be helpful, I'm not sure what additional permission you would think an implementation would need in cases like the one you show.
(*) i.e. situations where no operations accesses a region of storage, or derive a pointer/reference that will be used to do so, at times when there exists a newer pointer/reference that will also be used to access or address the same storage in conflicting fashion.
There's no need to do that.
Either a compiler is smart enough to know that these struct members cannot alias, or it's not smart enough to do anything useful with that information.
The reason you have the __restrict__ and C99 restrict keywords is because unlike structs, arrays might alias. Therefore the keywords provide real and useful information to the compiler.

Wrapping built-in C++ types to guarantee initialization

It recently occurred to me that more often than I'd like to admit, the fix for a "strange bug that only materializes occasionally" is to simply initialize the one member variable of a class I forgot to add to the initializer list.
To prevent wasting time on such bugs in the future, I've been toying with the idea to completely abandon built-in primitive types and replacing them with wrapper classes that act exactly like their primitive counterparts, except that they'll always be initialized.
I'm proficient enough in C++ to know that I can write classes that get very close to that goal. I.e. I'm confident I can write a MyInt class that behaves very much like a real int. But I also know C++ well enough to know that there's probably an arcane thing or two I'd be missing ;)
Has anyone done something like this before? Any pointers to relevant documentation, or list of pitfalls to watch out for? Is this even a good idea, or are there any downsides I'm not seeing?
Thanks!
EDIT: Thanks everyone for your comments, here's an update. I started playing with Jarod42's wrapper snippet and see if I could convert a small hobby project codebase. Not completely unexpectedly, it's quite a PITA, but would probably be doable. It does start feeling like a very big hammer for this problem though.
Compiler warnings are not a real option, since only a single one (-Weffc++) seems to find the problem and it only exists for gcc, i.e. this is not a safe, portable solution.
My conclusion so far is to start using C++11's in-class initialization for all primitive members as suggested by Praetorian below. I.e. something like
struct C {
int x = 0; // yay C++11!
};
.. and hope that after some time, ommitting such initialized feels as "naked" as declaring an unititialized variable in code within a function (which I've stopped doing a long time ago). This seems much less error-prone than trying to keep the initializer list(s) up-to-date, because it's right there with the declaration.
C++11 makes it quite easy to avoid this pitfall by allowing in-class initialization of non-static data members. For example:
struct foo
{
foo(int i) : i(i) {} // here i will be set to argument value
foo() {} // here i will be zero
int i = {}; // value (zero) initialize i
};
This feature is not restricted to trivial types either. So just start initializing data members as soon you declare them within the class definition.
If your compiler doesn't support this feature, try cranking the warning level up to see if it'll tell you about uninitialized data members. For instance, g++ has the -Weffc++ flag that will warn you about uninitialized data members (amongst other things).
Next thing to try would be a static analysis tool to catch these mistakes.
In conclusion, there are several things I'd try before going down the path of boxing every trivial data type.
It's a lot easier to just turn on compiler warnings. Most decent compilers will warn you about using uninitialized variables - granted there are a few edge cases that compilers can miss.
Try better debugging.
You can switch on compiler warnings for uninitialized variables (see this SO question).
You can also use programs that do this and other checking of your code (static analysis), like cppcheck, which lists uninitialised variables.
Also try changing how you code. In C++ you have control over when memory is allocated, what constructors are used, and so on. If you are coding in a style where you construct objects with partial data, and then later populate other pieces, then you are likely to run into uninitialised variables a lot. But if you make sure that all the constructors construct a valid object in a valid state, and avoid having multiple points of truth (see Single Point Of Truth principle), then your errors are more likely to be caught by the compiler - you would have to pass an uninitialised variable as a value (which VC++ will warn you on), or have the wrong number or type of things in your constructor call (compile error), etc.
Might I suggest you pick out your most recent source of this kind of thing, complete with the chain of structures that got you there, and ask how you might restructure it better? There is a particularly disciplined style of coding in C++ which makes maximum use of the compiler and thus tips you off as early as possible. Really the bugs you create when using that style shouldn't be anything less than multi-threading issues, resource issues etc.
I worry that if you initialise everything just to prevent such errors, you'll miss out on learning that disciplined style which extends so much further than uninitialised variables.
Following may help:
template <typename T>
class My
{
public:
constexpr My() : t() {}
constexpr My(const T&t) : t(t) {}
operator T& () { return t; }
constexpr operator const T& () const { return t; }
const T* operator& () const { return &t; }
T* operator& () { return &t; }
private:
T t;
};
Note sure if it is better to check that My<int> is used in place of each possible uninitialized int...
But note that you have to do special job for union anyway.

Any performance penalty for wrapping int in a class?

I have a project with many vectors, sets and maps. In most cases the key/index is an integer. I am considering creating small classes like:
class PhoneRepoIx //index into map {phone_number => pointer}
{
public:
int n;
};
class PersonIx //index into map {social_security_number => pointer}
{
public:
int n;
};
Would I incur any speed or memory penalty? With memory I am 90% sure that there would be no memory cost per instance, only per class-type. With speed I am not clear.
Motivation:
With the above approach, the compiler would do some extra type-checking for me. Also, with well chosen explicit type-names, the reader of my code will see more easily what I am doing. As of now I am using int everywhere and I chose the variable names to express what each index is. With the above, my variable names could be shorter.
Note:
Tyepdefs do not address my issue completely as the compiler would not do any extra type-checking, internally all the types would just be int.
Different compilers have different optimization abilities and different bugs. It is theoretically possible to compile this with precisely zero overhead. Will your compiler attain this theoretical limit? The answer is a definite "maybe". At least some compilers are known to do it at least some of the time.
The more interesting question is whether you should be worried over a possible performance degradation. And the answer to this question is a strong "no". Not until your program does in fact show unacceptable performance figures.
I would suggest the use of templates to get what you want.
template <typename T>
struct Index {
Index(int value) : value(value) {}
int value;
};
This is used like.
struct PhoneRepoIx {};
Index<PhoneRepoIx> PhoneIndex(1);
list[PhoneIndex.value];
There are two functions which will commonly be called on this class:
Constructor
operator< (since STL map is a tree impl, the keys should support this)
I think the above answer "don't worry" sounds pretty good (profile then optimize). But to take a crack at why this won't cause any slowdown (guesswork):
Constructor: No reason why a decent compiler couldn't turn this into a stack pointer increment (to make space for the int) followed by setting the available space.
operator<: No reason why a decent compiler couldn't inline the simple comparison between the 'n's of the two objects.

Casting big POD into small POD - guaranteed to work?

Suppose I've a POD struct which has more than 40 members. These members are not built-in types, rather most of them are POD structs, which in turn has lots of members, most of which are POD struct again. This pattern goes up to many levels - POD has POD has POD and so on - up to even 10 or so levels.
I cannot post the actual code, so here is one very simple example of this pattern:
//POD struct
struct Big
{
A a[2]; //POD has POD
B b; //POD has POD
double dar[6];
int m;
bool is;
double d;
char c[10];
};
And A and B are defined as:
struct A
{
int i;
int j;
int k;
};
struct B
{
A a; //POD has POD
double x;
double y;
double z;
char *s;
};
It's really very simplified version of the actual code which was written (in C) almost 20 years back by Citrix Systems when they came up with ICA protocol. Over the years, the code has been changed a lot. Now we've the source code, but we cannot know which code is being used in the current version of ICA, and which has been discarded, as the discarded part is also present in the source code.
That is the background of the problem. The problem is: now we've the source code, and we're building a system on the top of ICA protocol, for which at some point we need to know the values of few members of the big struct. Few members, not all. Fortunately, those members appear in the beginning of the struct, so can we write a struct which is part of the big struct, as:
//Part of struct B
//Whatever members it has, they are in the same order as they appear in Big.
struct partBig
{
A a[2];
B b;
double dar[6];
//rest is ignored
};
Now suppose, we know pointer to Big struct (that we know by deciphering the protocol and data streams), then can we write this:
Big *pBig = GetBig();
partBig *part = (partBig*)pBig; //Is this safe?
/*here can we pretend that part is actually Big, so as to access
first few members safely (using part pointer), namely those
which are defined in partBig?*/
I don't want to define the entire Big struct in our code, as it has too many POD members and if I define the struct entirely, I've to first define hundreds of other structs. I don't want to that, as even if I do, I doubt if I can do that correctly, as I don't know all the structs correctly (as to which version is being used today, and which is discarded).
I've done the casting already, and it seems to work for last one year, I didn't see any problem with that. But now I thought why not start a topic and ask everyone. Maybe, I'll have a better solution, or at least, will make some important notes.
Relevant references from the language specification will be appreciated. :-)
Here is a demo of such casting: http://ideone.com/c7SWr
The language specification has some features that are similar to what you are trying to do: the 6.5.2.3/5 states that if you have several structs that share common initial sequence of members, you are allowed to inspect these common members through any of the structs in the union, regardless of which one is currently active. So, from this guarantee one can easily derive that structs with common initial sequence of members should have identical memory layout for these common members.
However, the language does not seem to explicitly allow doing what you are doing, i.e. reinterpreting one struct object as another unrelated struct object through a pointer cast. (The language allows you to access the first member of a struct object through a pointer cast, but not what you do in your code). So, from that perspective, what you are doing might be a strict-aliasing violation (see 6.5/7). I'm not sure about this though, since it is not immediately clear to me whether the intent of 6.5/7 was to outlaw this kind of access.
However, in any case, I don't think that compilers that use strict-aliasing rules for optimization do it at aggregate type level. Most likely they only do it at fundamental type level, meaning that your code should work fine in practice.
Yes, assuming your small structure is laid out with the same packing/padding rules as the big one, you'll be fine. The memory layout order of fields in a structure is well-defined by the language specifications.
The only way to get BigPart from Big is using reinterpret_cast (or C style, as in your question), and the standard does not specify what happens in that case. However, it should work as expected. It would probably fail only for some super exotic platforms.
The relevant type-aliasing rule is 3.10/10: "If a program attempts to access the stored value of an object through a glvalue of other than one of the following types the behavior is undefined: ...".
The list contains two cases that are relevant to us:
a type similar (as defined in 4.4) to the dynamic type of the object
an aggregate or union type that includes one of the aforementioned types among its elements or nonstatic data members (including, recursively, an element or non-static data member of a subaggregate or contained union)
The first case isn't sufficient: it merely covers cv-qualifications. The second case allows at the union hack that AndreyT mentions (the common initial sequence), but not anything else.

Inheritance Costs in C++

Taking the following snippet as an example:
struct Foo
{
typedef int type;
};
class Bar : private Foo
{
};
class Baz
{
};
As you can see, no virtual functions exist in this relationship. Since this is the case, are the the following assumptions accurate as far as the language is concerned?
No virtual function table will be created in Bar.
sizeof(Bar) == sizeof(Baz)
Basically, I'm trying to figure out if I'll be paying any sort of penalty for doing this. My initial testing (albeit on a single compiler) indicates that my assertions are valid, but I'm not sure if this is my compiler's optimizer or the language specification that's responsible for what I'm seeing.
According to the standard, Bar is not a POD (plain old data) type, because it has a base. As a result, the standard gives C++ compilers wide latitude with what they do with such a type.
However, very few compilers are going to do anything insane here. The one thing you probably have to look out for is the Empty Base Optimization. For various technical reasons, the C++ standard requires that any instance be allocated storage space. For some compilers, Foo will be allocated dedicated space in the bar class. Compilers which implement the Empty Base Optimization (most all in modern use) will remove the empty base, however.
If the given compiler does not implement EBO, then sizeof(foo) will be at least twice sizeof(baz).
Yeah, without any virtual members or member variables, there shouldn't be a size difference.
As far as I know the compiler will optimize this correctly, if any optimizing is needed at all.