2010-12-13 35 views
0

我有一個struct,其中定義了一個常量char字符串,並且指向了我自己的字符串對象。目標是聲明這個結構體的變量,其中字符集和txt設置爲NULL,並且在運行時創建表示字符的MyString對象。我在編譯期間無法創建MyString,而使用GLib,並且此庫首先需要調用g_type_init。mingw const char字符串顯然不是const

struct _MyStaticString { 
    volatile MyString * txt; 
    const char *chars; 
}; 

的聲明會再看看這樣的:

struct _MyStaticString my_test_string = { NULL, "Hello world or foo bar, or a rick roll" }; 

那麼他們是一個函數,它是repsonsible通過第一檢查交付我的MyString的對象,如果TXT爲NULL,如果是創建一個新的MyString對象並返回這個MyString對象。

struct _MyString *my_static_string(struct _MyStaticString *a_static) { 
    printf("a_static=%lx\n", (gulong) a_static); 
    printf("a_static.chars=%s\n", (char *) a_static->chars); 
    if (a_static->txt == NULL) { 
     CatString *result = g_object_new(MY_TYPE_STRING, NULL); 
//  result->data = (gchar *) a_static->chars; 
     result->data = strdup((char *) a_static->chars); 
     result->size = strlen((char *) a_static->chars); 
     result->hash = 0; 
     g_object_ref_sink(G_OBJECT(result)); 
    result->parent.ref_count = 1000; 
    a_static->txt = result; 
} 
return (struct _MyString *) (a_static->txt); 

}

這一切的偉大工程,我很高興,至少當我在Linux上運行GCC。只要我在MinGW編譯器的幫助下開始在Windows上編譯此代碼,就會出錯。如果我把所有東西放在一個項目中它仍然沒問題,但只要將聲明放入.a庫並在其他地方使用,字段a_static-> chars就會變爲NULL。所以我開始播放/調整/測試:我想也許這是對象文件中數據的對齊,並因此添加了#pragma pack(16)。它沒有工作。比我想也許有一個屬性可以幫助我。所以我加了__attribute__((普通))。它沒有工作。我認爲是聰明和分離從結構聲明本身喜歡的字符串:

const char helper_txt = "Hello world or foo bar, or a rick roll"; 
struct _MyStaticString my_test_string = { NULL, helper_txt }; 

我得到的編譯錯誤:

error: initializer element is not constant 
error: (near initialization for 'field.chars') 

這裏是我的編譯器標誌

C:\MinGW\bin\gcc.exe 
    -IC:\MinGW\include 
    -IC:\GTK_ALL_IN_ONE\include\gtk-2.0 
    -IC:\GTK_ALL_IN_ONE\lib\gtk-2.0\include 
    -IC:\GTK_ALL_IN_ONE\include\atk-1.0 
    -IC:\GTK_ALL_IN_ONE\include\cairo 
    -IC:\GTK_ALL_IN_ONE\include\gdk-pixbuf-2.0 
    -IC:\GTK_ALL_IN_ONE\include\pango-1.0 
    -IC:\GTK_ALL_IN_ONE\include\glib-2.0 
    -IC:\GTK_ALL_IN_ONE\lib\glib-2.0\include 
    -IC:\GTK_ALL_IN_ONE\include 
    -IC:\GTK_ALL_IN_ONE\include\freetype2 
    -IC:\GTK_ALL_IN_ONE\include\libpng14 
    -IC:\work\workspace\module-blah\src 
    -O0 -g3 -Wall -c -fmessage-length=0 -mms-bitfields -DOSWINDOWS 

和這裏版本

C:\>c:\MinGW\bin\gcc.exe --version 
gcc.exe (GCC) 4.5.0 
Copyright (C) 2010 Free Software Foundation, Inc. 
This is free software; see the source for copying conditions. There is NO 
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 

我錯過了一些編譯器標誌,還是需要添加一個屬性來確保const char *字符串被導出到.a庫中,並且它們是檢查天氣中字符串是否位於.a庫中的簡單方法?或者它可能是一些鏈接器選項?

+1

您正在使用保留的標識符:C中任何以下劃線開頭並帶有大寫字母的標識符都被保留用於實現(見標準7.1.3),因此該程序會調用未定義的行爲。我的規則永遠不會以下劃線開始我的標識符。 – 2010-12-13 21:37:30

+0

另外,你的意思是「字段a_static->字符變爲NULL」?具體發生了什麼?那是'const char helper_txt'還是正確的'const char * helper_txt'? – 2010-12-13 21:44:32

回答

3

我的猜測是,你仍然得到了什麼看起來像你的項目中的NULL值在庫(.a文件)之外的地方變成了聲明。 GCC和鏈接器有時會生成代碼,這些代碼似乎遵循您的意圖,而不是C的嚴格字母,例如在多個.c文件中聲明相同的變量(或包含在多個.h文件中的.h文件.c文件在同一個項目中)。這應該導致的結果是變量的多個副本,並且可能還有鏈接器錯誤,告訴您代碼中存在多個具有相同名稱的對象,但由於某些原因,當您連接在一起時並不總是發生這種情況許多包含同一變量重複的.o文件。這裏

我的猜測是不是:

extern struct _MyStaticString a_string; 
在頭文件

您有:

struct _MyStaticString a_string; 

和你有什麼你認爲真正的聲明 - 一個與初始化 - 在一個.c文件中。

將實際聲明移至庫時,鏈接器的行爲在滿足對a_string對象的需求時發生了變化。它已經有一個或多個來自主程序的.o文件,所以它沒有打擾在圖書館尋找一個。以前它看到它有幾個來自.o文件,並決定使用已初始化爲非零值或非NULL值(全局或靜態變量的缺省值)的值。但是,如果連接器周圍的變量初始化版本已經決定在未初始化版本的變量之前,甚至在庫中查找您希望使用的值,那麼就不要使用變量的初始化版本。

+0

這聽起來像一個非常合理的解釋。解決方案:確保變量在所有頭文件中聲明爲'extern'。 – caf 2010-12-13 21:59:43

+0

我測試過它,它似乎工作。 Yeeeeha ...我會爲此喝一杯Glühwein。我確實玩過extern關鍵字,但我沒有把它放在正確的地方,並沒有給它任何想法。但是,這是與linux上的gcc完全不同的行爲 – LittleFunnyMan 2010-12-14 20:32:55