Hey all,
@stevebronder and I have been trying to figure out part of the OpenCL 1.2 async API for a little while now. Many of the commands, such as enqueueWriteBuffer, take a pointer to a collection of events that the command should wait for,
cl_int cl::CommandQueue::enqueueWriteBuffer(
const Buffer& buffer,
cl_bool blocking_write,
::size_t offset,
::size_t size,
const void * ptr,
const VECTOR_CLASS<Event> * events = NULL,
Event * event = NULL)
And I’m a little worried about that pointer because we can’t find in the spec anywhere exactly what they do with that (and the underlying implementations don’t seem to be open source). We would love it if they copied the events as soon as you pass them in, but they could technically try to access that pointer later, after the call to enqueueWriteBuffer
has returned.
I wrote a little sample program that tries to stress this out and ran it with clang’s AddressSanitizer, and it came out clean (well, it says my OpenCL implementation has a variety of unrelated memory leaks but they don’t seem important).
Here’s that code, most of which is copied from some tutorial. The important case is on line 57 in schedWriteEvents
, which creates a std::vectorcl::Event at local scope and passes that in to enqueueWriteBuffer
. If they copy things immediately, this should be fine (and it seems to work with my local implementation of OpenCL), but obviously if it keeps that pointer past the return of this function and the subsequent destruction of the vector of events, then it would be accessing freed memory.
Anyone know if this kind of API is common? I suspect it’s just a relic of wrapping the underlying C API and it probably will do the correct thing because it’s difficult for me to imagine how we would be supposed to manage the lifetimes of those collections otherwise (I mean, it’s possible, but pretty nasty).