строка символов mingw const явно не постоянна - PullRequest
0 голосов
/ 14 декабря 2010

У меня есть структура, в которой определена постоянная строка символов и указатель на мой собственный строковый объект. Цель состоит в том, чтобы объявить переменную этой структуры с установленными символами и набором txt t 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 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? Или это может быть какой-то вариант компоновщика?

1 Ответ

3 голосов
/ 14 декабря 2010

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

Мое предположение здесь, а не:

extern struct _MyStaticString a_string;

в заголовочном файле:

struct _MyStaticString a_string;

и что у вас есть то, что вы считаете реальной декларацией - той, с инициализацией - в файле .c.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...