2009-03-06 15 views
1

對於調試和日誌記錄庫,我希望能夠在運行時查找項目已編譯的所有源文件的列表以及鏈接。我假設我將在每個源文件中包含某種頭文件,並且預處理程序__FILE__宏可以爲該文件提供一個字符常量,所以我只需要以某種方式「廣播」來自每個文件的信息,以便通過運行時功能。註冊每個C/C++源文件以創建使用源的運行時列表

問題是如何優雅地做到這一點,特別是如果它可以從C而不是C++完成。在C++中,我可能會嘗試使用靜態存儲來創建一個類來保存文件名列表。每個頭文件都會創建該類的文件本地靜態實例,該實例在創建時會將FILE指針或其他任何內容附加到類的靜態數據成員中,可能會作爲鏈接列表。

但我不認爲這將在C中工作,甚至在C++中我不確定它會保證每個元素都將被創建。

+0

你使用makefile或Visual Studio/Eclipse/etc? – 2009-03-06 12:18:28

回答

4

我不會在代碼中做這樣的事情。我會編寫一個解析項目文件的工具(vcproj,makefile或甚至只是掃描項目目錄中的* .c *文件),並生成一個額外的C源文件,其中包含所有源文件的名稱,初始化數據結構。

然後,我會使該工具成爲構建過程的一部分,以便每次構建時都會自動發生。在運行時,您只需讀取已構建的數據結構即可。

+0

解析vcproj是一項額外的工作。掃描目錄不會保證任何內容。 – 2009-03-06 12:12:38

0

我不認爲你可以用你在「被動」模式下勾畫的方式來做到這一點。也就是說,你將以某種方式運行每個源文件的代碼以添加到註冊表中,很難讓它自動發生。

當然,您可以使用宏使代碼非常不顯眼。對於沒有「入口點」的C源文件可能會有問題,所以如果你的代碼還沒有被組織成「模塊」,例如,一個init()函數爲每個模塊,它可能很難。靜態初始化代碼可能是可能的,我不能100%確定事物初始化的順序是否會在這裏產生問題。

在註冊表模塊中使用static存儲聽起來像是一個很好的想法,如果您的項目尚未包含任何通用實用程序庫,則簡單鏈接列表或簡單哈希表應該足夠容易實現。

+0

可以自動化。看到我的答案。 – 2009-03-06 12:03:59

0

在C++中,您的解決方案將起作用。它有保證。

編輯:剛剛發現在我的頭上的解決方案:更改你的makefile規則添加 「-include‘cfiles_register.h’」每個「G ++ file.cpp」。

%.o : %.cpp 
    $(CC) -include 'cfiles_register.h' -o [email protected] $< 

把你提出的問題實現爲'cfiles_register.h'。

1

世界上沒有辦法做到這一點的C.在C++中,你可以創建一個這樣的類:

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

其中StaticDictionary是您所有文件名的單容器。然後,在每一個源文件:

static Reg regthisfile(__FILE__); 

你會想使字典中的Meyers單,以避免產生問題的順序。

+0

爲什麼在這種情況下訂單是一個問題? – 2009-03-06 12:03:24

+0

因爲在嘗試使用它之前需要確保已創建靜態字典。既然你不能依賴於全局的創建順序,你需要通過單例模式在第一次使用時創建它。 – 2009-03-06 12:07:10

2

我同意Ferruccio,最好的方法是在構建系統中,而不是代碼本身。作爲他的想法的一個擴展,將目標添加到您的構建系統中,該系統將文件列表(它必須知道)轉儲爲C文件作爲字符串或字符串數​​組,然後將此文件編譯到源代碼中。這樣可以避免源代碼中的許多複雜情況,並且可以擴展,如果您想添加其他信息,例如源代碼控制系統的版本號,構建可執行文件的版本號等。

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 

不是真的不錯,但......

2

有在UNIX和Linux的標準方式 - ident。爲每個源文件創建ID標記 - 通常由您的版本控制系統分配,例如SVN keywords

然後找出每個源文件的名稱和修訂版,您只需使用ident命令。如果您需要在運行時執行此操作,請查看ident是如何做到的 - 它的來源應該是免費的。

0

可怕的想法,我敢肯定,但使用單身。並在每個文件上做類似

Singleton.register(__FILE__); 

在全局範圍。它只會在cpp文件上工作。 我做了一些像這些年前一樣的新手,並且很有效。但我現在就畏縮去做。我現在要添加一個構建步驟。

0

我同意那些誰說,這是更好地避免在運行時這樣做,但在C,您可以初始化函數調用一個靜態變量,那就是,在每個文件:

static int doesntmatter = register(__FILE__);