Hi Kevin, On 09/17/2014 11:27 AM, Kevin Hendricks wrote: > Hello Everyone, > > I only have a few days experience with libuv, but done a lot of reading > of uv.h, the libuv-dox, and other resources, and I've gotten both a udp > client and udp echo server running with just libuv. I understand all the > memory management is on the user, which is an area I'm pretty green in. > I'm using the current version of the master branch. >
FYI, we have better docs now! http://docs.libuv.org Also, I suggest to switch to using the v1.x branch. > Both programs are fairly simple: the client opens a socket for sending > and recieving, and while loops calls to uv_udp_send hundreds of char * > packets ("packet 1," "packet 2," etc.), individually malloc'd, to the > server. The server opens a socket for receiving, has a receive callback > that prints the message, copies that into a newly allocated buffer, > sends it back to the same addr it got it from, and frees() the received > buf->base. The client receives the echoed message, prints it, and frees > the received buffer. So far that's the strategy I've seen in all the > examples. > That sounds ok. > In both cases, that leaves the send buffers to be freed. I realized I > couldn't free them immediately after calling uv_udp_send, since that > just points to the buffer and doesn't send it right away. So I went to > free it in the send callback, but unlike the receive and read cbs, you > can't just free(buf->base). I tried free(req->bufs[0].base) similar to > the write examples, but it appears to have already been freed and set to > null in uv__udp_run_completed, before the callback is called. So that > segfaults, but free(req->bufsml[0].base) works and gives no valgrind > errors or leaks. I tried iterating over all non-null array entries in > bufsml [ int i=0; while (req->bufsml[i].base) free(req->bufsml[i].base); > ++i; ] but that gives me one valgrind error per packet ("Conditional > jump or move depends on uninitialised value(s)"). > > Am I doing this right? > Nope. libuv will copy the buffer structures you pass to uv_udp_send, but not the content. That is left up to you to free. > I haven't been able to find any samples or examples of udp echo servers > using libuv that even free memory in the send_cb other than free(req), > but as far as I can tell, they all have memory leaks. The tcp server > example in libuv-dox uses free(wr->buf.base) in its write_cb, but > valgrind reports it has a huge memory leak (maybe it didn't 8 or 9 > months ago with the version it was made for, but it does now). I don't > know what the difference between bufs and bufsml is, and don't know if I > should be concerned that I can't seem to check all members of the bufsml > array to see if I should free them, only blindly free the first. It > seems like this is harder than it should be. > The way to solve this elegantly is to embed the uv_udp_send_t structure into another one: typedef struct { uv_udp_send_t req; char *data; } udp_send_ctx_t; Then malloc one of these and pass &ctx->req to uv_udp_send. In the callback, you can do the following to get a pointer to your context: udp_send_ctx_t* ctx = container_of(req, udp_send_ctx_t, req); And then you can just free ctx->data. Cheers, -- Saúl Ibarra Corretgé bettercallsaghul.com
signature.asc
Description: OpenPGP digital signature
