challenge 呼んだのは誰?

自身を呼び出した関数(メソッド)の名前を返す関数(メソッド)を書いてください。

Ruby で表現すると、 以下のような「fooという関数を呼び出す関数」#bar、#bazがあるとき

def bar; foo end
def baz; foo end
このbar, bazの返り値が以下のようになるような関数fooを定義してください。
bar  #=> "bar"
baz  #=> "baz"

このお題は匿名の「Smalltalk からの挑戦状」を元に作成しました。 確かにこの手のリフレクションの機能が言語によってどう違うのかは興味深いところです。 リフレクションを使う問題をいくつか考えてみたいと思います。 ご投稿ありがとうございました。

Posted feedbacks - C

GNU拡張を使用しています。

$ gcc -finstrument-functions -rdynamic caller.c -ldl

のような形でコンパイルしてください。

参考 : http://alohakun.blog7.fc2.com/blog-entry-760.html
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
#define _GNU_SOURCE
#include <stdio.h>
#include <string.h>
#include <dlfcn.h>

char *caller_func_name;

__attribute__((no_instrument_function))
void __cyg_profile_func_enter(void *func_address, void *call_site)
{
    Dl_info func_info;
    Dl_info call_info;

    if (dladdr(func_address, &func_info) == 0) {
        return;
    }
    if (strcmp(func_info.dli_sname, "foo") != 0) {
        return;
    }

    if (dladdr(call_site, &call_info) == 0) {
        return;
    }
    caller_func_name = (char *)call_info.dli_sname;
}

char *foo()
{
    return caller_func_name;
}

char *bar()
{
    return foo();
}

char *baz()
{
    return foo();
}

int main()
{
    printf("%s\n", bar());
    printf("%s\n", baz());
    return 0;
}

__builtin_return_address() と libbfd の bfd_find_nearest_line() を使ってみました。 % gcc -g caller.c -lbfd でコンパイルできます。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
#include <stdio.h>
#include <stdlib.h>
#include <bfd.h>

static bfd *abfd;
static int size;
static asymbol **symbols;
static asection *section;

const char *foo()
{
    int ret;
    void *addr;
    const char *file;
    const char *func;
    unsigned int line;

    addr = __builtin_return_address(0);
    ret = bfd_find_nearest_line(abfd, section, symbols, (long)addr,
                                &file, &func, &line);
    return func;
}

const char *bar()
{
    return foo();
}

const char *baz()
{
    return foo();
}

int main()
{
    abfd = bfd_openr("/proc/self/exe", NULL);
    bfd_check_format(abfd, bfd_object);
    size = bfd_get_symtab_upper_bound(abfd);
    symbols = (asymbol**)malloc(size);
    section = bfd_get_section_by_name(abfd, ".debug_info");
    printf("%s\n", bar());
    printf("%s\n", baz());
    free(symbols);
    return 0;
}

Index

Feed

Other

Link

Pathtraq

loading...