Depending on the system type the memory doesn't get released. It is rare that a malloc implementation calls sbreak with a smaller number than the previous call which is what you are looking for. If you have a program that consumes say 100 MB to do some initialization and then frees all those memory objects the program size does not shrink. However malloc will keep track of what is free and reuse it so if the growth goes up to a certain level and stays constant after that as you continue to use the application then you don't have a leak. A leak is where the memory is not freed but the references to it are lost so it keeps going for more memory from the system. In that case the memory growth will not hit a levelling off point like your application seems to have reached and instead continues to grow and either hit system imposed limits or consume all physical memory on the system and force swapping.
My web2py application starts at 22 MB of RSS and if I hit every page in a test run it grows to 48 MB and I only have configuration data in the database so small tables. I can run the server for weeks after that and will not see any further growth. If you see behaviour like that while users are still using the application you don't have a memory leak.