In C++, I can determine the size of a class object using sizeof(my_class)
.
However, there seems to be no equivalent operator for the static part of a class.
Is there something like sizeof(static my_class)
in C++?
In C++, I can determine the size of a class object using sizeof(my_class)
.
However, there seems to be no equivalent operator for the static part of a class.
Is there something like sizeof(static my_class)
in C++?
You won't find a legal or portable1 way to do this in standard C++, but you can certainly use platform-specific tools to examine the binary to get an estimate of the size of global data.
On Unix platforms you can use one of a variety of ELF-format reading tools to dump the symbol table along with sizes. For example, something like:
nm --demangle --print-size a.out | egrep -i ' [bdgsr] '
Will dump the size (as the second field in the output) of all the global data in the .bss
, .data
, .rodata
and related sections2.
The --demangle
argument gives you human-readable names from the C++ mangled names. The egrep
at the end of the pipeline restricts the symbols to the ones that are typically used for static variables (i.e., it omits the symbols for functions). Given the following class:
class Foo {
static void StaticFunction();
void MemberFunction();
static int some_int_s;
static long some_zero_long;
static char some_char_array[];
static const char *some_const_string;
};
int Foo::some_int_s = 5;
char Foo::some_char_array[42];
const char* Foo::some_const_string = "hello, world?";
void Foo::StaticFunction() {
}
void Foo::MemberFunction() {
static double f = 0.5;
}
... and compiled with g++
, the nm
command given above outputs:
0000000000000000 0000000000000004 D Foo::some_int_s
0000000000000000 000000000000002a B Foo::some_char_array
0000000000000008 0000000000000008 D Foo::some_const_string
0000000000000010 0000000000000008 d Foo::MemberFunction()::f
The second column is the size of the global: 4 bytes for the int
, 0x2a (42) bytes for the char[]
and so on. Note that it includes function-local static variables as well, which is probably what you want since they take up size like anything else. You can use another grep
to restrict to specific classes.
Note that Foo::some_const_string
has size 8, despite having the value hello, world?
which is 14 characters (including the terminating null). In fact, you'll find that any const char *
or any static pointer at all will have size 8 on a 64-bit platform, since that is the size of the pointer itself. The actual data for the string literal (the characters h,e,l,l,o,...
) are stored somewhere else and this size is not reported by nm
. In general determining the size of string literals is complex and may not have a straightforward answer (i.e,. several classes may share the same underlying literal data). You'll probably have to script something like readelf
if you really want to include that in your accounting.
You might also try existing binary sizing utilities, such as Bloaty McBloatface, although a quick scan of the readme seems to indicate that it might simply give the same information as above (for example, it doesn't seem to handle the "string literal" issue).
1 For example, a comment mentions an approach of taking the difference of the "first" and "last" statics at runtime to estimate the size, but in addition to being undefined behavior it isn't likely to work in practice since global variables get spread across various sections in the binary, such as .bss
, .data
, .rodata
and other variants of those, so a simply subtraction will almost certainly return the wrong result for many classes.
2 In particular, when I say "related" I mean that it dumps the size of the "small" initialized and uninitialized sections in addition to the default ones.