apr_pool_t *pool;
char *a;
char *b;
apr_pool_create(&pool, NULL);
a = (char *) apr_palloc(pool, 10);
strcpy(a, "hello");
printf("a is %s\n", a);
apr_pool_destroy(pool);
apr_terminate();
b = (char *) apr_palloc(pool, 10);
strcpy(b, "world");
printf("b is %s\n", b);
I'm new to libapr, from the document it said
Destroy the pool. This takes similar action as apr_pool_clear() and then frees all the memory.
but actually it's not, and I can still use apr_palloc
to alloc memory from a destroyed pool? so my question is how can I actually free the memory and how can I actually destroy the pool object
You are invoking Undefined Behavior in at least two places.
I compiled on my linux (Mint a derived of Ubuntu), gcc 7.4. Your program crashes at the first apr_pool_create
because you did not invoke the appropriate initialization functions (e.g. apr_initialize
), see https://apr.apache.org/docs/apr/1.6/group__apr__library.html .
Here is the Valgrind trace:
==7158== Process terminating with default action of signal 11 (SIGSEGV)
==7158== Access not within mapped region at address 0x30
==7158== at 0x4E595F0: apr_pool_create_ex (in /usr/lib/x86_64-linux-gnu/libapr-1.so.0.6.3)
==7158== by 0x1088EB: main (in /home/user/apr/test)
=
Once that issue is fixed, you get the following program (note: I do not know whether apr_initialize
or apr_app_initialize
is appropriate for your use case).
apr_pool_t *pool;
char *a;
char *b;
apr_initialize(); // You need this or apr_app_initialize
apr_pool_create(&pool, NULL);
a = (char *) apr_palloc(pool, 10);
strcpy(a, "hello");
printf("a is %s\n", a);
apr_pool_destroy(pool);
apr_terminate();
b = (char *) apr_palloc(pool, 10);
strcpy(b, "world");
printf("b is %s\n", b);
The above code crashes in the second apr_palloc
with the following Valgrind trace because you are accessing memory that was freed most likely as a consequence of apr_pool_destroy
a is hello
==7196== Invalid read of size 8
==7196== at 0x4E58A62: apr_palloc (in /usr/lib/x86_64-linux-gnu/libapr-1.so.0.6.3)
==7196== by 0x1089AF: main (in /home/user/apr/test)
==7196== Address 0x402d080 is not stack'd, malloc'd or (recently) free'd
==7196==
Removing the last lines
b = (char *) apr_palloc(pool, 10);
strcpy(b, "world");
printf("b is %s\n", b);
allow the program to terminate correctly and Valgrind shows no errors.
So it looks like apr_pool_destroy
is working correctly, you were simply accessing memory you were not supposed to have access to and you did not experience a crash: Undefined Behavior is sneaky, your program can run for years without showing any problem, and then, one day it crashes.
For completeness, I compiled with the following command (the code was in test.c):
gcc -Wall test.c $(apr-1-config --cflags --cppflags --includes --link-ld) -o test
I suggest that you should use tools like Valgrind (http://www.valgrind.org/) to detect these kind of issues.
User Eliyahu Machluf (thanks) makes the point that APR provides facilities to debug memory allocation, from http://download.vikis.lt/manual/developer/debugging.html
Allocation Debugging
ALLOC_DEBUG
Debugging support: Define this to enable code which helps detect re-use of free()d memory and other such nonsense. The theory is simple. The FILL_BYTE (0xa5) is written over all malloc'd memory as we receive it, and is written over everything that we free up during a clear_pool. We check that blocks on the free list always have the FILL_BYTE in them, and we check during palloc() that the bytes still have FILL_BYTE in them. If you ever see garbage URLs or whatnot containing lots of 0xa5s then you know something used data that's been freed or uninitialized.