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

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

但我认为这在 C 中行不通,甚至在 C++ 中我也不确定是否能保证每个元素都会被创建。

有帮助吗?

解决方案

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

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

其他提示

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

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

然后找出每个源文件的名称和修订版,只需使用<=>命令。如果你需要在运行时这样做,请查看<=>如何做到 - 它的来源应该是免费提供的。

Theres无法在C中完成。在C ++中,您可以创建一个这样的类:

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

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

static Reg regthisfile( __FILE__ );

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

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

当然,您可以使用宏来使代码非常不引人注目。对于没有<!>“entrypoint <!>”的C源文件可能会有问题,因此,如果您的代码尚未组织为<!> quot; modules <!> quot;,例如,每个模块的init()函数,可能很难。静态初始化代码可能是可能的,我不是100%确定如果初始化事物的顺序在这里产生问题。

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

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

编辑:刚刚找到了解决方案:更改makefile中的规则以添加 '-include <!> quot; cfiles_register.h <!> quot;'每个'g ++ file.cpp'。

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

将您提出的问题在实施中提交给'cfiles_register.h'。

在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

不太好,但是......

可怕的想法,我确定,但是使用单身人士。并在每个文件上执行类似

的操作
  Singleton.register(__FILE__); 

在全球范围内。它只适用于cpp文件。 几年前我做了一些像新手一样的事情,并且它起作用了。但我现在很畏缩。我现在要添加一个构建步骤。

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

static int doesntmatter = register( __FILE__);
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top