Reputation: 55
I am learning about interposition. The code below is taken from a course (CMU 15-213), however, when I compile, this warning "mymalloc.c:6:29: warning: all paths through this function will call itself [-Winfinite-recursion]" occurs.
As I understand, a call to malloc in main() will instead be transferred to the call to mymalloc(). Inside mymalloc(), malloc is called again and hence, the loop occurs.
//int.c
#include <stdio.h>
#include "malloc.h"
int main() {
int *p = malloc(32);
free(p);
return (0);
}
//malloc.h
#include <stdlib.h>
#define malloc(size) mymalloc(size)
#define free(ptr) myfree(ptr)
void *mymalloc(size_t size);
void myfree(void *ptr);
//mymalloc.c
#ifdef COMPILETIME
#include <stdio.h>
#include "malloc.h"
/* malloc wrapper function */
void *mymalloc(size_t size) {
void *ptr = malloc(size);
printf("malloc(%d)=%p\n",
(int)size, ptr);
return ptr;
}
/* free wrapper function */
void myfree(void *ptr)
{
free(ptr);
printf("free(%p)\n", ptr);
}
#endif
//Makefile
CC = gcc
CFLAGS = -Wall
intc: int.c mymalloc.c
$(CC) $(CFLAGS) -DCOMPILETIME -c mymalloc.c
$(CC) $(CFLAGS) -I. -o intc int.c mymalloc.o
runc:
./intc
clean:
rm -f *~ intr intl intc *.so *.o
I tried searching but couldn't find any solution to this problem. Can anyone please help ? Thank you.
Upvotes: 5
Views: 104
Reputation: 222933
The #define malloc(size) mymalloc(size)
in malloc.h
results in the code void *ptr = malloc(size);
in mymalloc.c
being changed to void *ptr = mymalloc(size);
.
Solutions include:
void *ptr = malloc(size);
to void *ptr = (malloc)(size);
. Then, because malloc
is not followed by a parentheses, the function-like macro will have no effect. Also change free(ptr);
to (free)(ptr);
.#undef malloc
after #include "malloc.h"
in mymalloc.c
.privatemalloc.h
that declares the routines and change malloc.h
to have #include "privatemalloc.h"
instead of declaring the routines directly. Then use #include "privatemalloc.h"
in mymalloc.c
instead of #include "malloc.h"
. Continue using #include "malloc.h"
in other source files. So other source files will get the macro definitions, but mymalloc.c
will not.malloc.h
to define the macros only if some symbol, say PrivateMalloc
, is not defined. In mymalloc.c
, insert #define PrivateMalloc 1
before #include "malloc.h"
.#define mymalloc malloc
after #include "malloc.h"
in mymalloc.c
. When malloc
is later replaced by mymalloc
, this #define
will cause mymalloc
to be replaced by malloc
. Macro replacement will then stop, as recursive macro replacements are not performed. Similarly, the mymalloc
in the source code will be replaced by malloc
and then mymalloc
.Upvotes: 1
Reputation: 20460
You wrote
#include "malloc.h"
...
void *mymalloc(size_t size) {
void *ptr = malloc(size);
which after preprocessing comes out as
void *mymalloc(size_t size) {
void *ptr = mymalloc(size);
The diagnostic is accurate. Infinite recursion won't make you happy, as it will lead to stack overflow.
The #define malloc(size) mymalloc(size)
is good for user application code,
but not for the library code you're writing here.
Arrange for application and library source files
to consume appropriate macro definitions.
You might need one more header file, here.
You wrote that both int.c and mymalloc.c
should #include "malloc.h"
.
No, that cannot be.
The int.c application can consume a #define
which changes what "malloc()" means.
But the mymalloc.c library code cannot,
as it must access the original libc malloc routine.
Upvotes: 4