IMO, the final authority for correctness is the API page at http://api.zeromq.org/3-2:zmq-recv. Even though your code works - and probably will continue work with new versions of ZeroMQ - you are not following the rules.
Argument 2 (buf) is a reference to a buffer. There is no mention of any special case where you can provide NULL. Fortunately if the received payload is larger than argument 3 (len), then the data will be truncated. Which means you can provide a really small buffer. It can be stack based to avoid any memory allocation cost as shown below.
void zmq_drain_multipart(void *sock)
{
int more;
size_t size = sizeof(int);
zmq_getsockopt(sock, ZMQ_RCVMORE, &more, &size);
while (more)
{
char buf[32];
zmq_recv(sock, buf, 32, 0);
zmq_getsockopt(sock, ZMQ_RCVMORE, &more, &size);
}
}
This also has a minor advantage when things go wrong. When stepping through a debugger, the above code will let you examine the first few bytes of each fragment that is being received and drained.