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

Problem with ... error: invalid conversion from ‘void*’ to ‘void**’ #13

Closed brewmanz closed 7 years ago

brewmanz commented 7 years ago

I was getting

/usr/include/csptr/smart_ptr.h: In function ‘void sfree_stack(void*)’:
/usr/include/csptr/smart_ptr.h:33:23: error: invalid conversion from ‘void*’ to ‘void**’ [-fpermissive]
     void **real_ptr = ptr;
                       ^
make: *** [src/Test.o] Error 1

which I fixed by changing line void **real_ptr = ptr; to void **real_ptr = (void**)ptr;

Snaipe commented 7 years ago

The problem is innocent enough that I could include the fix, but it makes no sense on a standard point of view: in C99, void * is implicitely convertible to any other pointer type. What compiler and build flags are you using here?

brewmanz commented 7 years ago

I'm actually compiling it as C++ (g++ under Ubuntu) for unit testing some C code I'm writing, so I'd like it to be bilingual i.e. work in C and C++. I've ended up creating my own .hpp headers from the .h ones (which are now left untouched). By using '#if __cplusplus' and 'extern "C"' the *.h can probably be made bilingual, and mman.c being compiled under C (gcc).

brewmanz commented 7 years ago

By using #if __cplusplus, I've got rid of the *.hpp I created. The downside is that I've had to shift some header-only code into mman.c e.g. array_length. (Maybe there's another way, but that was simplest for me).

Snaipe commented 7 years ago

Right. Moving the inline functions from the headers to the .c is probably the best of both worlds.

Snaipe commented 7 years ago

So it turns out that casting to void ** violates aliasing rules (since the original type can pretty much be any pointer type, not just the generic void *). Using an union rather than casting avoids this problem and makes C++ happy at the same time.