1

对于调试和日志库,我希望能够在运行时找到项目已编译和链接的所有源文件的列表。我假设我将在每个源文件中包含某种标题,并且预处理器 __FILE__ 宏可以为我提供该文件的字符常量,因此我只需要以某种方式“广播”来自每个文件的信息以由 a运行时函数。

问题是如何优雅地做到这一点,特别是如果它可以从 C 而不是 C++ 中完成。在 C++ 中,我可能会尝试使用静态存储创建一个类来保存文件名列表。每个头文件都将创建该类的文件本地静态实例,该实例在创建时会将 FILE 指针或其他任何内容附加到类的静态数据成员中,可能作为链表。

但我认为这在 C 中不起作用,即使在 C++ 中,我也不确定是否可以保证每个元素都会被创建。

4

9 回答 9

4

我不会在代码中做那种事情。我会编写一个工具来解析项目文件(vcproj、makefile 甚至只是扫描项目目录中的 *.c* 文件)并生成一个额外的 C 源文件,其中包含某种预定义的所有源文件的名称初始化数据结构

然后我会将该工具作为构建过程的一部分,这样每次您进行构建时,这一切都会自动发生。在运行时,您所要做的就是读取已构建的数据结构。

于 2009-03-06T11:56:38.797 回答
2

我同意 Ferruccio 的观点,最好的方法是在构建系统中,而不是代码本身。作为他想法的扩展,在您的构建系统中添加一个目标,它将文件列表(无论如何它必须知道)作为字符串或字符串数​​组转储到 C 文件中,然后将此文件编译到您的源代码中。这避免了源代码中的很多复杂性,并且是可扩展的,如果您想添加其他信息,例如源代码控制系统的版本号、构建可执行文件的人等。

于 2009-03-06T12:17:49.230 回答
2

在 UNIX 和 Linux 上有一种标准方式 - ident. 对于您创建的每个源文件 ID 标记 - 通常它由您的版本控制系统分配,例如SVN 关键字

然后找出你只需使用ident命令的每个源文件的名称和版本。如果您需要在运行时执行此操作,请查看它是如何ident操作的 - 它的源代码应该是免费提供的。

于 2009-03-06T12:49:02.603 回答
1

在 C 中没有办法做到这一点。在 C++ 中,您可以创建这样的类:

struct Reg {
   Reg( const char * file ) {
      StaticDictionary::Register( file );
};

其中 StaticDictionary 是所有文件名的单例容器。然后在每个源文件中:

static Reg regthisfile( __FILE__ );

您可能希望将字典设为Meyers单例以避免创建顺序问题。

于 2009-03-06T11:58:58.747 回答
0

我认为您不能以“被动”模式下概述的方式做到这一点。也就是说,您将以某种方式为要添加到注册表的每个源文件运行代码,很难让它自动发生。

当然,您可以使用宏使该代码非常不显眼。对于没有“入口点”的 C 源文件可能会有问题,因此如果您的代码还没有组织为“模块”,例如init()每个模块都有一个函数,那可能会很困难。静态初始化代码可能是可能的,我不能 100% 确定初始化的顺序是否会在这里产生问题。

在注册表模块中使用static存储听起来是个好主意,如果您的项目还没有包含任何通用实用程序库,那么简单的链表或简单的哈希表应该很容易实现。

于 2009-03-06T11:57:38.297 回答
0

在 C++ 中,您的解决方案将起作用。这是有保证的。

编辑:刚刚在我的脑海中找到了一个解决方案:更改makefile中的规则以将'-include“cfiles_register.h”'添加到每个'g++ file.cpp'。

%.o : %.cpp
    $(CC) -include 'cfiles_register.h' -o $@ $<

将您的建议放在“cfiles_register.h”的问题实施中。

于 2009-03-06T11:58:24.473 回答
0

在 C++ 中使用静态实例可以正常工作。

您也可以在 C 中执行此操作,但您需要使用运行时特定功能 - 对于 MSVC CRT,请查看http://www.codeguru.com/cpp/misc/misc/threadsprocesses/article.php/c6945/

对于 C - 你可以用宏来做 - 定义一个与你的文件相对应的变量,然后你可以扫描你的可执行文件的符号,就像一个想法:

 #define TRACK_FILE(name) char _file_tracker_##name;

在你的 my_c_file.c 中使用它,如下所示:

 TRACK_FILE(my_c_file_c)

而不是像这样从二进制文件中grep所有文件/变量名

nm my-binary | grep _file_tracker

不是很好,但是...

于 2009-03-06T12:48:33.430 回答
0

可怕的想法,我敢肯定,但使用单例。并在每个文件上做类似的事情

  Singleton.register(__FILE__); 

在全球范围内。它只适用于 cpp 文件。几年前,我作为新手做过类似的事情,并且奏效了。但我现在很想这么做。我现在要添加一个构建步骤。

于 2009-03-06T13:02:57.937 回答
0

我同意那些说最好避免在运行时这样做的人的观点,但是在 C 中,您可以使用函数调用来初始化静态变量,即在每个文件中:

static int doesntmatter = register( __FILE__);
于 2009-03-06T14:38:01.000 回答