проблема с shared library (одинаковые идентификаторы)

Модератор: Модераторы разделов

Аватара пользователя
whirlwind
Сообщения: 67

проблема с shared library

Сообщение whirlwind »

Есть разделяемая библиотека (shared library). Есть h-файл, который ее описывает несколько функций этой библиотеки. Внутри самой библиотеки есть еще ряд функций, и, кроме того, глобально обьявленная структура configuration, задающая параметры работы библиотеки.

В приложении, которое использует библиотеку, тоже есть структура по имени configuration, но уже другого типа, с совершенно другими полями. Теоретически, структура, обьявленная внутри библиотеки, при компиляции никак не видна.

Проблема в том, что когда приложение начинает использовать функции библиотеки, повреждается информация в полях обьявленной для приложения структуры configuration. При этом меняет их именно внутренняя функция из библиотеки.

Вопрос: это глюк компилятора или так и должно быть? если должно быть, то как можно обойти данную проблему?

P.S. извините, возможно, написано непонятно. если надо будет, могу попробовать привести исходный код.
Добро всегда побеждает зло. Мы победили, значит мы - добро.
Спасибо сказали:
Аватара пользователя
/dev/random
Администратор
Сообщения: 5458
ОС: Gentoo

Re: проблема с shared library

Сообщение /dev/random »

Да, написанное непонятно. Из него можно сделать вывод, что вы передаёте функциям библиотеки, которые ожидают получения структуры "библиотечного" типа configuration, структуру другого типа, не имеющего с требуемым ничего общего, кроме имени.
Спасибо сказали:
d_n_k
Сообщения: 636
ОС: Gentoo GNU/Linux

Re: проблема с shared library

Сообщение d_n_k »

Теоретически, структура, обьявленная внутри библиотеки, при компиляции никак не видна.

как вы можете передавать в библиотеку структуру которая не видна ака не объявлена нигде ?
если она нужна библиотеке, то структура должна быть в заголовочном файле.
если эта структура есть в заголовочном файле, то компилятор не даст вам объявить еще одну структуру с таким именем.

что-то у вас не так
все сказанное есть имхо...
Спасибо сказали:
Аватара пользователя
whirlwind
Сообщения: 67

Re: проблема с shared library

Сообщение whirlwind »

вторая попытка, букв окажется намного больше ;) код я переписал, выкинул все лишнее, чтобы стало яснее.

есть файл trulala.h, в котором обьявлены несколько функций и констант. По факту - интерфейс библиотеки.

Код: Выделить всё

#ifndef _TLLI_        //так оформлен каждый из заголовочных файлов
#define _TLLI_
void tll_init();          //эта ф-ция заполняет поля в configuration, см ниже
int  tlldoSomething(int );
#define SOME_CONST 25
....
#endif

есть файл, описывающий конфигурацию библиотеки, trulala_conf.h

Код: Выделить всё

typedef struct
{
    char*   somename;
    int     someint;
    ....
} TrulalaConfiguration;

extern TrulalaConfiguration configuration;


с соответствующей реализацией, trulala_conf.c

Код: Выделить всё

#include "inc/trulala.h"
#include "trulala_conf.h"

TrulalaConfiguration configuration;

void tll_init()
{//на самом деле, значения полей читаются из файла,
 //но здесь, это, наверное, не важно
    configuration.somename = "trulala";
    configuration.someint = 42;
}

и еще несколько файлов, которые реализуют функции библиотеки, trulala_another.c

Код: Выделить всё

#include "inc/trulala.h"
#include "trulala_conf.h"
int  tlldoSomething(int )
{
        if (configuration.someint<50)
            return 42;
}


все это компилируется в обьектные файлы с опциями -Wall -fPIC , а потом из них собирается собственно so-файл, с опциями -shared -Wl,-soname,$(LIBNAME)

Конфигурация основного приложения тоже описывается в переменной с именем configuration, но это уже совершенно другая структура, описанная в другом файле, с другим типом и т.д.
main_conf.h

Код: Выделить всё

typedef struct
{
    char*   mainname;
    int     mainint;
    ....
} MainConfiguration;

extern MainConfiguration configuration;

И вот основной файл программы, нечто вроде

Код: Выделить всё

#include "trulala.h"
#include "main_conf.h"

MainConfiguration configuration;

int
main(inc argc, char* argv[])
{
    configuration.mainname = "main";
    tll_init();
    printf("%s\n", configuration.mainname);// здесь я получаю trulala !!!
}


То есть, две совершенно разных переменных оказались на одном и том же месте в памяти. Когда в обоих структурах на первом месте идет char*, эффект хотя бы заметен; если поменять порядок полей местами, при попытке работать со строкой получается segmentation fault.

Исходники библиотеки, файл trulala.h и so-файл находятся в разных каталогах.
Исходники основной программы компилируются с -I<каталог с trulala.h>; потом собираются
cc -o $(TARGET) -I<каталог с trulala.h> <все *.o файлы> <путь к скомпилированному файлу библиотеки>/trulala.so -Wl,-rpath,<каталог, в котором библ окажется после установки>
Добро всегда побеждает зло. Мы победили, значит мы - добро.
Спасибо сказали:
Аватара пользователя
/dev/random
Администратор
Сообщения: 5458
ОС: Gentoo

Re: проблема с shared library

Сообщение /dev/random »

whirlwind писал(а):
28.05.2008 16:15
вторая попытка, букв окажется намного больше ;) код я переписал, выкинул все лишнее, чтобы стало яснее.
[cut]

Да, теперь понятнее.
Всё так, как и должно быть. extern помещает переменную в глобальную область видимости, сквозь все модули и библиотеки. Соответственно, эти две переменные configuration - на самом деле одна и та же переменная. Чтобы этого избежать, нужно либо переименовать одну из них, либо превратить одну из них из extern в static.
Спасибо сказали:
d_n_k
Сообщения: 636
ОС: Gentoo GNU/Linux

Re: проблема с shared library

Сообщение d_n_k »

lib.h

Код: Выделить всё

#ifndef _lib_h_
#define _lib_h_

typedef struct
{
        char*   name;
} testStruct;


extern testStruct value;
[code]
void value_init();

#endif


lib.c

Код: Выделить всё

#include "lib.h"

testStruct value;


void value_init()
{
        value.name = "test value from lib";
}

после
gcc lib.c -o lib.so -fPIC -shared
получается библиотека с
readelf -sD lib.so

Symbol table for image:
Num Buc: Value Size Type Bind Vis Ndx Name
8 0: 00000314 0 FUNC GLOBAL DEFAULT 9 _init
5 0: 00002010 0 NOTYPE GLOBAL DEFAULT ABS _edata
10 0: 0000041c 30 FUNC GLOBAL DEFAULT 11 value_init
2 0: 00000000 0 NOTYPE WEAK DEFAULT UND _Jv_RegisterClasses
1 0: 00000000 0 NOTYPE WEAK DEFAULT UND __gmon_start__
4 1: 00002018 0 NOTYPE GLOBAL DEFAULT ABS _end
6 1: 00002014 4 OBJECT GLOBAL DEFAULT 22 value
9 1: 00000474 0 FUNC GLOBAL DEFAULT 12 _fini
3 2: 00000000 236 FUNC WEAK DEFAULT UND __cxa_finalize
7 2: 00002010 0 NOTYPE GLOBAL DEFAULT ABS __bss_start



test.h

Код: Выделить всё

#ifndef _test_h_H
#define _test_h_H

typedef struct
{
        char *name;
} xyz;

extern xyz value;

#endif


test.c

Код: Выделить всё

#include "lib.h"

#include "test.h"

#include <stdio.h>
#include <stdlib.h>

xyz value;

int main()
{

        value.name = "test";

        value_init();


        printf ("%s\n", value.name);


        return 0;

}




при попытке собрать основной файл получается
gcc test.c -l lib.so
In file included from test.c:3:
test.h:9: ошибка: conflicting types for ‘value’
lib.h:10: ошибка: previous declaration of ‘value’ was here
test.c:8: ошибка: conflicting types for ‘value’
lib.h:10: ошибка: previous declaration of ‘value’ was here


gcc (GCC) 4.1.2 (Gentoo 4.1.2)
все сказанное есть имхо...
Спасибо сказали:
Аватара пользователя
/dev/random
Администратор
Сообщения: 5458
ОС: Gentoo

Re: проблема с shared library

Сообщение /dev/random »

d_n_k писал(а):
28.05.2008 17:07
In file included from test.c:3:
test.h:9: ошибка: conflicting types for ‘value’
lib.h:10: ошибка: previous declaration of ‘value’ was here
test.c:8: ошибка: conflicting types for ‘value’
lib.h:10: ошибка: previous declaration of ‘value’ was here

У whirlwind код другой. У вас в одном из модулей подключаются оба хидера (lib.h и test.h), а у него в каждом модуле только свой хидер (main_conf.h и trulala_conf.h).
Спасибо сказали:
d_n_k
Сообщения: 636
ОС: Gentoo GNU/Linux

Re: проблема с shared library

Сообщение d_n_k »

есть такое
все сказанное есть имхо...
Спасибо сказали:
d_n_k
Сообщения: 636
ОС: Gentoo GNU/Linux

Re: проблема с shared library

Сообщение d_n_k »

там написано про видимиость символов
http://developer.apple.com/documentation/D...Visibility.html

можно использовать __attribute__((visibility("hidden"))) чтобы прятать символы.

получается вот такое
readelf -sD libxyz.so

Symbol table for image:
Num Buc: Value Size Type Bind Vis Ndx Name
7 0: 000002fc 0 FUNC GLOBAL DEFAULT 9 _init
5 0: 00002010 0 NOTYPE GLOBAL DEFAULT ABS _edata
9 0: 0000040c 15 FUNC GLOBAL DEFAULT 11 value_init
2 0: 00000000 0 NOTYPE WEAK DEFAULT UND _Jv_RegisterClasses
1 0: 00000000 0 NOTYPE WEAK DEFAULT UND __gmon_start__
4 1: 00002018 0 NOTYPE GLOBAL DEFAULT ABS _end
8 1: 00000454 0 FUNC GLOBAL DEFAULT 12 _fini
3 2: 00000000 236 FUNC WEAK DEFAULT UND __cxa_finalize
6 2: 00002010 0 NOTYPE GLOBAL DEFAULT ABS __bss_start

символ value не видно из вне
все сказанное есть имхо...
Спасибо сказали:
Аватара пользователя
whirlwind
Сообщения: 67

Re: проблема с shared library

Сообщение whirlwind »

огромное спасибо всем
к сожалению, мой компилятор далек от apple и от четвертой версии, умных слов не понимает ....
но все равно, куда копать, вроде ясно, что-нибудь найдется
Добро всегда побеждает зло. Мы победили, значит мы - добро.
Спасибо сказали: