Grant Edwards said:
In Unix there is no way to release heap memory (which is what you're
talking about) back to the OS except for terminating the process.
That's not quite true. The man page for BRK(2) (at least on the Linux
box I happen to have handy) says:
"brk() and sbrk() change the location of the program break, which
defines the end of the process's data segment (i.e., the program
break is the first location after the end of the uninitialized data
segment). Increasing the program break has the effect of allocating
memory to the process; decreasing the break deallocates memory."
So, in theory, it's possible. I just ran this C program:
#include <unistd.h>
#include <time.h>
int main(int argc, char** argv) {
struct timespec t;
t.tv_sec = 10;
t.tv_nsec = 0;
nanosleep(&t, NULL);
sbrk(500 * 1024 * 1024);
nanosleep(&t, NULL);
sbrk(-500 * 1024 * 1024);
nanosleep(&t, NULL);
}
while watching the process with ps. I could see the process appear and
for the first 10 seconds it had a VSZ of 4156. Then, for the next 10
seconds, the VSZ was 516156, then it went back down to 4156.
$ while sleep 1; do ps augx | grep a.out | grep -v grep; done
roy 6657 0.0 0.0 4156 356 pts/10 S+ 19:56 0:00 ./a.out
roy 6657 0.0 0.0 4156 356 pts/10 S+ 19:56 0:00 ./a.out
roy 6657 0.0 0.0 4156 356 pts/10 S+ 19:56 0:00 ./a.out
roy 6657 0.0 0.0 4156 356 pts/10 S+ 19:56 0:00 ./a.out
roy 6657 0.0 0.0 4156 356 pts/10 S+ 19:56 0:00 ./a.out
roy 6657 0.0 0.0 4156 356 pts/10 S+ 19:56 0:00 ./a.out
roy 6657 0.0 0.0 4156 356 pts/10 S+ 19:56 0:00 ./a.out
roy 6657 0.0 0.0 4156 356 pts/10 S+ 19:56 0:00 ./a.out
roy 6657 0.0 0.0 4156 356 pts/10 S+ 19:56 0:00 ./a.out
roy 6657 0.0 0.0 4156 356 pts/10 S+ 19:56 0:00 ./a.out
roy 6657 0.0 0.0 516156 356 pts/10 S+ 19:56 0:00 ./a.out
roy 6657 0.0 0.0 516156 356 pts/10 S+ 19:56 0:00 ./a.out
roy 6657 0.0 0.0 516156 356 pts/10 S+ 19:56 0:00 ./a.out
roy 6657 0.0 0.0 516156 356 pts/10 S+ 19:56 0:00 ./a.out
roy 6657 0.0 0.0 516156 356 pts/10 S+ 19:56 0:00 ./a.out
roy 6657 0.0 0.0 516156 356 pts/10 S+ 19:56 0:00 ./a.out
roy 6657 0.0 0.0 516156 356 pts/10 S+ 19:56 0:00 ./a.out
roy 6657 0.0 0.0 516156 356 pts/10 S+ 19:56 0:00 ./a.out
roy 6657 0.0 0.0 516156 356 pts/10 S+ 19:56 0:00 ./a.out
roy 6657 0.0 0.0 4156 356 pts/10 S+ 19:56 0:00 ./a.out
roy 6657 0.0 0.0 4156 356 pts/10 S+ 19:56 0:00 ./a.out
roy 6657 0.0 0.0 4156 356 pts/10 S+ 19:56 0:00 ./a.out
roy 6657 0.0 0.0 4156 356 pts/10 S+ 19:56 0:00 ./a.out
roy 6657 0.0 0.0 4156 356 pts/10 S+ 19:56 0:00 ./a.out
roy 6657 0.0 0.0 4156 356 pts/10 S+ 19:56 0:00 ./a.out
roy 6657 0.0 0.0 4156 356 pts/10 S+ 19:56 0:00 ./a.out
roy 6657 0.0 0.0 4156 356 pts/10 S+ 19:56 0:00 ./a.out
roy 6657 0.0 0.0 4156 356 pts/10 S+ 19:56 0:00 ./a.out
roy 6657 0.0 0.0 4156 356 pts/10 S+ 19:56 0:00 ./a.out
In practice, unless you go to extraordinary lengths (i.e. avoid almost
all of the standard C library), the break is going to be managed by
malloc(), and malloc() provides no way to give memory back (insert
handwave here about mmap, and another handwave about various versions of
malloc). But, that's due to the way malloc() manages its arena, not
anything fundamental about how Unix works.