Struct hack equivalent in C++ - c++

The struct hack where you have an array of length 0 as the last member of a struct from C90 and C99 is well known, and with the introduction of flexible array members in C99, we even got a standardized way of using it with []. Unfortunately, C++ provides no such construct, and (at least with Clang 3.4), compiling a struct with either [0] or [] will yield a compilation warning with --std=c++11 -pedantic:
$ cat test.cpp
struct hack {
char filler;
int things[0];
};
$ clang++ --std=c++11 -pedantic test.cpp
\test.cpp:3:14: warning: zero size arrays are an extension [-Wzero-length-array]
int things[0];
and similarly
$ cat test.cpp
struct fam {
char filler;
int things[];
};
$ clang++ --std=c++11 -pedantic test.cpp
\test.cpp:3:7: warning: flexible array members are a C99 feature [-Wc99-extensions]
int things[];
My question then is this; say that I want to have a struct that contains an array of variable size as the last item in C++. What is the right thing to do given a compiler that supports both? Should I go with the struct hack [0] (which is a compiler extension), or the FAM [] (which is a C99 feature)? As far as I understand it, either will work, but I am trying to figure out which is the lesser evil?
Also, before people start suggesting keeping an int* to a separately allocated piece of memory in the struct instead, that is not a satisfactory answer. I want to allocate a single piece of memory to hold both my struct and the array elements. Using a std::vector also falls into the same category. If you wonder why I don't want to use a pointer instead, the R.'s answer to another question gives a good overview.
There have been some similar questions elsewhere, but none give an answer to this particular question:
Are flexible array members valid in C++?: Very similar, but the question there is whether FAM is valid in C++ (no). I am looking for a good reason to pick one or the other.
Conforming variant of the old “struct hack”: Proposes an alternative, but it's neither pretty, nor always correct (what if padding is added to the struct?). Accessing the elements later is also not as clean as doing e.things[42].

You can get more or less the same effect using a member
function and a reinterpret_cast:
int* buffer() { return reinterpret_cast<int*>(this + 1); }
This has one major defect: it doesn't guarantee correct
alignment. For example, something like:
struct Hack
{
char size;
int* buffer() { return reinterpret_cast<int*>(this + 1); }
};
is likely to return a mis-aligned pointer. You can work around
this by putting the data in the struct in a union with the type
whose pointer you are returning. If you have C++11, you can
declare:
struct alignas(alignof(int)) Hack
{
char size;
int* buffer() { return reinterpret_cast<int*>(this + 1); }
};
(I think. I've never actually tried this, and I could have some
details of the syntax wrong.)
This idiom has a second important defect: it does nothing to
ensure that the size field corresponds to the actual size of the
buffer, and worse, there is no real way of using new here. To
correct this, somewhat, you can define a class specific
operator new and operator delete:
struct alignas(alignof(int)) Hack
{
void* operator new( size_t, size_t n );
void operator delete( void* );
Hack( size_t n );
char size;
int* buffer() { return reinterpret_cast<int*>(this + 1); }
};
The client code will then have to use placement new to allocate:
Hack* hack = new (20) Hack(20);
The client still has to repeat the size, but he cannot ignore
it.
There are also techniques which can be used to prevent creating
instances which aren't allocated dynamically, etc., to end up
with something like:
struct alignas(alignof(int)) Hack
{
private:
void operator delete( void* p )
{
::operator delete( p );
}
// ban all but dynamic lifetime (and also inheritance, member, etc.)
~Hack() = default;
// ban arrays
void* operator new[]( size_t ) = delete;
void operator delete[]( void* p ) = delete;
public:
Hack( size_t n );
void* operator new( size_t, size_t n )
{
return ::operator new( sizeof(Hack) + n * sizeof(int) );
}
char size;
// Since dtor is private, we need this.
void deleteMe() { delete this; }
int* buffer() { return reinterpret_cast<int*>(this + 1); }
};
Given the fundamental dangers of such a class, it is debatable
if so many protective measures are necessary. Even with them,
it's really only usable by someone who fully understands all of
the constraints, and is carefully paying attention. In all but
extreme cases, in very low level code, you'd just make the
buffer a std::vector<int> and be done with it. In all but the
lowest level code, the difference in performance would not be
worth the risk and effort.
EDIT:
As a point of example, g++'s implementation of
std::basic_string uses something very similar to the above,
with a struct containing a reference count, the current size
and the current capacity (three size_t), followed directly by
the character buffer. And since it was written long before
C++11 and alignas/alignof, something like
std::basic_string<double> will crash on some systems (e.g.
a Sparc). (While technically a bug, most people do not consider
this a critical problem.)

This is C++, so templates are available:
template <int N>
struct hack {
int filler;
int thing [N];
};
Casting between different pointers to different instantiations will be the difficult issue, then.

The first thing that comes to mind is DON't, don't write C in C++. In 99.99% of the cases this hack is not needed, won't make any noticeable improvement in performance over just holding a std::vector and will complicate your life and that of the other maintainers of the project in which you deploy this.
If you want a standard compliant approach, provide a wrapper type that dynamically allocates a chunk of memory large enough to contain the hack (minus the array) plus N*sizeof(int) for the equivalent of the array (don't forget to ensure proper alighnment). The class would have accessors that map the members and the array elements to the correct location in memory.
Ignoring alignment and boiler plate code to make the interface nice and the implementation safe:
template <typename T>
class DataWithDynamicArray {
void *ptr;
int* array() {
return static_cast<int*>(static_cast<char*>(ptr)+sizeof(T)); // align!
}
public:
DataWithDynamicArray(int size) : ptr() {
ptr = malloc(sizeof(T) + sizeof(int)*size); // force correct alignment
new (ptr) T();
}
~DataWithDynamicArray() {
static_cast<T*>(ptr)->~T();
free(ptr);
}
// copy, assignment...
int& operator[](int pos) {
return array()[pos];
}
T& data() {
return *static_cast<T*>(ptr);
}
};
struct JustSize { int size; };
DataWithDynamicArray<JustSize> x(10);
x.data().size = 10
for (int i = 0; i < 10; ++i) {
x[i] = i;
}
Now I would really not implement it that way (I would avoid implementing it at all!!), as for example the size should be a part of the state of DataWithDynamicArray...
This answer is provided only as an exercise, to explain that the same thing can be done without extensions, but beware this is just a toy example that has many issues including but not limited to exception safety or alignment (and yet is better than forcing the user to do the malloc with the correct size). The fact that you can does not mean that you should, and the real question is whether you need this feature and whether what you are trying to do is a good design at all or not.

If you really you feel the need to use a hack, why not just use
struct hack {
char filler;
int things[1];
};
followed by
hack_p = malloc(sizeof(struct hack)+(N-1)*sizeof int));
Or don't even bother about the -1 and live with a little extra space.

C++ does not have the concept of "flexible arrays". The only way to have a flexible array in C++ is to use a dynamic array - which leads you to use int* things. You will need a size parameter if you are attempting to read this data from a file so that you can create the appropriate sized array (or use a std::vector and just keep reading until you reach the end of the stream).
The "flexible array" hack keeps the spatial locality (that is has the allocated memory in a contiguous block to the rest of the structure), which you lose when you are forced to use dynamic memory. There isn't really an elegant way around that (e.g. you could allocate a large buffer, but you would have to make it sufficiently large enough to hold any number of elements you wanted - and if the actual data being read in was smaller than the buffer, there would be wasted space allocated).
Also, before people start suggesting keeping an int* to a separately
allocated piece of memory in the struct instead, that is not a
satisfactory answer. I want to allocate a single piece of memory to
hold both my struct and the array elements. Using a std::vector also
falls into the same category.
A non-standard extension is not going to work when you move to a compiler that does not support it. If you keep to the standard (e.g. avoid using compiler-specific hacks), you are less likely to run into these types of issues.

There is at least one advantage for flexible array members over zero length arrays when the compiler is clang.
struct Strukt1 {
int fam[];
int size;
};
struct Strukt2 {
int fam[0];
int size;
};
Here clang will error if it sees Strukt1 but won't error if it instead sees Strukt2. gcc and icc accept either without errors and msvc errors in either case. gcc does error if the code is compiled as C.
The same applies for this similar but less obvious example:
struct Strukt3 {
int size;
int fam[];
};
strukt Strukt4 {
Strukt3 s3;
int i;
};

Related

How to fill buffers with mixed types conveniently in standard conformant way?

There are problems, where we need to fill buffers with mixed types. Two examples:
programming OpenGL/DirectX, we need to fill vertex buffers, which can have mixed types (which is basically an array of struct, but the struct maybe described by a run-time data)
creating a memory allocator: putting header/trailer information to the buffer (size, flags, next/prev pointer, sentinels, etc.)
The problem can be described like this:
there is an allocation function, which gives back some memory (new, malloc, OS dependent allocation function, like mmap or VirtualAlloc)
there is a need to put mixed types into an allocated buffer, at various offsets
A solution can be this, for example writing an int to an offset:
void *buffer = <allocate>;
int offset = <some_offset>;
char *ptr = static_cast<char*>(buffer);
*reinterpret_cast<int*>(ptr+offset) = int_value;
However, this is inconvenient, and has UB at least two places:
ptr+offset is UB, as there is no char array at ptr
writing to the result of reinterpret_cast is UB, as there is no int there
To solve the inconvenience problem, this solution is often used:
union Pointer {
void *asVoid;
bool *asBool;
byte *asByte;
char *asChar;
short *asShort;
int *asInt;
Pointer(void *p) : asVoid(p) { }
};
So, with this union, we can do this:
Pointer p = <allocate>;
p.asChar += offset;
*p.asInt++ = int_value; // write an int to offset
*p.asShort++ = short_value; // then a short afterwards
// other writes here
This solution is convenient for filling buffers, but has further UB, as the solution uses non-active union members.
So, my question is: how can one solve this problem in a strictly standard conformant, and most convenient way? I mean, I'd like to have the functionality which the union solution gives me, but in a standard conformant way.
(Note: suppose, that we have no alignment issues here, alignment is taken care of by using proper offsets)
A simple (and conformant) way to handle these things is leveraging std::memcpy to move whatever values you need into the correct offsets in your storage area, e.g.
std::int32_t value;
char *ptr;
int offset;
// ...
std::memcpy(ptr+offset, &value, sizeof(value));
Do not worry about performance, since your compiler will not actually perform std::memcpy calls in many cases (e.g. small values). Of course, check the assembly output (and profile!), but it should be fine in general.

Is using alloca() for variable length arrays better than using a vector on the heap?

I have some code using a variable length array (VLA), which compiles fine in gcc and clang, but does not work with MSVC 2015.
class Test {
public:
Test() {
P = 5;
}
void somemethod() {
int array[P];
// do something with the array
}
private:
int P;
}
There seem to be two solutions in the code:
using alloca(), taking the risks of alloca in account by making absolutely sure not to access elements outside of the array.
using a vector member variable (assuming that the overhead between vector and c array is not the limiting factor as long as P is constant after construction of the object)
The ector would be more portable (less #ifdef testing which compiler is used), but I suspect alloca() to be faster.
The vector implementation would look like this:
class Test {
public:
Test() {
P = 5;
init();
}
void init() {
array.resize(P);
}
void somemethod() {
// do something with the array
}
private:
int P;
vector<int> array;
}
Another consideration: when I only change P outside of the function, is having a array on the heap which isn't reallocated even faster than having a VLA on the stack?
Maximum P will be about 400.
You could and probably should use some dynamically allocated heap memory, such as managed by a std::vector (as answered by Peter). You could use smart pointers, or plain raw pointers (new, malloc,....) that you should not forget to release (delete,free,....). Notice that heap allocation is probably faster than what you believe (practically, much less than a microsecond on current laptops most of the time).
Sometimes you can move the allocation out of some inner loop, or grow it only occasionally (so for a realloc-like thing, better use unsigned newsize=5*oldsize/4+10; than unsigned newsize=oldsize+1; i.e. have some geometrical growth). If you can't use vectors, be sure to keep separate allocated size and used lengths (as std::vector does internally).
Another strategy would be to special case small sizes vs bigger ones. e.g. for an array less than 30 elements, use the call stack; for bigger ones, use the heap.
If you insist on allocating (using VLAs -they are a commonly available extension of standard C++11- or alloca) on the call stack, be wise to limit your call frame to a few kilobytes. The total call stack is limited (e.g. often to about a megabyte or a few of them on many laptops) to some implementation specific limit. In some OSes you can raise that limit (see also setrlimit(2) on Linux)
Be sure to benchmark before hand-tuning your code. Don't forget to enable compiler optimization (e.g. g++ -O2 -Wall with GCC) before benchmarking. Remember that caches misses are generally much more expensive than heap allocation. Don't forget that developer's time also has some cost (which often is comparable to cumulated hardware costs).
Notice that using static variable or data has also issues (it is not reentrant, not thread safe, not async-signal-safe -see signal-safety(7) ....) and is less readable and less robust.
First of all, you're getting lucky if your code compiles with ANY C++ compiler as is. VLAs are not standard C++. Some compilers support them as an extension.
Using alloca() is also not standard, so is not guaranteed to work reliably (or even at all) when using different compilers.
Using a static vector is inadvisable in many cases. In your case, it gives behaviour that is potentially not equivalent to the original code.
A third option you may wish to consider is
// in definition of class Test
void somemethod()
{
std::vector<int> array(P); // assume preceding #include <vector>
// do something with array
}
A vector is essentially a dynamically allocated array, but will be cleaned up properly in the above when the function returns.
The above is standard C++. Unless you perform rigorous testing and profiling that provides evidence of a performance concern this should be sufficient.
Why don't you make the array a private member?
#include <vector>
class Test
{
public:
Test()
{
data_.resize(5);
}
void somemethod()
{
// do something with data_
}
private:
std::vector<int> data_;
}
As you've specified a likely maximum size of the array, you could also look at something like boost::small_vector, which could be used like:
#include <boost/container/small_vector.hpp>
class Test
{
public:
Test()
{
data_.resize(5);
}
void somemethod()
{
// do something with data_
}
private:
using boc = boost::container;
constexpr std::size_t preset_capacity_ = 400;
boc::small_vector<int, preset_capacity_> data_;
}
You should profile to see if this is actually better, and be aware this will likely use more memory, which could be an issue if there are many Test instances.

Casting a pointer to a struct into another struct type with a smaller number of fields

Basic problem
I'm in a tricky situation that requires taking a pointer to a struct mainset and turning this into a pointer to a struct subset, whose fields are a contiguous subset of the fields of mainset, starting from the first. Is such a thing possible, with well-defined behavior? I realize that this is a pretty terrible thing to do, but I have good and frustrating reasons to do it [explained at the bottom for patient readers].
My attempt an an implementation seems to work, on OS X with the clang compiler:
#include <iostream>
struct mainset {
size_t size;
uint32_t reflex_size;
};
struct subset {
size_t size;
};
using namespace std;
int main(int argc, char *argv[]) {
mainset test = {1, 1};
subset* stest = reinterpret_cast<subset*>(&test);
std::cout << stest->size << std::endl;
}
The output is indeed 1, as I expect. However, I wonder: am I just getting lucky with a particular compiler and a simple case (in reality my structs are more complicated), or will this work in general?
Also, a follow-up question: for other annoying reasons, I worry that I might need to make my larger struct
struct mainset {
uint32_t reflex_size;
size_t size;
};
instead, with the extra field coming at the front. Could my implementation be extended to work in this case? I tried replacing &test with &test+sizeof(test.reflex_size) but this didn't work; the output of the cout statement was 0.
Explanation of why I have to do this
My project uses the GSL library for linear algebra. This library makes use of structs of the form
struct gsl_block {
size_t size;
double* data;
}
and similar structs like gsl_vector and gsl_matrix. So, I've used these structs as members of my C++ classes; no problem. A recently demanded feature for my project, however, is to enable reflection to my classes with the Reflex tool, part of the ROOT ecosystem. To enable reflection for a struct like this in Reflex, I must add an annotation like
struct gsl_block {
size_t size;
double* data; //[size]
}
This annotation tells Reflex that that the length of the array is provided by the field size of the same struct. Normally that would be that, but Reflex and ROOT have a very unfortunate limitation: the length field must be 32 bit. Having been informed that this limitation won't be fixed anytime soon, and not having the time/resources to fix it myself, I'm looking for workarounds. My idea is to somehow embed a struct bit-compatible with gsl_block within a larger struct:
struct extended_gsl_block {
size_t size;
double* data; //[reflex_size]
uint32_t reflex_size;
}
and similar things for gsl_vector and gsl_matrix; I can ensure that reflex_size and size are always equal (neither is ever bigger than ~50) and Reflex will be able to parse this header correctly (I hope; if reflex_size is required to precede data as a field something more difficult would be required). Since GSL routines work with pointers to these structs, my idea is this: given a pointer extended_gsl_block*, somehow get a pointer to just the fields size and data and reinterpret_cast this into a gsl_block*.
You are in luck.
The classes you show as an example conform to the requirements of standard layout types.
You can read more here:
http://en.cppreference.com/w/cpp/language/data_members#Standard_layout
You can test this premise in the compiler with:
static_assert(std::is_standard_layout<gsl_block>::value, "not a standard layout");

dynamic array in structure with consecutive memory?

struct Test
{
int var;
char *arr;
}
int main()
{
Test a;
a.arr = new char[50];
}
The above code would create a dynamic array in the structure but the dynamic array would not be actually memory allocated within the structure, its memory would be allocated somewhere else. I want this array to be allocated in the structure as with the fixed array but I don't want to use fixed array. Any ideas?
I've tried my best to clarify my question, hope you understand.
I want to send this structure through UDP and UDP takes continues memory buffer to send that's why I want this structure to have continuous memory.
You can not do that as the new memory is from heap/ free store and your a will be allocated on stack....
you can allocate using malloc/new a continous memory block of sizeof Test + your required size and make the pointer arr to point at the end of the Test structure.
If you need it in function scope on stack you can use alloca.
Test *a = (Test*)alloca(sizeof(Test)+yoursize);
a->arr = (char*)a+sizeof(Test)...
No you cannot have variable length arrays in C++.
So you cannot do that.
You can have a fixed length array or you can use the approach you have given.
Another approach is,
You can use placement new to place your array at an pre-allocated memory location. This memory could be on stack.
Your code don't compile. You should compile it with all warnings enabled, and improve it till you got no warnings. And are your studying C or C++? If it is C++, consider using std::vector
struct Test {
int var;
char arr[1];
};
int main()
{
std::vector<char> buf;
buf.resize(sizeof(Test) + 50);
Test *foo = reinterpret_cast<Test *>(&buf[0]);
foo->arr[40] = 'b';
}
You can pass array size to structs constructor and allocate memory for array there. Don't forget to deallocate it somewhere, e.g. in destructor:
struct Test
{
int m_var;
char *arr;
public:
Test(int var) : m_var(var)
{
arr = new char[m_var];
}
~Test()
{
delete[] arr;
arr = 0;
}
};
void main(int argc, char* argv[])
{
Test t(50);
return 0;
}
Although it hasn't been "blessed" like it has in C, most compilers will still let you use the "struct hack":
struct variable_array {
size_t size;
char data[1];
};
The "trick" is that when you allocate it, you allocate enough space for the data you want to store (but this means it must be dynamically allocated):
variable_array *a = (variable_array *) ::operator new(sizeof(*a) + data_size);
a->size = data_size;
In theory, this isn't required to work -- the compiler could do a bound-check on references to the data member to ensure you don't index beyond the one element you've defined it to hold in the struct definition. In reality, I don't know of a single compiler that does such a thing, and kind of doubt that such a thing exists. Quite a lot of C code has done things like this for years, so a compiler that did such a check just wouldn't work with a lot of real-world code, even though the standard allows it. C99 also adds this (with minutely different syntax) as an official feature of the language.
Bottom line: it's a bit clumsy, but the possibility of really not working is almost entirely theoretical.
Not truly dynamic allocation, but might solve your problem (depends on if you always know the desired size of the array at compile time)
template <size_t ArraySize>
struct Test
{
int var;
char arr[ArraySize];
}
int main()
{
Test<50> a;
}

Size of an Array.... in C/C++?

Okay so you have and array A[]... that is passed to you in some function say with the following function prototype:
void foo(int A[]);
Okay, as you know it's kind of hard to find the size of that array without knowing some sort of ending variable or knowing the size already...
Well here is the deal though. I have seem some people figure it out on a challenge problem, and I don't understand how they did it. I wasn't able to see their source code of course, that is why I am here asking.
Does anyone know how it would even be remotely possible to find the size of that array?? Maybe something like what the free() function does in C??
What do you think of this??
template<typename E, int size>
int ArrLength(E(&)[size]){return size;}
void main()
{
int arr[17];
int sizeofArray = ArrLength(arr);
}
The signature of that function is not that of a function taking an array, but rather a pointer to int. You cannot obtain the size of the array within the function, and will have to pass it as an extra argument to the function.
If you are allowed to change the signature of the function there are different alternatives:
C/C++ (simple):
void f( int *data, int size ); // function
f( array, sizeof array/sizeof array[0] ); // caller code
C++:
template <int N>
void f( int (&array)[N] ); // Inside f, size N embedded in type
f( array ); // caller code
C++ (though a dispatch):
template <int N>
void f( int (&array)[N] ) { // Dispatcher
f( array, N );
}
void f( int *array, int size ); // Actual function, as per option 1
f( array ); // Compiler processes the type as per 2
You cannot do that. Either you have a convention to signal the end of the array (e.g. that it is made of non-zero integers followed by a 0), or you transmit the size of the array (usually as an additional argument).
If you use the Boehm garbage collector (which has a lot of benefit, in particular you allocate with GC_malloc and friends but you don't care about free-ing memory explicitly), you could use the GC_size function to give you the size of a GC_malloc-ed memory zone, but standard malloc don't have this feature.
You're asking what we think of the following code:
template<typename E, int size>
int ArrLength(E(&)[size]){return size;}
void main()
{
int arr[17];
int sizeofArray = ArrLength(arr);
}
Well, void main has never been standard, neither in C nor in C++.
It's int main.
Regarding the ArrLength function, a proper implementation does not work for local types in C++98. It does work for local types by C++11 rules. But in C++11 you can write just end(a) - begin(a).
The implementation you show is not proper: it should absolutely not have int template argument. Make that a ptrdiff_t. For example, in 64-bit Windows the type int is still 32-bit.
Finally, as general advice:
Use std::vector and std::array.
One relevant benefit of this approach is that it avoid throwing away the size information, i.e. it avoids creating the problem you're asking about. There are also many other advantages. So, try it.
The first element could be a count, or the last element could be a sentinel. That's about all I can think of that could work portably.
In new code, for container-agnostic code prefer passing two iterators (or pointers in C) as a much better solution than just passing a raw array. For container-specific code use the C++ containers like vector.
No you can't. Your prototype is equivalent to
void foo(int * A);
there is obviously no size information. Also implementation dependent tricks can't help:
the array variable can be allocated on the stack or be static, so there is no information provided by malloc or friends
if allocated on the heap, a user of that function is not forced to call it with the first element of an allocation.
e.g the following are valid
int B[22];
foo(B);
int * A = new int[33];
foo(A + 25);
This is something that I would not suggest doing, however if you know the address of the beginning of the array and the address of the next variable/structure defined, you could subtract the address. Probably not a good idea though.
Probably an array allocated at compile time has information on its size in the debug information of the executable. Moreover one could search in the code for all the address corresponding to compile time allocated variables and assume the size of the array is minus the difference between its starting address and the next closest starting address of any variable.
For a dinamically allocated variable it should be possible to get its size from the heap data structures.
It is hacky and system dependant, but it is still a possible solution.
One estimate is as follows: if you have for instance an array of ints but know that they are between (stupid example) 0..80000, the first array element that's either negative or larger than 80000 is potentially right past the end of the array.
This can sometimes work because the memory right past the end of the array (I'm assuming it was dynamically allocated) won't have been initialized by the program (and thus might contain garbage values), but might still be part of the allocated pages, depending on the size of the array. In other cases it will crash or fail to provide meaningful output.
All of the other answers are probably better, i.e. you either have to pass the length of the array or terminate it with a special byte sequence.
The following method is not portable, but it works for me in VS2005:
int getSizeOfArray( int* ptr )
{
int size = 0;
void* ptrToStruct = ptr;
long adr = (long)ptrToStruct;
adr = adr - 0x10;
void* ptrToSize = (void*)adr;
size = *(int*)ptrToSize;
size /= sizeof(int);
return size;
}
This is entirely dependent of the memory model of your compiler and system so, again, it is not portable. I bet there are equivalent methods for other platforms. I would never use this in a production environment, merely stating this as an alternative.
You can use this: int n = sizeof(A) / sizeof(A[0]);