mingw const char string is apparantly not const
I have a struct where a constant char string is defined and a pointer to my own string object. The goal is to declare a variable of this struct with the chars set and the txt set t NULL and than during runtime create the MyString object representing the chars. I can not create the MyString during compilation while I use the GLib and this lib first needs the g_type_init to be called.
struct _MyStaticString {
volatile MyString * txt;
const char *chars;
};
A declaration would then look like:
struct _MyStaticString my_test_string = { NULL, "Hello world or foo bar, or a rick roll" };
Then their is a function which is repsonsible for delivering me the MyString object by first checking if txt is NULL, if so create a new MyString object and return this MyString object.
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);
}
This all works great and I'm so happy, at least when I'm running GCC on Linux. As soon as I start compiling this code on Windows with the help of the MinGW compiler things start going wrong. If I put everything in one project It's still fine but as soon as put the declaration in a .a library and use it elsewhere the field a_static->chars becomes NULL. So I started playing/tweaking/testing: I thought maybe it's the alignment of the data in the Object files and thus added #pragma pack(16). It didn't work. Than I thought maybe there is an attribute which can help me. So I added __attribute__
((common)). It didn't work. I thought to be smart and separated the string from the structure declaration itself like:
const char helper_txt = "Hello world or foo bar, or a rick roll";
struct _MyStaticString my_test_string = { NULL, helper_txt };
I get compile errors:
error: initializer element is not constant
error: (near initialization for 'field.chars')
Here are my compiler flags
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
and here is the 开发者_如何学Cversion
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.
Do I miss some compiler flag or do I need to add an attribute to make sure the const char * string is exported into the .a lib and is their an easy way to check weather a string is in the .a lib? Or is it maybe some linker option ?
My guess is that you've still got what looks like a declaration of the variable that is turning up with NULL value in your project somewhere besides the library (.a file). GCC and the linker sometimes produce code that seems to follow your intentions rather than the strict letter of C when you do things like declare the same variable in more than one .c file (or in a .h file which is included in more than one .c file in the same project). What this should result in is more than one copy of the variable and possibly a linker error telling you that there is more than one object with the same name in your code, but for some reason this doesn't always happen when you are linking together lots of .o files that contain duplications of the same variable.
My guess here is that rather than:
extern struct _MyStaticString a_string;
in a header file you have:
struct _MyStaticString a_string;
and that you had what you consider the real declaration -- the one with the initialization -- in a .c file.
When you moved the real declaration to the library the linker's behavior changed when fulfilling the need for an a_string object. It already had one or more from the .o files from the main program so it didn't bother looking in the library for one. Previously it saw that it had several from the .o files and decided to go with the one that had been initialized to a non-zero or non-NULL value (the default for global or static variables). But without that initialized version of your variable around the linker has already decided to just go with one of the uninitialized versions of the variable before it even looks in the library for the value you wanted it to use.
精彩评论