我有一个结构,其中定义了一个常量字符串,并指向了我自己的字符串对象。目标是使用chars set和txt set t NULL声明此结构的变量,并且在运行时创建表示chars的MyString对象。我在编译期间无法创建MyString,而我使用GLib,这个lib首先需要调用g_type_init。
struct _MyStaticString {
volatile MyString * txt;
const char *chars;
};
声明如下:
struct _MyStaticString my_test_string = { NULL, "Hello world or foo bar, or a rick roll" };
然后,他们是一个可以通过首先检查txt是否为NULL来传递MyString对象的函数,如果这样,则创建一个新的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->字符就变为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 lib中,并且它们是一种检查字符串在.a lib中的天气的简单方法吗?或者它可能是一些链接器选项?
答案 0 :(得分:3)
我的猜测是,除了库(.a文件)之外的某个地方,你仍然有一个看起来像是在项目中出现NULL值的变量声明。当您执行诸如在多个.c文件中声明相同变量(或包含在多个.h文件中的.h文件)之类的操作时,GCC和链接器有时会产生似乎遵循您的意图而不是C的严格字母的代码。 .c文件在同一个项目中)。这应该导致的是变量的多个副本以及可能的链接器错误,告诉您代码中有多个具有相同名称的对象,但由于某种原因,当您将链接连接在一起时并不总是这样许多包含相同变量重复的.o文件。
我的猜测是,而不是:
extern struct _MyStaticString a_string;
在头文件中:
struct _MyStaticString a_string;
并且您在.c文件中拥有了您认为真实的声明 - 初始化声明。
当您将实际声明移动到库时,链接器的行为在满足a_string对象的需要时会发生变化。它已经有来自主程序的.o文件中的一个或多个,因此它不会在库中寻找一个。以前它看到它有几个来自.o文件,并决定使用已初始化为非零或非NULL值的那个(全局变量或静态变量的默认值)。但是如果没有链接器周围的变量的初始化版本已经决定只使用其中一个未初始化的变量版本,它甚至会在库中查找您希望它使用的值。