【问题标题】:how to find code-functions that called before c++ main如何找到在 c++ main 之前调用的代码函数
【发布时间】:2019-09-29 09:13:49
【问题描述】:

如何找到在 c++ main 之前调用的代码函数?我试图找出调用了哪些函数,以便通过函数初始化静态变量,从而在 main.js 之前执行。

【问题讨论】:

  • 你使用的是什么环境?
  • 您可能想要使用调试器并在您感兴趣的静态变量上设置数据断点。
  • 在 linux:g++ 上,在 Windows 上:microsoft visual studio
  • @Matteo Italia:实际上我正在尝试查找以这种方式初始化的静态变量
  • @A.Papadopoulos 我更新了我的答案,我认为找到静态/全局变量会很好。如果您有相同的源代码(跨平台代码),您可以使用 linux 脚本实用程序来调用 nm/objdump 来完成您需要的事情。我真的认为这是一个很好的尝试。

标签: c++


【解决方案1】:

在 GCC 情况下,您有:

__CTOR_LIST__ (list of initialization functions called - pointers) 
__DTOR_LIST__ (list of functions called for cleanup)

它们由编译器为每个翻译单元(C/C++ 文件)自动生成。

您可以找到有关此here 的更多信息。对于其他编译器,这必须是相似的,但您可以使用 objdumpnm 等实用程序“猜测”它(当然,对于您的编译器套件)。

我们在使用 g++ 的自定义嵌入式平台上手动调用了这些指针函数 ( void (*func)(void) )。


我看到您对查找静态/全局变量感兴趣。

对于这个任务,你真的可以使用一些工具,比如 objdump 和 nm(前面提到过)。首先创建 2-3 个测试文件(并编译它们以获得 .o/.obj)并查看这些工具如何看到静态/全局变量(在 .obj/.o 文件中。一旦看到,您就可以使用脚本浏览所有 .obj/.o 文件并列出静态/全局变量。

【讨论】:

  • 我已经尝试过了,但我无法找到其中哪些(数千个变量)被函数调用初始化
  • @A.Papadopoulos .o文件中未初始化的变量和已初始化的变量难道没有区别吗?
  • @A.Papadopoulos 看到这个答案:stackoverflow.com/questions/17159666/… 初始化变量和未初始化变量之间确实存在差异。这应该可以帮助您调整脚本以查看在全局/静态定义时已分配(或未分配)值的变量。
  • @A.Papadopoulos 您应该在 .o 文件中针对您的特定情况进行一些测试,看看是否与 objdump/nm 有差异。
  • 由函数调用初始化的全局静态变量和未初始化的全局静态变量是未初始化数据部分(称为 BSS)中的符号,并被 nm 列为“B”(全局范围)或“ b"(文件范围)
【解决方案2】:

这是非常特定于编译器和/或平台的。事实上,我只是花了一天的大部分时间来追查两个不同编译器处理此问题的方式之间的不兼容性。

试试你的编译器文档,特别是 C++ 运行时初始化部分。

【讨论】:

    【解决方案3】:

    在运行时最好的方法是找到 C++ 运行时的启动文件。这是在 main 之前执行的代码。它负责系统初始化,包括初始化内存、静态变量和调用全局对象的构造函数。在 MS VC++ 中,这个文件是 crt0.c。您可以通过在 main 处设置断点然后查看堆栈跟踪来找到它。

    【讨论】:

      【解决方案4】:

      我过去所做的,现在从 C++ 项目的第一天开始,就是删除所有全局变量。此时唯一的方法是使用可以从main() 调用的初始化函数创建所有内容(当然,您可以通过创建许多不同的初始化函数来分解初始化过程,实际上强烈建议这样做。)

      如果您被一个项目困住,无法对代码进行如此深入的更改,那么您必须在这里和那里手动调整一些东西,例如文件链接的顺序,这是一个非常弱的方法为了保证正确的初始化(虽然我在编写自己的链接器时使用了该技术,但实际上我可以在初始化函数中查找一个数字,让它们按该数字排序。)

      一种解决方案是使用覆盖工具。这将显示所有被调用的函数。对于 C++,这意味着您将看到所有被调用的构造函数,从而找到相应的全局变量。显然,A 类使用 B 类,B 可能没有任何全局变量……这仍然需要大量工作。在这种情况下,您希望在到达main() 后立即返回:

      int main()
      {
           return;
           ...your other code...
      }
      

      这是暂时的,直到您获得所需的列表。在 GNU C++ 套件中运行覆盖的工具被命名为gcov。如果你搜索这些,你会很容易找到很多例子。

      再次,正如 Joe Z 所提到的,在 main() 之前初始化的全局变量的问题将成为一个移动目标,具体取决于您的环境(编译器、库、版本等),因此最好不要首先进行此类初始化.但是,仍然存在需要它的情况:例如,当我使用单例模式时,您必须至少将全局变量初始化为 null。 (在潜在的多线程环境中,单例可能会导致问题......)

      【讨论】:

        猜你喜欢
        • 2017-04-22
        • 1970-01-01
        • 2011-06-20
        • 2017-08-26
        • 2011-07-10
        • 2010-09-16
        • 1970-01-01
        • 2012-06-09
        • 1970-01-01
        相关资源
        最近更新 更多