I have a macro:
#define checkAlloc(ans) checkPointer((ans), __FILE__, __LINE__);
which is used to wrap around any pointer allocation to check it is valid (used for checking memory allocations on a GPU device side).
The macro is used as follows:
SomeObject* myObj = checkAlloc(new SomeObject());
and the checkPointer function is implemented as:
inline __device__ SomeObject* checkPointer(SomeObject* pointer, char *file, int line)
{
if (pointer == nullptr)
{
// do error logging
}
return pointer;
}
Now, it is very inconvenient to create a new version of the function for each type of object I might allocate to. Templates are also not an option since I would like syntax to be clear - i.e. just putting checkAlloc(…) around each allocation rather than checkAlloc<SomeObject>(…) which is ugly and hopefully unnecessary.
Ideally I would like to change the checkPointer to be:
inline __device__ auto checkPointer(auto pointer, char *file, int line)
but I understand auto cannot be used for a function parameter yet. The GPU code supports C++14 so lambdas could be used as a potential workaround from I can read at https://stackoverflow.com/a/29945034/7283981 but I am not familiar enough with lambdas to know how to do this. Any ideas?
This is the perfect case for a template, I don't understand why you are trying to avoid it:
template < typename T >
inline __device__ T* checkPointer(T* pointer, const char *file, int line)
{
if (pointer == nullptr)
{
// do error logging
}
return pointer;
}
This is very clear and clean and you can use it as if there was an auto there:
int main(int argc, char** argv)
{
SomeObject* myObj = checkAlloc(new SomeObject());
}
As you can see, there are automatic argument deduction capabilities that don't even require any type specification...
Oh, and notice that I changed char * file to const char * file as C++11 doesn't allow conversion of literals to char *
Related
I'm currently working on a project where I often have to build linked lists of various C structs. Since I don't want to keep repeating myself setting next pointers, I wrote some helper templates, but soon found out that it falls apart if one of the next fields is a pointer-to-const.
My linked list elements look something like this:
struct WorkingElementType {
void *pNext;
/* stuff */
};
struct TroublesomeElementType {
const void *pNext;
/* stuff */
};
In reality, there are of course a lot more of these structs. My helper functions have to keep a pointer to the last element's pNext field in order to write to it when the linked list gets extended, so I went for a void **ppNext = &last->pNext. Unfortunately, that of course breaks down with TroublesomeElementType and its const void *pNext.
In the end, what I'd like to achieve is this:
void **m_ppNext;
/* In one function */
m_ppNext = &last->pNext;
/* In a different function, extending the list */
T *elementToAppend = ...;
*m_ppNext = elementToAppend;
I solved this by using a std::variant<void **, const void **> ppNext instead, but using a std::variant and std::visit just for a difference in constness that doesn't even affect the code's function feels like a bit of a waste.
That's why I'm wondering: Is it legal to use const_cast here to cast away const and stuff the const void ** into a void ** only for updating the pointed-to pointer? No const object actually gets modified, after all.
In other words: I'm not sure whether it's legal to alias const void* and void *. (My gut feeling says no, it's not legal because these are incompatible types, but I don't know for sure.)
The C++ standard in question is C++20.
Here's some simple example code:
#include <variant>
int g_i = 42;
/* This is legal */
void setIntPtr1(std::variant<int **, const int **> v) {
std::visit([](auto& p) { *p = &g_i; }, v);
}
int testNonConst1() {
int *i;
setIntPtr1(&i);
return *i;
}
int testConst1() {
const int *i;
setIntPtr1(&i);
return *i;
}
/* But I'm not sure about this */
void setIntPtr2(int **p) {
*p = &g_i;
}
int testNonConst2() {
int *i;
setIntPtr2(&i);
return *i;
}
int testConst2() {
const int *i;
setIntPtr2(const_cast<int **>(&i)); // Is this legal?
return *i;
}
On Godbolt, all of the various test... functions compile to the exact same assembly, but I don't know if testConst2 is legal C++.
I've found the following two existing questions:
Is it legal to modify any data pointer through a void **
Why isn't it legal to convert "pointer to pointer to non-const" to a "pointer to pointer to const"
However, both of them don't seem to quite answer my question. The first one deals with casting any T** to a void **, which is not what I'm doing; I'm just casting away constness. The second one asks why it's a compile error to convert a void ** to a const void **, but not whether interpreting the memory of a void * as a const void * and vice-versa (without actually overwriting a const object) would be a violation of the aliasing rules.
Yes, it is legal.
[basic.lval]/11:
If a program attempts to access the stored value of an object through a glvalue whose type is not similar to one of the following types the behavior is undefined:
the dynamic type of the object [...]
T* and const T* are similar:
Two types T1 and T2 are similar if they have cv-decompositions with the same n such that corresponding Pi components are either the same or one is "array of Ni" and the other is "array of unknown bound of", and the types denoted by U are the same.
I've begun works on a hook/event system in C++. This system is supposed to handle all sorts of events as notified by other parts of the application.
The issue I've faced is with the way I want it to run.
Generally, I want it to be so that you call a specific function with all arguments you wish to pass on, and then that function handles calling all registered hooks of that specific event, passing them on the arguments, retrieving their result values and returning it to the original caller.
Generally, this is how it was supposed to look:
CHookReturn* bInitializationStatus = Hook::Run("Initialize", gGame);
CHookReturn* bThinkSuccessful = Hook::Run("Think");
However, I ran into one issue.
I set it up in such way that the Run function in the Hook namespace, calling the Run function of the CHookData_t structure, needs to pass on varargs. I couldn't find any other way. This is how it ended up:
union CHookReturn
{
const char* m_pszValue;
int m_iValue;
float m_flValue;
double m_dlValue;
bool m_bValue;
};
struct CHookData_t
{
virtual void Run(CHookReturn* ret, ...) = 0;
};
namespace Hook
{
std::unordered_map<const char*, std::unordered_map<const char*, CHookData_t*>> umHookList;
bool Add(const char*, const char*, CHookData_t*);
bool Exists(const char*, const char*);
bool Remove(const char*, const char*);
int Count(const char*);
CHookReturn* Run(const char*, ...);
};
CPP file segment of the Hook::Run function:
CHookReturn* Hook::Run(const char* eventName, ...)
{
// FIXME: Look into alternative execution.
// This code seems more like a workaround
// than what I originally wanted it to be.
int count = Hook::Count(eventName);
CHookReturn* returnValues = new CHookReturn[count];
int c = 0;
unordered_map<const char*, CHookData_t*>::iterator itr;
unordered_map<const char*, CHookData_t*> res;
res = umHookList.at(eventName);
va_list valist;
void* args;
va_copy(args, valist);
for (itr = res.begin(); itr != res.end(); itr++)
{
CHookReturn returnData;
itr->second->Run(&returnData, args);
returnValues[c] = returnData;
++c;
}
return returnValues;
}
The above code brings up two warnings which make me question if it is a good idea to execute it in this way, as well as whether there are any alternatives I should look into.
The warnings I received were:
Warning C6001 Using uninitialized memory 'valist'.
Warning C6386 Buffer overrun while writing to 'returnValues': the writable size is 'count*8' bytes, but '16' bytes might be written.
Is there a better way to do this?
Fixing your code using va_list:
struct CHookData_t
{
virtual ~CHookData_t() {}
virtual void Run(CHookReturn* ret, va_list arg) = 0;
};
namespace Hook
{
using HooksList = std::unordered_map<
std::string,
std::unordered_map<std::string, std::unique_ptr<CHookData_t>>;
HooksList umHookList;
...
}
std::vector<CHookReturn> Hook::Run(const std::string& eventName, ....)
{
va_list valist;
va_start(valist, eventName);
auto result = Hook::RunVarg(eventName, valist);
va_end(valist);
return result;
}
std::vector<CHookReturn> Hook::RunVarg(const std::string& eventName, va_list arg)
{
int count = Hook::Count(eventName);
std::vector<CHookReturn> returnValues(count);
size_t c = 0;
for (auto& item : umHookList.at(eventName))
{
va_list arg_copy;
va_copy(arg_copy, arg);
item.second->Run(&returnValues[c], arg_copy);
va_end(arg_copy);
++c;
}
return returnValues;
}
I have no idea what are arguments of Hook::Run what va_list points to, so I can't you provide nice C++ solution.
Note that va_copy is needed inside of loop, since some compilers (don't remembered which, possibly msvc) va_list behaves like a pointer and reading arguments from it will have impact on each iteration. On other compilers va_list behaves like a value and va_copy do not change anything.
offtopic: your code is to much C, you shouldn't use const char* but std::string or std::string_view if you are using C++17, instead va_args it would be better to use variadic template or std::initializer_list, avoid raw pointers in favor of std::unique_ptr and std::shared_ptr. I've tweaked your code a bit to cover that.
Also Hook should not be a namespace, by the look of functions and variables it contains it should be a class, so you should fix it too.
Say I want to write a vector-based string (String) just for the heck of it and I want an efficient c_str() operation on it.
Seems easy enough if I simply ensure the following:
//Make sure end() points to a '\0' and that '\0' is in allocated space
void afterEachNonConst() { reserve(size()+1); *(end()) = '\0'; }
Then c_str() is "just" begin() converted to const char*:
//Return C-string
const char* c_str() const { return (const char*)(&((*this)[0])); }
(I don't know how to do it shorter; the type system seems very unwilling to convert vector<char>::const_iterator to const char* even though they should be the same).
With that I want to override every non-const non-void method (except for and reserve) with:
auto ret = vector::method(arg1, arg2, arg3, ...);
//^can't it be just something like `auto ret = super();` ??
afterEachNonConst();
return ret;
and every non-const void method with:
vector::method(arg1, arg2, arg3, ...);
afterEachNonConst();
I guess there's no reasonably elegant way to just let C++ metaprogramming do all the work (?). Can I at least get a listing of all vector method signatures into my text editor somehow?
Here's a compilable example I played with:
#include <iostream>
#include <vector>
#include <cstring>
#include <cassert>
class String : public std::vector<char> {
public:
//Initialize from c-string
String& operator=(const char* cstr) {
size_t length = strlen(cstr);
reserve(strlen(cstr) + 1);
resize(length);
for(iterator ptr = begin(); *ptr++=*cstr++; ); //this will copy the '\0' too, but only at end()
return *this;
}
String(const char* cstr){ (*this) = cstr; }
//Return C-string
const char* c_str() const { return (const char*)(&((*this)[0])); }
void push_back(char value){
vector::push_back(value);
afterEachNonConst();
};
private:
//Make sure end() points to a '\0' and that '\0' is in allocated space
void afterEachNonConst() { reserve(size()+1); *(end()) = '\0'; }
};
int main(int argc, char **argv)
{
using namespace std;
String a = "foobar";
assert(a.size() == strlen(a.c_str()));
a.push_back('_');
a.push_back('1');
assert(a.size() == strlen(a.c_str()));
cout<<a.c_str()<<endl;
return 0;
}
What you want to do cannot be done with metaprogramming. You'd need reflection as part of the language, which is IMHO sadly a missing feature of C++.
To get a list of the member functions of std::vector I'd go and open the standard, N4431 §23.3.6 and try to extract them from there.
If this is too "much work" you could also try to implement something using libclang or libTooling, though this seems by far easier as it really is. (I just had to do something similar)
Since the syntax of C++ is so extremely complicated, especially in combination with templates, parsing it is really hard. Sadly using the above libraries it's also very hard to reproduce a parsed member function declaration.
Consider a typical function that fills in a buffer:
const char* fillMyBuffer( const char* buf, int size );
Suppose this function fills the buffer with some useful data, that I want to use almost immediately after the call, and then I want to get rid of the buffer.
An efficient way of doing this is to allocate on the stack:
doStuff();
{
char myBuf[BUF_LEN];
const char* pBuf = fillMyBuffer( myBuf, BUF_LEN );
processBuffer( pBuf );
}
doOtherStuff();
So this is great for my library because the buffer is allocated on the stack - being essentially no cost to allocate, use and discard. It lasts the entire scope of the containing braces.
But I have a library where I do this pattern all the time. I'd like to automate this a little. Ideally I'd like code that looks like this:
doStuff();
{
// tricky - the returned buffer lasts the entire scope of the braces.
const char* pBuf = fillMyBufferLocal();
processBuffer( pBuf );
}
doOtherStuff();
But how to achieve this?
I did the following, which seems to work, but I know is counter to the standard:
class localBuf
{
public:
operator char* () { return &mBuf[0]; }
char mBuf[BUF_LEN];
};
#define fillMyBufferLocal() fillMyBuffer( localBuf(), BUF_LEN );
As a practical matter, the buffer is lasting on the stack during the entire lifetime of the containing braces. But the standard says that the object only has to last until the function returns. E.g. technically its just as unsafe as if I'd allocated the buffer on the stack inside the function.
Is there a safe way to achieve this?
I would generally recommend your original solution. It separates the allocation of the buffer from filling it. However, if you want to implement this fillMyBufferLocal alternative, it will have to dynamically allocate the buffer and return a pointer to it. Of course, if you return a raw pointer to dynamically allocated memory, it's very unclear that the memory should later be destroyed. Instead, return a smart pointer that encapsulates the appropriate ownership:
std::unique_ptr<char[]> fillMyBufferLocal()
{
std::unique_ptr<char[]> buffer(new char[BUF_LEN]);
// Fill it
return buffer;
}
Then you can use it like so:
auto buffer = fillMyBufferLocal();
processBuffer(buffer.get());
I do not think you should want to do this. It just makes the code harder to understand.
Automatic storage duration means that when an object goes out of scope, it is destroyed. Here you want trick the system into something that behaves like creating an object with automatic storage duration (i.e. allocates on the stack), but without respecting the corresponding rules (i.e. without being destroyed when returning from fillMyBuffer()).
The closest, meaningful thing you can do in my opinion is to use a global buffer that fillMyBuffer() can reuse, or let that buffer be a static variable inside fillMyBuffer(). For instance:
template<int BUF_LEN = 255>
const char* fill_my_buffer()
{
static char myBuf[BUF_LEN];
// Fill...
return myBuf;
}
However, I strongly suggest reconsidering your requirements, and either:
Keep using the solution you are currently adopting (i.e. transparently allocate on the stack); or
Allocate the buffer dynamically inside fillMyBuffer() and return a RAII wrapper (like a unique_ptr) to this dynamically allocated buffer.
UPDATE:
As a last, desperate attempt, you could define a macro that does the allocation and the invocation of fill_my_buffer() for you:
#define PREPARE_BUFFER(B, S) \
char buffer[S]; \
const char* B = fill_my_buffer(buffer, S);
You would then use it this way:
PREPARE_BUFFER(pBuf, 256);
processBuffer(pBuf);
You could write a class that contains a stack-based buffer and converts to char const *, e.g.
void processBuffer(char const * buffer);
char const * fillMyBuffer(char const * buffer, int size);
int const BUF_LEN = 123;
class Wrapper
{
public:
Wrapper(char const * (*fill)(char const *, int))
{
fill(&m_buffer[0], m_buffer.size());
}
operator char const * () const { return &m_buffer[0]; }
private:
std::array<char, BUF_LEN> m_buffer;
};
void foo()
{
Wrapper wrapper(fillMyBuffer);
processBuffer(wrapper);
}
I want to write a C++11 function that will only accept string literals as a parameter:
void f(const char* s) { static_assert(s is a string literal); ... }
That is:
f("foo"); // OK
char c = ...;
f(&c); // ERROR: Doesn't compile
string s = ...;
f(s.c_str()); // ERROR: Doesn't compile
etc
Is there anyway to implement this? The signature of the function is open to changes, as is adding the use of macros or any other language feature.
If this is not possible what is the closest approximation? (Can user-defined literals help in anyway?)
If not is there a platform specific way in GCC 4.7 / Linux ?
I think the closest you are going to get is this
template<int N>
void f(const char (&str)[N]){
...
}
It will compile with literals and arrays but not pointers.
An alternative might be to make a GCC extension to check at compile time that your particular function is only called with a literal string.
You could use MELT to extend GCC. MELT is a high-level domain specific language to extend the GCC compiler, and is very well suited for the kind of check you want.
Basically, you would add a new pass inside GCC and code that pass in MELT which would find every gimple which is a call to your function and check that the argument is indeed a literal string. The ex06 example on melt-examples should inspire you. Then subscribe to gcc-melt#googlegroups.com and ask your MELT specific questions there.
Of course, this is not a foolproof approach: the function could be called indirectly thru pointers, and it could e.g. have a partial literal string, e.g. f("hello world I am here"+(i%4)) is conceptually a call with some literal string (e.g. in .rodata segment), but not in the generated code nor in the gimple.
I use this :
// these are used to force constant, literal strings in sqfish binding names
// which allows to store/copy just the pointer without having to manage
// allocations and memory copies
struct _literalstring
{
// these functions are just for easy usage... not needed
// the struct can be empty
bool equal(_literalstring const *other) { return !strcmp((const char *)this, (const char *)other); }
bool equal(const char *other) { return !strcmp((const char *)this, other); }
const char *str(void) { return (const char *)this; }
bool empty(void) { return *(const char *)this == 0; }
};
typedef _literalstring *LITSTR;
constexpr LITSTR operator "" _LIT(const char *s, size_t) {
return (LITSTR)s;
}
Then you just declare your function like this :
void myFunc(LITSTR str)
{
printf("%s\n", str->str());
printf("%s\n", (const char *)str);
const char *aVar = str->str();
const char *another = (const char *)str;
}
And you call it like this:
myFunc("some text"_LIT);
If you do something like this:
myFunc("some text");
myFunc(aTextVariable);
you get a compiler error.