That all makes sense but it's seriously complex. You intend the programmer to allocate memory in their preProcessFunc from which ownership passes: their preProcessFunc -> chunk_new -> gridfs_store_buffer -> chunk_new -> their preProcessFunc -> chunk_new -> gridfs_store_buffer, and so on. Then gridfs_store_buffer ultimately frees it.

If, as you say, compression is slow, the cost of reallocating a target buffer may be relatively minor for the amount of complexity it takes to reuse the block. Consider also that the bson_append_binary call in chunk_new is reallocating memory for each block, and mongo_message_create is doing so a second time.

Another thought as you adjust the interface is that you could provide a cleanup callback, and let the programmer's custom code free the memory instead of expecting gridfs to do it.