Строка mingw const char, по-видимому, не является константой

У меня есть структура, в которой определена постоянная строка char и указатель на мой собственный строковый объект. Цель состоит в том, чтобы объявить переменную этой структуры с набором символов и набором txt NULL, а затем во время выполнения создать объект MyString, представляющий символы. Я не могу создать MyString во время компиляции, пока я использую GLib, и эта библиотека сначала требует вызова 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" };

Тогда это функция, которая отвечает за доставку мне объекта 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);

}

Все это отлично работает, и я так счастлив, по крайней мере, когда я запускаю GCC в Linux. Как только я начинаю компилировать этот код в Windows с помощью компилятора MinGW, все начинает идти не так. Если я помещу все в один проект, все будет в порядке, но как только я поместил объявление в библиотеку .a и использовал его в другом месте, поле a_static-> chars становится NULL. Итак, я начал играть/настраивать/тестировать: я подумал, может быть, это выравнивание данных в файлах объектов, и поэтому добавил пакет #pragma (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? Или это может быть какой-то вариант компоновщика?


person LittleFunnyMan    schedule 13.12.2010    source источник
comment
Вы используете зарезервированные идентификаторы: любой идентификатор в C, начинающийся со знака подчеркивания, за которым следует заглавная буква, зарезервирован для использования в реализации (см. 7.1.3 Стандарта), и поэтому эта программа вызывает неопределенное поведение. Мое правило — никогда не начинать свои идентификаторы со знака подчеркивания.   -  person David Thornley    schedule 14.12.2010
comment
Кроме того, что вы подразумеваете под тем, что поле a_static-›chars становится NULL? Что конкретно произошло? Это const char helper_txt или правильный const char * helper_txt?   -  person David Thornley    schedule 14.12.2010


Ответы (1)


Я предполагаю, что у вас все еще есть то, что выглядит как объявление переменной, которая появляется со значением NULL в вашем проекте где-то помимо библиотеки (файл .a). GCC и компоновщик иногда создают код, который, кажется, следует вашим намерениям, а не строгой букве C, когда вы делаете такие вещи, как объявление одной и той же переменной более чем в одном файле .c (или в файле .h, который включен более чем в один файл). .c в том же проекте). Это должно привести к более чем одной копии переменной и, возможно, к ошибке компоновщика, говорящей вам, что в вашем коде есть более одного объекта с одним и тем же именем, но по какой-то причине это не всегда происходит, когда вы связываете вместе множество файлов .o, содержащих дубликаты одной и той же переменной.

Я предполагаю, что вместо этого:

extern struct _MyStaticString a_string;

в заголовочном файле у вас есть:

struct _MyStaticString a_string;

и что у вас было то, что вы считаете настоящим объявлением - объявление с инициализацией - в файле .c.

Когда вы переместили реальное объявление в библиотеку, поведение компоновщика изменилось при выполнении потребности в объекте a_string. У него уже был один или несколько файлов .o из основной программы, поэтому он не стал искать их в библиотеке. Раньше он видел, что у него есть несколько файлов .o, и решил использовать тот, который был инициализирован ненулевым или ненулевым значением (по умолчанию для глобальных или статических переменных). Но без этой инициализированной версии вашей переменной компоновщик уже решил просто использовать одну из неинициализированных версий переменной, прежде чем он даже ищет в библиотеке значение, которое вы хотели использовать.

person nategoose    schedule 13.12.2010
comment
Это звучит как очень правдоподобное объяснение. Решение: убедитесь, что переменная объявлена ​​extern во всех заголовочных файлах. - person caf; 14.12.2010
comment
Я проверил это, и это, кажется, работает. Даааа... Я выпью за это глинтвейн. Я играл с ключевым словом extern, но я просто не поставил его в нужное место и не придал этому значения. Но это совершенно другое поведение, чем gcc в Linux. - person LittleFunnyMan; 14.12.2010