Есть разделяемая библиотека (shared library). Есть h-файл, который ее описывает несколько функций этой библиотеки. Внутри самой библиотеки есть еще ряд функций, и, кроме того, глобально обьявленная структура configuration, задающая параметры работы библиотеки.
В приложении, которое использует библиотеку, тоже есть структура по имени configuration, но уже другого типа, с совершенно другими полями. Теоретически, структура, обьявленная внутри библиотеки, при компиляции никак не видна.
Проблема в том, что когда приложение начинает использовать функции библиотеки, повреждается информация в полях обьявленной для приложения структуры configuration. При этом меняет их именно внутренняя функция из библиотеки.
Вопрос: это глюк компилятора или так и должно быть? если должно быть, то как можно обойти данную проблему?
P.S. извините, возможно, написано непонятно. если надо будет, могу попробовать привести исходный код.
проблема с shared library (одинаковые идентификаторы)
Модератор: Модераторы разделов
-
whirlwind
- Сообщения: 67
проблема с shared library
Добро всегда побеждает зло. Мы победили, значит мы - добро.
-
/dev/random
- Администратор
- Сообщения: 5458
- ОС: Gentoo
Re: проблема с shared library
Да, написанное непонятно. Из него можно сделать вывод, что вы передаёте функциям библиотеки, которые ожидают получения структуры "библиотечного" типа configuration, структуру другого типа, не имеющего с требуемым ничего общего, кроме имени.
-
d_n_k
- Сообщения: 636
- ОС: Gentoo GNU/Linux
Re: проблема с shared library
Теоретически, структура, обьявленная внутри библиотеки, при компиляции никак не видна.
как вы можете передавать в библиотеку структуру которая не видна ака не объявлена нигде ?
если она нужна библиотеке, то структура должна быть в заголовочном файле.
если эта структура есть в заголовочном файле, то компилятор не даст вам объявить еще одну структуру с таким именем.
что-то у вас не так
все сказанное есть имхо...
-
whirlwind
- Сообщения: 67
Re: проблема с shared library
вторая попытка, букв окажется намного больше
код я переписал, выкинул все лишнее, чтобы стало яснее.
есть файл trulala.h, в котором обьявлены несколько функций и констант. По факту - интерфейс библиотеки.
есть файл, описывающий конфигурацию библиотеки, trulala_conf.h
с соответствующей реализацией, trulala_conf.c
и еще несколько файлов, которые реализуют функции библиотеки, trulala_another.c
все это компилируется в обьектные файлы с опциями -Wall -fPIC , а потом из них собирается собственно so-файл, с опциями -shared -Wl,-soname,$(LIBNAME)
Конфигурация основного приложения тоже описывается в переменной с именем configuration, но это уже совершенно другая структура, описанная в другом файле, с другим типом и т.д.
main_conf.h
И вот основной файл программы, нечто вроде
То есть, две совершенно разных переменных оказались на одном и том же месте в памяти. Когда в обоих структурах на первом месте идет char*, эффект хотя бы заметен; если поменять порядок полей местами, при попытке работать со строкой получается segmentation fault.
Исходники библиотеки, файл trulala.h и so-файл находятся в разных каталогах.
Исходники основной программы компилируются с -I<каталог с trulala.h>; потом собираются
cc -o $(TARGET) -I<каталог с trulala.h> <все *.o файлы> <путь к скомпилированному файлу библиотеки>/trulala.so -Wl,-rpath,<каталог, в котором библ окажется после установки>
есть файл 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
Да, теперь понятнее.
Всё так, как и должно быть. extern помещает переменную в глобальную область видимости, сквозь все модули и библиотеки. Соответственно, эти две переменные configuration - на самом деле одна и та же переменная. Чтобы этого избежать, нужно либо переименовать одну из них, либо превратить одну из них из extern в static.
-
d_n_k
- Сообщения: 636
- ОС: Gentoo GNU/Linux
Re: проблема с shared library
lib.h
lib.c
после
gcc lib.c -o lib.so -fPIC -shared
получается библиотека с
test.h
test.c
при попытке собрать основной файл получается
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)
Код: Выделить всё
#ifndef _lib_h_
#define _lib_h_
typedef struct
{
char* name;
} testStruct;
extern testStruct value;
[code]
void value_init();
#endiflib.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;
#endiftest.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
У whirlwind код другой. У вас в одном из модулей подключаются оба хидера (lib.h и test.h), а у него в каждом модуле только свой хидер (main_conf.h и trulala_conf.h).
-
d_n_k
- Сообщения: 636
- ОС: Gentoo GNU/Linux
-
d_n_k
- Сообщения: 636
- ОС: Gentoo GNU/Linux
Re: проблема с shared library
там написано про видимиость символов
http://developer.apple.com/documentation/D...Visibility.html
можно использовать __attribute__((visibility("hidden"))) чтобы прятать символы.
получается вот такое
символ value не видно из вне
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
огромное спасибо всем
к сожалению, мой компилятор далек от apple и от четвертой версии, умных слов не понимает ....
но все равно, куда копать, вроде ясно, что-нибудь найдется
к сожалению, мой компилятор далек от apple и от четвертой версии, умных слов не понимает ....
но все равно, куда копать, вроде ясно, что-нибудь найдется
Добро всегда побеждает зло. Мы победили, значит мы - добро.