source

포인터가 C를 가리키고 있는 함수를 판별하고 있습니까?

gigabyte 2022. 8. 21. 19:49
반응형

포인터가 C를 가리키고 있는 함수를 판별하고 있습니까?

난 작동에 대한 포인터가 있어. 어떤 서명이라도 가정해봐.그리고 같은 시그니처의 5가지 기능이 있습니다.

실행 시 이들 중 하나가 포인터에 할당되어 해당 함수가 호출됩니다.

이러한 기능에 인쇄문을 삽입하지 않고 포인터가 현재 가리키는 기능의 이름을 어떻게 알 수 있을까요?

포인터가 가리키는 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 실행 파일의 기호 테이블도 도움이 될 수 있습니다.nm(1), objdump(1), readelf(1) 참조

Linux GNU/libc 고유의 또 다른 접근법은 실행 시 dladdr(3) 함수를 사용하는 것입니다.프로그램이 훌륭하고 동적으로 연결되어 있다고 가정합니다(예:-rdynamic)는 (글로벌하게 명명된 함수의) 주소가 지정된 기호 이름과 공유 개체 경로를 검색할 수 있습니다.

물론 특정 시그니처의 기능이5개밖에 없는 경우는, 주소(그 5개의 주소와)를 비교할 수 있습니다.

에는 ( 이름이 를 들어, ( 보이는) 이름이 .static★★★★★★★★★★★★★★★★★★.

또한 일부 기능은 다음과 같습니다.dlopen 및 -ed »dlsym ( : : 부부 ( ( ( )또는 그는 실행 시 JIT-ing 프레임워크JIT-ing 프레임워크)에 의해 됩니다.libjit,gccjit,LLVM,asmjit최적화 컴파일러는 인라인 함수, 클론 작성, 테일콜 등을 할 수 있습니다.그래서 당신의 질문은 일반적으로 말이 안 될 수도 있습니다.

GCC 내의 역추적(3) 및 Ian Taylor의 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. Linux 또는 유사한 ELF 기반 시스템을 사용하고 있습니다.
  2. 동적 링크를 사용하고 있습니다.
  3. 함수가 공유 라이브러리에 있거나 사용 중입니다.-rdynamic링크할 때.
  4. 아마 당신이 하지 말아야 할 다른 많은 가정들은...

비표준 함수에 주소를 전달하면 함수의 이름을 얻을 수 있습니다.

  1. MAP 파일을 출력하도록 링커를 설정합니다.
  2. 프로그램을 일시 정지하다
  3. 포인터에 포함된 주소를 검사합니다.
  4. MAP 파일에서 주소를 검색하여 어떤 기능을 가리키고 있는지 확인합니다.

C 함수에 대한 포인터는 다른 포인터와 마찬가지로 주소입니다.디버거에서 값을 얻을 수 있습니다.포인터는 완전히 표현하기에 충분한 비트가 있는 임의의 정수형에 캐스팅하여 인쇄할 수 있습니다.포인터를 사용할 수 있는 컴파일 유닛(즉, 함수명 범위 내)은 함수 내부의 어떤 것도 건드리지 않고 포인터 값을 인쇄하거나 런타임 변수와 비교할 수 있습니다.

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

반응형