c/c++语言开发共享在C中查找函数调用者

嘿所有,我只是想知道是否有可能获得在函数内运行的程序的名称?

这是一个例子:

我打电话说: ./ runProgram

main() { A(); } function A() { // Possible to retrieve "runProgram" if I cannot use main's argc(argv) constants?? } 

    编译器依赖,所以:

     $ cc --version i686-apple-darwin10-gcc-4.2.1 (GCC) 4.2.1 (Apple Inc. build 5646) 

    制作节目

     $ more xc int main(int argc, char *argv[]) { printf("program: %sn", argv[0]); foo(); } int foo() { } $ make x cc xc -ox xc: In function 'main': xc:2: warning: incompatible implicit declaration of built-in function 'printf' $ ./x program: ./x 

    获取argc / v变量的全局名称

     $ nm ./x 0000000100000efe s stub helpers 0000000100001048 D _NXArgc 0000000100001050 D _NXArgv 0000000100001060 D ___progname 0000000100000000 A __mh_execute_header 0000000100001058 D _environ U _exit 0000000100000eeb T _foo 0000000100000eb8 T _main U _printf 0000000100001020 s _pvars U dyld_stub_binder 0000000100000e7c T start 

    添加全局名称,声明为extern,并考虑到重整。

     $ more x2.c int main(int argc, char *argv[]) { printf("program: %sn", argv[0]); foo(); } int foo() { extern char **NXArgv; printf("in foo: %sn", NXArgv[0]); } 

    跑恐怖

     $ make x2 cc x2.c -o x2 x2.c: In function 'main': x2.c:2: warning: incompatible implicit declaration of built-in function 'printf' x2.c: In function 'foo': x2.c:9: warning: incompatible implicit declaration of built-in function 'printf' $ ./x2 program: ./x2 in foo: ./x2 

    请不要告诉我的妈妈。

    GetCurrentProcessId(); 将为您提供当前的进程ID。 从那里,您需要将其与当前运行的进程名称进行匹配。

    有关步骤2的更多信息,请参阅此代码项目文章 。

    这在“标准C”中是不可能的。 如果你是jiggery-pokery,你可以查看程序的环境变量来查找命令行。 以下适用于FreeBSD:

     /* _ _ _ (_|_) __ _ __ _ ___ _ __ _ _ _ __ ___ | | _____ _ __ _ _ | | |/ _` |/ _` |/ _  '__| | | |_____| '_  / _ | |/ / _  '__| | | | | | | (_| | (_| | __/ | | |_| |_____| |_) | (_) | < __/ | | |_| | _/ |_|__, |__, |___|_| __, | | .__/ ___/|_|____|_| __, | |__/ |___/ |___/ |___/ |_| |___/ */ #include  extern char ** environ; void A () { char ** p; for (p = environ; *p; p++) printf ("%sn", * p); } int main () { A (); } 

    但是,在C本身中,与JavaScript和Perl等语言不同,没有办法偷看堆栈并找出谁给你打电话。

    通常,您要做的是使用全局变量。

     const char *g_argv0; void A() { printf("program is %sn", g_argv0); } int main(int argc, char *argv[]) { g_argv0 = argv[0]; A(); return 0; } 

    对于这个想法的微不足道的变化,如果需要,可以将整个命令行数组保存在全局变量中。

    程序名称将存储在argv [0]中。

    请注意,这不一定与首先想到的文件名相同。 例如,如果有程序的符号链接,并且使用该名称调用程序,那么这将存储在argv [0]中。

    因此,例如,您可以使用以下程序:

     #include  int main(int argc, char **argv) { printf("%sn", argv[0]); return 0; } 

    这会产生以下行为:

     $ cc tc $ ./a.out ./a.out $ ln -s a.out foo $ ./foo ./foo 

    请注意,在名称到达程序之前发生shell替换:

     $ alias bar=./foo $ bar ./foo 

     int main(int argc, char *argv[]) { printf("program: %sn", argv[0]); //pass argv[0] to the desired function. } 

    使用Windows,您可以使用GetCommandLine函数。 也许Linux有一个类似的API。

    您可以找到导致您的进程从getpid执行的完整命令,但有关如何执行此操作的具体信息因平台而异。

    无视上面的代码是可怕的C并且实际上更接近伪代码的事实……

    不可以。您可以将argv[0]分配给全局变量,以便可以通过其他地方的代码访问它,也可以将其作为参数传递。 我怀疑是否有一种标准的C方式来进入另一个函数的局部变量。 这听起来像是一个相当糟糕的主意(以我的拙见)。

    使用全局:

     char *progname; void A(void) { // do stuff with progname } int main(int argc, char **argv) { progname = *argv; A(); return 0; } 

    作为论点传递:

     void A(char *progname) { // do stuff with progname } int main(int argc, char **argv) { A(*argv); return 0; } 

    编辑:我们大多数人错过了它,因为它在评论中隐藏着相当具体,但你说你不能使用argv 。 我只想指出,任何不使用argv解决方案都是不可移植的,最好的答案是继续使用argv因为它是由标准给你的,并且没有任何可能的原因你不能使用argv 。 这就像说“如何在不使用stdin文件句柄的情况下将文本打印到控制台?” 你可以做到,但你为什么要这样做?

    在Linux下,您可以查看/proc/self/cmdline (或者使用getpid()查找进程ID,然后查看/proc/[pid]/cmdline ;前者是后者的快捷方式。

    x86上的C调用约定具有这样的堆栈帧布局。

                                     ...                     * 0x4000000c = 0x60000000(第二个参数)                     * 0x40000008 = 0x00000001(第一个参数)                     * 0x40000004 = 0x20000000(返回地址)  *(旧%esp =%ebp = 0x40000000)= 0x3ffffff0(旧%ebp)                     * 0x3ffffffc = 0x00000000(第一局)                     * 0x3ffffff8 = 0x00000000(第二局部)                                 ...             *(%esp = 0x3ffffff0)(帧结束) 

    因此,要获得调用者的参数,请从(%ebp)并向上走。 GCC的__builtin_frame_address扩展有助于第一步。

     A() { void **ebp = __builtin_frame_address(1); void **ra = ebp + 1; int *argc = ra + 1; char ***argv = argc + 1; int i; for (i = 0; i < *argc; i++) printf("[%d] %sn", i, (*argv)[i]); } a(int argc, char **argv) { A(); } main(int argc, char **argv) { a(argc, argv); } 

    不幸的是, main有点特殊,所以直接从main调用A可能会崩溃。

    此外,为了节省工作并释放寄存器,优化编译器可能会省略此标准堆栈帧设置,这也会导致失败。

      以上就是c/c++开发分享在C中查找函数调用者相关内容,想了解更多C/C++开发(异常处理)及C/C++游戏开发关注计算机技术网(www.ctvol.com)!)。

      本文来自网络收集,不代表计算机技术网立场,如涉及侵权请联系管理员删除。

      ctvol管理联系方式QQ:251552304

      本文章地址:https://www.ctvol.com/c-cdevelopment/549617.html

      (0)
      上一篇 2021年1月14日
      下一篇 2021年1月14日

      精彩推荐