-
-
Notifications
You must be signed in to change notification settings - Fork 1.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
CT sizeof(T) is wrong if T or any member is empty object #13945
Comments
Here is some information that is important when working on a solution here. In C an empty struct has size 0 and in C++ it has size 1. I can only imagine this to cause problems at some point. #include <stdio.h>
struct MyEmptyStruct{};
int main() {
printf("%d\n", sizeof(struct MyEmptyStruct)); // output: 0 in C but 1 in C++
} Maybe it is best to set the compile time size of an empty object to unknown for Nim. As far as I know they are useful for wrapper code only, and here they are already marked as unknown in size by the |
that's too pessimistic (and propagates to any containing type that have Empty as a sub-member). We should be able to infer sizeof with 100% reliability in this case (even if it means a
no, see examples I showed above, they don't even involve importc. This issue shouldnt' be hard to fix, IMO. |
Well, I looked it up again. An empty struct in C seems to be undefined behavior. In this case what gcc does isn't necessary what other C compilers do here. So it is correct that the Nim compiler injects a dummy char. In C++ though the size of an empty struct is defined to be 1 byte at least. I prefer a pessimistic compiler that is correct over a compiler that always has an answer that isn't always correct. |
Another thing that should be mentioned. Inheritance is done differently for C and C++ backends. In C++ inheritance maps to C++ inheritance. In C inheritance puts a value of the inherited type at the top level of the object. This has an affect on the size of the object. Make sure you test inheriting from an empty object in both C and C++, if you implement a fix for this. Or as you linked this optimization of empty structs causes a big mess and special cases in computing sizes of objects: #include <stdio.h>
#include <stdint.h>
struct BaseA {
uint8_t dummy;
};
struct BaseB {
};
struct InheritanceA: public BaseA {
int64_t data;
};
struct InheritanceB: public BaseB {
int64_t data;
};
int main() {
printf("%d\n", sizeof(BaseA)); // 1
printf("%d\n", sizeof(BaseB)); // 1
printf("%d\n", sizeof(InheritanceA)); // 16
printf("%d\n", sizeof(InheritanceB)); // 8
} Even though My proposed solution is still, set the size of empty objects to unknown for the Nim compiler and let the C and C++ compilers do whatever they want to do. And yes, stop emitting this dummy field for the C++ backend. |
Works since 1.4.0 |
CT sizeof(T) is wrong if T or any member is empty object.
$
, {.sizeof.}, const CVAR {.importc.}: int RFCs#205Example
Current Output
for both C and C++:
Expected Output
sizeof should match c_sizeof
Possible Solution
result.addf("char dummy;$n", [])
for empty objects, but CT sizeof doesn't take that into accountdummy
is probably not a good idea because it prevents optimization for empty base class: see http://www.stroustrup.com/bs_faq2.html#sizeof-emptySee also http://www.cantrip.org/emptyopt.html which explains how stdlib is implemented to eliminate the corresponding bloat
so probably this
dummy
should only be inserted for C backend, not C++ backend.Additional Information
$
, {.sizeof.}, const CVAR {.importc.}: int RFCs#205The text was updated successfully, but these errors were encountered: