如何解决如果我的函数来自另一个.c,我是否可以从调用它的位置知道文件和函数的名称?
我正在开发一个库,我想知道一些有关我提供的功能之一的调用者的数据。特别是,我需要知道文件名,函数名和调用函数(重新定义的malloc)的行。
编辑:这是一个最小的工作示例,在此示例中,我可以检测到用户何时调用malloc并将其“重定向”到我自己的malloc函数:
main.c:
#include <stdio.h>
#include <stdlib.h>
#include "myLib.h"
int main(){
printf("Inside main,asking for memory\n");
int *p = malloc(sizeof(int));
*p = 3;
free(p);
return 0;
}
myLib.c:
#include "myLib.h"
void * myAlloc (size_t size){
void * p = NULL;
fprintf(stderr,"Inside my own malloc\n");
p = (malloc)(size);
return p;
}
#undef malloc
#define malloc(size) myAlloc(size)
myLib.h:
#ifndef MYLIB_H
#define MYLIB_H
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#define malloc(size) myAlloc(size)
void * myAlloc(size_t size);
#endif
我尝试使用_ FILE _ _ _ func _和_ LINE _关键字,但是由于该原因,我无法使其正常工作在另一个模块中。
解决方法
您可以:
//mylib.h
#ifndef MYLIB_H
#define MYLIB_H
#include <stdlib.h>
// replace malloc in case it's already a macro
#ifdef malloc
#undef malloc
#endif
// I believe that from the standards point of view,this is undefined behavior
#define malloc(size) my_alloc(size,__FILE__,__LINE__,__func__)
#ifdef __GNUC__
// Allow compiler to do static checking.
__attribute__((__alloc_size__(1),__malloc__))
#endif
void *my_alloc(size_t size,const char *file,int line,const char *func);
// ^^^^^^^^ I do not like camelCase case - one snake case to rule them all.
#endif
// mylib.c
#include "mylib.h" // do not ever mix uppercase and lowercase in filenames
#undef malloc // undef malloc so we don't call ourselves recursively
#include <stdio.h>
void *my_alloc(size_t size,const char *func){
fprintf(stderr,"Och my god,you wouldn't believe it!\n"
"A function %s in file %s at line %d called malloc!\n",func,file,line);
return malloc(size);
}
您可能还会看到assert does it的情况。如果您打算使用glibc,请阅读glibc docs replacing malloc。
您发现用户仍然可以进行(malloc)(size)
cicumvent宏扩展。您可以这样做:
void *my_alloc(size_t size,const char *func);
static inline void *MY_ALLOC(size_t size) {
return my_alloc(size,NULL,NULL);
}
#define MY_ALLOC(size) my_alloc(size,__func__)
// if called with `malloc()` then MY_ALLOC is expanded
// if called as `(malloc)`,then just expands to MY_ALLOC.
#define malloc MY_ALLOC
int main() {
malloc(10); // calls my_alloc(10,"main.c",62,"main");
(malloc)(20); // calls my_alloc(20,NULL);
}
,
GLIBC为malloc(),free()...定义了隐藏符号,称为__libc_malloc(),__libc_free()...
因此,您可以极大地简化调试宏。
在 m.h 中,定义以下内容:
#if DEBUG_LEVEL > 0
extern void *__libc_malloc (size_t bytes);
extern void *myMalloc(size_t size,const char *filename,const char *funcname,int line);
#define malloc(size) myMalloc(size,__FUNCTION__,__LINE__)
#endif
然后,您可以编写一个定义myMalloc()的程序,如下所示(例如,文件名为 m.c ):
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "m.h"
#if DEBUG_LEVEL > 0
void *myMalloc(
size_t size,int line
) {
fprintf(stderr,"malloc(%zu) called from %s/%s()#%d\n",size,filename,funcname,line);
return __libc_malloc(size);
}
#endif
char *dup_str(char *string) {
char *str = malloc(strlen(string) + 1);
strcpy(str,string);
return str;
}
int main(int ac,char *av[]) {
char *str;
if (av[1]) {
str = dup_str(av[1]);
} else {
str = dup_str("NULL");
}
printf("String = '%s'\n",str);
free(str);
return 0;
}
在非调试模式下编译此示例程序时:
$ gcc m.c -DDEBUG_LEVEL=0
$ ./a.out azerty
String = 'azerty'
在调试模式下编译程序时:
$ gcc m.c -DDEBUG_LEVEL=1
$ ./a.out azerty
malloc(7) called from m.c/dup_str()#27
String = 'azerty'
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。