【问题标题】:Reinitialize global/static memory at runtime or static analysis of global/static variables在运行时重新初始化全局/静态内存或全局/静态变量的静态分析
【发布时间】:2018-02-10 19:49:03
【问题描述】:

问题

我正在开发一个大量使用全局变量的大型 C 项目 (C99)(我知道,我知道)。该程序运行良好,但它最初设计为运行一次并退出。

因此,它依赖于它的全局/静态内存用 0(或它声明的任何值)进行初始化,并且在运行时它会修改这些变量(就像大多数程序一样)。

但是,我不想在完成时退出,而是想再次运行该程序。我想制作一个对这个大型程序具有控制权和可见性的父程序。完全了解正在运行的程序非常重要。

该解决方案需要在 macOS、Linux 和 Windows 上运行。

我考虑过:

1。分叉它

制作一个充当“shell”的小包装程序,并根据需要执行大程序。

优点

  • 操作系统会努力将内存重置为正确的值
  • 保证按预期运行

缺点

  • 失去对程序的了解
  • 在运行时无法从包装器检查执行程序的内存,启动前更难调整设置,更难收集运行时信息
  • 需要实现一个系统来将内部数据输入/输出程序,可能会涉及大量代码
  • 统一体验更难(共享 GUI 窗口等)

2。手动识别关键结构

仔细阅读源代码,多次运行程序,等待程序因健全性检查或错误的内存访问而崩溃。

优点

  • 简单易做
  • 容易上手
  • 高可见性、代码共享和统一

缺点

  • 不是每一个案例都抓到,非常拼凑
  • 耗时

3。重构

将所有全局变量收集到memset 的单个结构中,为使用值初始化的变量创建初始化程序。根据具体情况处理静态数据。

优点

  • 概念上简单的大锤方法
  • 高可见性、代码共享和统一

缺点

  • 非常耗时,代码库很大,几乎可以触及所有内容

4。魔杖

告诉操作系统重新初始化全局/静态内存。如果我需要保存一个值,我会将它存储在本地,然后在完成后重写它。

优点

  • 非常完美:)

缺点

  • 不存在 (?)
  • 非常黑魔法
  • 可能不是跨平台
  • 可能会激怒第 3 方库

我现在在做什么

我现在使用选项 2,只是通过代码,依靠程序崩溃并为我指明正确的方向。

我想说这种方法已经让我完成了大约 80% 的工作。我已经确定并重新初始化了足够多的东西,程序或多或少可以重新运行。它并没有我想象的那么普遍,它给了我很大的希望。

偶尔会发生奇怪的事情或者它没有按预期运行,但它也不会崩溃。这使得追踪它变得更加困难。

我只需要一些东西来让我最后 20%。可能是某种静态分析工具,或者可以帮助我查看源代码并查看全局变量的位置。

【问题讨论】:

  • 函数中的静态变量可能真的有问题——你甚至可能争辩说它们应该成为文件范围。使用方法 2 扩展为 “对于定义任何全局变量的每个文件,添加一个 void filename_reset(void) 函数将所有全局变量重置为默认值”。 如果它不为零,则需要一个可以在修改后的版本上复制的非默认数据的常量版本。不要跳过任何全局变量——直到你知道你可以安全地这样做。然后安排生成对filename1_reinit(); filename2_reinit(); 等的一系列调用——每个文件一个调用。
  • 选项号 1 是唯一真正的选项。选项 2 要求您拥有进入可执行文件的每段代码的源代码。这包括您可能拥有的 3rd 方库。但它还包括 C 运行时和 C 标准库,我敢肯定你没有。
  • @user3386109:标准 C 库不会缓存太多,除非您计算语言环境设置(并且重新启动的代码可能需要考虑是否设置了语言环境 - 但可能会说“不” )。 C 库之外的库是另一回事——那里很容易出现问题。 POSIX 库中非线程安全的函数可能会出现问题——例如getpwent()
  • @JonathanLeffler errno 例如。由malloc 维护的信息。有关打开文件的信息。即使是argv 指向的字符串,程序也可以更改。程序退出时全部清理,但如果您只是告诉程序重新开始,则不会清理。
  • @user3386109: ... 内存已分配但未释放;环境变量集(虽然不是标准 C 的一部分)。有足够的可能性重新启动不是为重新启动而设计的软件(通过使用太多全局变量并且通常不清理资源)是非常有问题的。

标签: c memory static initialization global


【解决方案1】:

要轻松检测全局变量和静态变量,您可以尝试CppDepend 并执行类似这样的 cqlinq 查询

from f in Fields where f.IsGlobal || f.IsStatic
select f

如果您想要特定函数或特定文件中使用的变量,您也可以修改查询。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-09-03
    • 2023-03-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多