Snaipe / libcsptr

Smart pointers for the (GNU) C programming language
https://snai.pe/c/c-smart-pointers/
MIT License
1.57k stars 143 forks source link

Unable to create dynamic arrays (i.e. size not known at compile time) #14

Open brewmanz opened 7 years ago

brewmanz commented 7 years ago

I can write code like smart char* pStrA = (char*)smart_arr(UNIQUE, char, 64); but not smart char* pStrA = (char*)smart_arr(UNIQUE, char, myArraySize); Can you give me any ideas what I need to do? Either with using csptr, or changing it. Thanks

Snaipe commented 7 years ago

Mind that when using a C++ compiler, calls to smalloc() become invalid since it uses compound literals under the cover, which is valid C99 but invalid C++ (I think gcc/clang allows it as an extension but the value has static storage rather than automatic storage, so you can't put non-constant expressions in its initializer). You'd have to explicitely #undef smalloc to remove the syntactic sugar and for each call populate the s_smalloc_args structure yourself, then pass it to the real smalloc function.

Using the API really wasn't designed for use in C++; if you can, try wrapping calls to smalloc in regular C functions compiled with a GNU99+ compiler. Another possibility if you're using C++11 and later would be to re-define the smalloc macro to use a lambda to set & call like described above:

#undef smalloc
#define smalloc(...) ([&]() { s_smalloc_struct p { 0, __VA_ARGS__ }; return smalloc(&p); })()
brewmanz commented 7 years ago

I don't quite follow what you are saying; it doesn't follow from what I wrote. This is not using C++; it is using the gcc C compiler with C99 set. How do I allocate dynamic (not known at compile time) arrays? When I compile the following code

    size_t mySize = 999;
    smart char* pRes1 = (smart char*)smart_arr(UNIQUE, char, 999); // ok
    smart char* pRes2 = (smart char*)smart_arr(UNIQUE, char, mySize); // not ok

it fails with

../DumpBufferBits.c:8:35: error: variable-sized object may not be initialized
  smart char* pRes2 = (smart char*)smart_arr(UNIQUE, char, mySize);

Do you get a similar error result with your C compiler, or does it work?

Snaipe commented 7 years ago

Oh, sorry, for some reason I thought this was related to your other issue.

Looking again at how I implemented the sugar for smart_arr, this seems to be a limitation -- the macro initializes a structure with an element of type T[Len], and is thus invalid when Len is a non-constant expression. Unfortunately, I don't see a way to make smart_arr work with this as putting a T[Len] value in the struct is the only way to both guarantee zero-initialization and make the initial value optional.

So, for this specific case you need to call smalloc(sizeof (char), mySize, UNIQUE) and initialize the returned value yourself.