I never tried malloc_trim, so I don't know how well it performs its documented function.
Usually you don't worry about giving the memory back prior to the process terminating. Once the process terminates, the memory is released whether you freed it or not.
If the chunks of memory you freed were mixed with chunks of memory you didn't free, then malloc_trim cannot release the freed chunks back to the OS. Memory is allocated from the OS to malloc as large ranges of contiguous 4KB pages. Malloc subdivides that memory to fill the requests from you program. Normally malloc only returns memory to the OS when one of those contiguous ranges of 4KB pages is completely freed. I think it could return the 4KB pages at the end of such a range while keeping the ones at the beginning (assuming all the remaining used chunks are at the beginning) but I don't know if it does so.
Why do you want the memory released prior to process termination?
If you want more control over when the memory is released back to the OS, you may need to manage the original allocation from the OS yourself as well. You can allocate a multiple of 4KB from the OS the same way malloc does and if necessary, you can subdivide that into the chunks your program wants to use.
You can also get the source code to malloc and see its rules for what can be returned by malloc_trim and you might change the code to fit your needs better.