注册每个 C/C++ 源文件来创建所用源的运行时列表

发布于 2024-07-14 10:41:55 字数 344 浏览 7 评论 0原文

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

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

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

For a debugging and logging library, I want to be able to find, at runtime, a list of all of the source files that the project has compiled and linked. I assume I'll be including some kind of header in each source file, and the preprocessor __FILE__ macro can give me a character constant for that file, so I just need to somehow "broadcast" that information from each file to be gathered by a runtime function.

The question is how to elegantly do this, and especially if it can be done from C as opposed to C++. In C++ I'd probably try to make a class with a static storage to hold the list of filenames. Each header file would create a file-local static instance of that class, which on creation would append the FILE pointer or whatever into the class's static data members, perhaps as a linked list.

But I don't think this will work in C, and even in C++ I'm not sure it's guaranteed that each element will be created.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(9

预谋 2024-07-21 10:41:56

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

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

There is a standard way on UNIX and Linux - ident. For every source file you create ID tag - usually it is assigned by you version control system, e.g. SVN keywords.

Then to find out the name and revision of each source file you just use ident command. If you need to do it at runtime check out how ident does it - source for it should be freely available.

所谓喜欢 2024-07-21 10:41:56

在 C 中无法做到这一点。在 C++ 中,您可以创建一个如下所示的类:

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

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

static Reg regthisfile( __FILE__ );

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

Theres no way to do it in C. In C++ you can create a class like this:

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

where StaticDictionary is a singleton container for all your file names. Then in each source file:

static Reg regthisfile( __FILE__ );

You would want to make the dictionary a Meyers singleton to avoid order of creation problems.

我是有多爱你 2024-07-21 10:41:56

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

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

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

I don't think you can do this in the way you outline in a "passive" mode. That is, you are going to somehow run code for each source file to be added to the registry, it's hard to get it to happen automatically.

Of course, it's possible that you can make that code very unobtrusive using macros. It might be problematic for C source files that don't have an "entrypoint", so if your code isn't already organised as "modules", with e.g. an init() function for each module, it might be hard. Static initializing code might be possible, I'm not 100% sure if the order in which things are initialized creates problems here.

Using static storage in the registry module sounds like an excellent idea, a plain linked list or simple hash table should be easy enough to implement, if your project doesn't already include any general-purpose utility library.

生寂 2024-07-21 10:41:56

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

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

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

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

In C++ your solution will work. It's guaranteed.

Edit: Just found out a solution in my head: Change a rule in your makefile to add
'-include "cfiles_register.h"' to each 'g++ file.cpp'.

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

put your proposed in the question implemnatation to that 'cfiles_register.h'.

眼波传意 2024-07-21 10:41:56

在 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

不是真的不错,但是……

Using static instances in C++ would work fine.

You could do this also in C, but you need to use runtime specific features - for MSVC CRT take a look at http://www.codeguru.com/cpp/misc/misc/threadsprocesses/article.php/c6945/

For C - you could do it with a macro - define a variable named corresponding to your file, and then you could scan the symbols of your executable, just as an idea:

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

use it in your my_c_file.c like this:

 TRACK_FILE(my_c_file_c)

and than grep all file/variable names from the binary like this

nm my-binary | grep _file_tracker

Not really nice, but...

温柔少女心 2024-07-21 10:41:56

我确信这是一个可怕的想法,但是使用单例。 操作

  Singleton.register(__FILE__); 

并在每个文件上执行类似于全局范围的 。 但它只适用于 cpp 文件。
几年前,作为新手,我做了类似的事情,而且很有效。 但我现在却不敢这样做。 我现在添加一个构建步骤。

Horrible idea, I'm sure, but use a singleton. And on each file do something like

  Singleton.register(__FILE__); 

at global scope. It'll only work on cpp files though.
I did something like this years ago as a novice, and it worked. But I'd cringe to do it now. I'd add a build step now.

飘落散花 2024-07-21 10:41:56

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

static int doesntmatter = register( __FILE__);

I agree with those who say that it is better to avoid doing this at run time, but in C, you can initialize a static variable with a function call, that is, in every file:

static int doesntmatter = register( __FILE__);
多彩岁月 2024-07-21 10:41:55

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

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

I wouldn't do that sort of thing right in the code. I would write a tool which parsed the project file (vcproj, makefile or even just scan the project directory for *.c* files) and generated an additional C source file which contained the names of all the source files in some kind of pre-initialized data structure.

I would then make that tool part of the build process so that every time you do a build this would all happen automatically. At run time, all you would have to do is read that data structure that was built.

清欢 2024-07-21 10:41:55

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

I agree with Ferruccio, the best way to do this is in the build system, not the code itself. As an expansion of his idea, add a target to your build system which dumps a list of the files (which it has to know anyway) to a C file as a string, or array of strings, and compile this file into your source. This avoids a lot of complication in the source, and is expandable, if you want to add additional information, like the version number from your source code control system, who built the executable, etc.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文