In CL/cl.hpp, line 1222, there is a constructor Wrapper::Wrapper(const cl_type &obj) that is used to wrap a C-style object into a C++ style object. Unlike the copy constructor, it does not call retain(). However, the destructor always calls release() for non-null objects. This asymmetry leads to subtile bugs that causes random crashes for which the culprit is hard to find.
Consider for example, a function like:
void eventCompleteCallBack(cl_event ev, cl_int status, void *arg)
{
cl::Event event(ev); // wrap C-style object into C++ style object
... // use event as C++-style object
// destructor of cl::Event calls release() while retain() was never invoked
}
The fact that event callback functions return a cl_event instead of a cl::Event is already not really elegant, but the obvious solution to wrap the cl_event object into a cl::Event as done above silently corrupts memory, as the destructor of cl::Event implicitly calls release() while retain() was never invoked.
Likewise, Wrapper<cl_type>& operator = (const cl_type &rhs) does not call retain().
I realise that simply adding “if (object_ != NULL) { retain(); }” causes other problems, as some of the internal code within cl.hpp seems to rely on this behavior, but I would be happy if this unexpected behavior could be fixed in the next release of CL/cl.hpp.