programing

C에서 포인터가 가리키는 함수를 결정합니까?

copysource 2021. 1. 16. 20:38
반응형

C에서 포인터가 가리키는 함수를 결정합니까?


기능에 대한 포인터가 있으며 서명을 가정합니다. 그리고 나는 동일한 서명을 가진 5 개의 다른 기능을 가지고 있습니다.

런타임에 그들 중 하나가 포인터에 할당되고 해당 함수가 호출됩니다.

이러한 함수에 print 문을 삽입하지 않고 포인터가 현재 가리키는 함수의 이름을 어떻게 알 수 있습니까?


포인터가 가리키는 5 가지 기능 중 어떤 것을 확인해야합니다.

if (func_ptr == my_function1) {
    puts("func_ptr points to my_function1");
} else if (func_ptr == my_function2) {
    puts("func_ptr points to my_function2");
} else if (func_ptr == my_function3) {
    puts("func_ptr points to my_function3");
} ... 

이것이 필요한 일반적인 패턴이라면 함수 포인터 대신 구조체 테이블을 사용하십시오.

typedef void (*my_func)(int);

struct Function {
    my_func func;
    const char *func_name;
};

#define FUNC_ENTRY(function) {function, #function}

const Function func_table[] = {
    FUNC_ENTRY(function1),
    FUNC_ENTRY(function2),
    FUNC_ENTRY(function3),
    FUNC_ENTRY(function4),
    FUNC_ENTRY(function5)
}

struct Function *func = &func_table[3]; //instead of func_ptr = function4;

printf("Calling function %s\n", func->func_name);
func ->func(44); //instead of func_ptr(44);

일반적으로 C에서는 프로그래머가 사용할 수 없습니다.

디버그 기호 등을 사용하여 시스템에 특정한 방법이있을 수 있지만 프로그램이 정상적으로 작동하기 위해 이러한 존재에 의존하고 싶지는 않을 것입니다.

그러나 물론 포인터의 값을 다른 값과 비교할 수 있습니다.

if (ptr_to_function == some_function)
    printf("Function pointer now points to some_function!\n");

함수 이름은 런타임에 사용할 수 없습니다.

C는 반사적 언어 가 아닙니다 .

이름으로 키가 지정된 함수 포인터 테이블을 유지하거나 이름 을 리턴하는 각 함수를 호출 하는 모드를 제공하십시오 .


디버거는이를 알려줄 수 있습니다 (즉, 주소가 주어진 함수 이름).

스트리핑되지 않은 ELF 실행 파일 의 기호 테이블 도 도움이 될 수 있습니다. 참조 나노 미터 (1) , objdump를 (1) , readelf (1)

또 다른 Linux GNU / libc 특정 접근 방식은 런타임에 dladdr (3) 함수를 사용하는 것입니다. 프로그램이 멋지고 동적으로 연결되어 있다고 가정하면 (예 :) -rdynamic심볼 이름과 (전역 적으로 명명 된 함수의) 주소가 주어진 공유 객체 경로를 찾을 수 있습니다.

물론 주어진 서명의 기능이 5 개뿐이라면 주소를 5 개 주소와 비교할 수 있습니다.

일부 함수에는 ((전역 적으로 볼 수있는) 이름이 없습니다 (예 : static함수).

그리고 일부 함수는 dlopen-ed 및 dlsym-ed 가 될 수 있습니다 (예 : 플러그인 내부). 또는 자신의 코드 일부 JIT - 보내고 프레임 워크에 의해 런타임에 합성 된 것이다 수 ( libjit, gccjit, LLVM, asmjit). 그리고 최적화 컴파일러 는 함수를 인라인하고 복제하고 꼬리 호출 하는 등의 작업을 수행 할 수 있습니다 (그리고 수행합니다!) . 따라서 귀하의 질문은 일반적으로 이해가되지 않을 수 있습니다.

backtrace (3) 및 Ian Taylor의 GCC 내부 libbacktrace 도 참조하십시오 .

그러나 일반적으로 당신의 탐구는 불가능합니다. 신뢰할 수있는 방식으로 이러한 반사 정보가 정말로 필요한 경우 빌드 중에 일부 코드를 생성 하여 직접 관리하십시오 ( 예 : Pitrat의 CAIA 시스템 또는 내 MELT 시스템 참조).


함수 포인터가 가리키는 위치를 파악하려면 프로그램에서 추적해야합니다. 가장 일반적인 것은 함수 포인터의 배열을 선언하고이 배열의 인덱스로 int 변수를 사용하는 것입니다.

즉, 현재는 __func__식별자 를 사용하여 현재 실행중인 함수를 런타임에서 알 수 있습니다 .

#include <stdio.h>

typedef const char* func_t (void);

const char* foo (void)
{
  // do foo stuff
  return __func__;
}

const char* bar (void)
{
  // do bar stuff
  return __func__;
}

int main (void)
{
  func_t* fptr;

  fptr = foo;
  printf("%s executed\n", fptr());

  fptr = bar;
  printf("%s executed\n", fptr());

  return 0;
}

산출:

foo executed
bar executed

전혀 아닙니다-함수의 상징적 인 이름은 컴파일 후에 사라집니다. 반사 언어와 달리 C는 프로그래머가 구문 요소의 이름을 어떻게 지정했는지 알지 못합니다. 특히 컴파일 후 이름에 의한 "함수 조회"가 없습니다.

물론 현재 포인터를 비교할 수있는 함수 포인터의 "데이터베이스"(예 : 배열)를 가질 수 있습니다.


이것은 완전히 끔찍하고 이식성이 없지만 다음을 가정합니다.

  1. You're on Linux or some similar, ELF-based system.
  2. You're using dynamic linking.
  3. The function is in a shared library or you used -rdynamic when linking.
  4. Probably a lot of other assumptions you shouldn't be making...

You can obtain the name of a function by passing its address to the nonstandard dladdr function.


  1. set your linker to output a MAP file.
  2. pause the program
  3. inspect the address contained in the pointer.
  4. look up the address in the MAP file to find out which function is being pointed to.

A pointer to a C function is an address, like any pointer. You can get the value from a debugger. You can cast the pointer to any integer type with enough bits to express it completely, and print it. Any compilation unit that can use the pointer, ie, has the function name in scope, can print the pointer values or compare them to a runtime variable, without touching anything inside the functions themselves.

ReferenceURL : https://stackoverflow.com/questions/33215374/determining-to-which-function-a-pointer-is-pointing-in-c

반응형