微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

如果我的函数来自另一个.c,我是否可以从调用它的位置知道文件和函数的名称?

如何解决如果我的函数来自另一个.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 举报,一经查实,本站将立刻删除。