You must use the same family of malloc()/free() functions.
What your program does, I guess, is that asprintf() mallocs with one memory system and frees with another. The culprit, as Corion said, is Perl re-definining free() to use Perl's memory pools. But you are not allocating memory with Perl's (same-family as your free()) malloc. Because memory allocation in your case happens within asprintf() which is in a library which is not affected by macro definitions (the #define construct) in the calling program.
I guess, if you had the following code it would have worked (because it uses the same malloc/free family - whatever that family is):
use strict;
use warnings;
use Inline C => <<'END_OF_C';
void foo() {
char *s = (char *)malloc(100);
sprintf(s, "%s", "hello there");
printf("'%s'\n", s);
free(s);
}
END_OF_C
foo();
__END__
What can you do?: See Threads: Free to wrong pool for a possible solution.
Your question opens a new one (for me): Why doesn't Perl use perl_free() and perl_malloc() (hypothetical names) internally instead of hijacking C's function names? Somewhat relevant is my problem Inline::CPP + OpenCV = problems (edit: which still seeks a robust solution). Can Inlining not be so tightly bound to Perl's internals?
Edit: this also may be of use: Make Perl use real malloc
More Edits 12hrs after:
This C program overrides C's (or shall I say the compiler's) free() implementation. It works because the linker in this case first checks the program to resolve symbols and then resorts to external libraries (can you rely that this is common across all compilers?)
// gcc y.c
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
void free(void *ptr);
void free(void *ptr){
printf("my free called\n");
}
void foo() {
char *s = (char *)malloc(100);
sprintf(s, "%s", "hello there");
printf("'%s'\n", s);
free(s);
}
void main(void){ foo(); }
% a.out
'hello there'
my free called
And this also works (as a standalone C program - and not via Inline::C)
// gcc x.c
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#define free myfree
void myfree(void *ptr);
void myfree(void *ptr){
printf("my free called\n");
}
void foo() {
char *s = (char *)malloc(100);
sprintf(s, "%s", "hello there");
printf("'%s'\n", s);
free(s);
}
void main(void){ foo(); }
However, when inserting the first code above into Perl via Inline::C it does not work. That is, my free called is not printed. This is because Inline::C compiles inline C code into a library which resides into the _Inline dir in current dir (for my linux system). Now it depends solely on the linker (or shall I say Inline::C's Makefile) which library to look first in order to resolve free(): (1) our library just created or (2) compiler's runtime. In my system it goes first to the runtime. But the linker can be instructed to do otherwise by LD_PRELOAD for GCC/Linux. syphilis below shows how to do that. BTW: this is how I made RealPlayer to save radio streams to files as well as playing them, some time in the last century... happy hacking
bw, bliako |