Russian Qt Forum

Qt => Общие вопросы => Тема начата: Вудруф от Март 14, 2006, 14:13



Название: Динамическая библиотека, использующая Qt
Отправлено: Вудруф от Март 14, 2006, 14:13
Написал функции с использованием Qt, оформил в виде динамической библиотеки. Написал программу, загружающую эту dll во время работы. Откомпилировал gcc - работает.
Загружаю ту же dll из Builder'а с использованием тех же функций. OpenLibrary и т.д. - не работает!
Делаю ещё одну отладочную версию библиотеки с выводом доп. информации в процессе работы. Убеждаюсь, что все параметры были переданы правильно, QHttp инициализирован, присоединился и скачал данные. Однако readAllData возвращает ахинею.

Собственно, вопрос:
Как такое возможно? Это же уже откомпилированный код...


Название: Динамическая библиотека, использующая Qt
Отправлено: Dendy от Март 14, 2006, 14:47
А программа, загружающая DLL написана тоже на Qt? Работает, скомпиллировав из GCC, но не работает, скомпиллировав из Builder?


Название: Динамическая библиотека, использующая Qt
Отправлено: Вудруф от Март 15, 2006, 08:23
Нет, это просто код, не привязанный к Qt. Загружая библиотеку из Билдера, получаю в работе чушь (но функция вызывается с правильными параметрами!!!), загружая библиотеку из gcc, всё работает как надо.

Код:

typedef char * (*some_lib_func) (char *, int, char *, char *);

HINSTANCE handler;
handler = LoadLibrary ("some_lib.dll");
if (!handler)
{
std::cerr << "Could not load some_lib.dll\n";
...
}

some_lib_func a = (some_lib_func) GetProcAddress (handler, "some_func");
if (!a)
{
std::cerr << "Could not find function some_func\n";
...
}

...

FreeLibrary (handler);


Название: Динамическая библиотека, использующая Qt
Отправлено: Dendy от Март 15, 2006, 13:59
Могу только посоветовать вставить побольше отладочной информации в DLL. На каком именно месте она начинает работать по разному.


Название: Динамическая библиотека, использующая Qt
Отправлено: Вудруф от Март 15, 2006, 15:02
На этом:
return http -> readAll().data();

где http - экземпляр QHttp


Название: Динамическая библиотека, использующая Qt
Отправлено: Dendy от Март 15, 2006, 15:45
Ха! Ну так всё понятно, дружище. Ошибка в DLL - тьІ юзаешь освободившуюся память. В зависимости от параметров сборки на етапе вьІполнения ето может позволиться, а может и нет.

Вопрос, что делает такая строка:

Код:
return http->readlAll().data();


1. СчитьІвает данньІе и заносит их в екземпляр QByteArray.
2. Сохраняет указатель на реальньІе данньІе в QByteArray.
3. Уничтожает QByteArray, вьІходя из метода readAll(), и, так как ссьІлка на данньІе бьІла одна, - сами данньІе.
4. Возвращает указатель на только что удалённьІе данньІе.

Вообще небезопастньІй метод - возвращать указатель на данньІе неизвестного размера. Ещё небезопастно пользоваться разньІми версиями CRT библиотеки: DLL память вьІделяет, а программа уничтожает.

СамьІй правильньІй способ - пользоваться С-интерфейсом со структурами, например:

Код:
struct http_data_t
{
  char * data;
  qint64 size;
};

http_data_t * read_http_data()
{
  ..
  http_data_t * h = new http_data_t;
  h->size = http->bytesAbailable();
  h->data = new char[ h->size ];
  http->read( h->data, h->size );
  return h;
}

void destroy_http_data( http_data_t * h )
{
  delete[] h->data;
  delete h;
}


:D


Название: Динамическая библиотека, использующая Qt
Отправлено: Hordi от Март 15, 2006, 16:16
To Dendy:
немножко неверно...(но в целом выводы правильные)
data() вернет указатель на неудаленные данные, но после выхода из return данные будут уничтожены.

Это работает:

const char* get(const char *p)
{
    //данные, на которые указывает p валидны

    return p;
}

const char *p = get( std::string("11111111").c_str() );

//а тут уже данные невалидны
std::cerr << p << '\n';


Название: Динамическая библиотека, использующая Qt
Отправлено: Dendy от Март 15, 2006, 18:07
To Hordi
Немного не соглашусь:

Код:
const char * data = http->readAll().constData();
// data already invalid, because QByteArray was destroyed
return data;


Название: Динамическая библиотека, использующая Qt
Отправлено: Hordi от Март 15, 2006, 18:20
так я так же и написал - это то же самое, что и мой второй пример


Название: Динамическая библиотека, использующая Qt
Отправлено: Dendy от Март 15, 2006, 18:51
Да, я вижу. Но первьІй пример непонятен.

Цитата: "Hordi"
data() вернет указатель на неудаленные данные, но после выхода из return данные будут уничтожены.


Я вот с етим не соглашался. ДанньІе будут уничтоженьІ в таком порядке:

Код:
const char * data = QString( "ABC" ).toLatin1().toLower().constData();


1. Конструктор QString( "ABC" )
2. Метод toLatin1() инкрементирует ссьІлку на QByteArray( "ABC" ) (до 2) и тут же декрементирует (до 1)
3. Метод toLower() инкрементирует ссьІлку на QByteArray( "abc" ) (до 2) и тут же декрементирует (до 1)
4. Метод constData() просто возвражает указатель
5. ВьІзьІвается деструктор QByteArray( "abc" ) и уничтожает свои данньІе
6. ВьІзьІвается дектруктор QByteArray( "ABC" ) и уничтожает свои данньІе
7. ВьІзьІвается деструктор QString( "ABC" ) и уничтожает свои данньІе
8. ВьІзьІвается следующая операция после вьІражения. Все данньІе уже уничтоженьІ


Название: Динамическая библиотека, использующая Qt
Отправлено: Hordi от Март 15, 2006, 19:03
Будут, но только если return не передается непосредственно в функцию (уничножен при передаче в функцию будет после завершения функции).
Т.е. нижеприведенный код работает правильно (в середине функции func все OK):

void func( const char *p )
{
 ...работа с p
}

int main()
{
   func(  QString( "ABC" ).toLatin1().toLower().constData() );
}


Название: Динамическая библиотека, использующая Qt
Отправлено: Dendy от Март 15, 2006, 20:27
Согласен. Но стрёмно как-то (-:


Название: Динамическая библиотека, использующая Qt
Отправлено: Hordi от Март 15, 2006, 20:57
Почему стремно? Это абсолютно нормально.


Название: Динамическая библиотека, использующая Qt
Отправлено: Steven_Orko от Март 15, 2006, 22:48
Цитата: "Dendy"
Согласен. Но стрёмно как-то (-:

Я даже скажу больше... Так тоже нормально:
Код:
QString mefunc()
{
 .. .. //Что-то делаем
if (....)
{
} else return QString();
}

Но соглашусь с этим:
Код:
const char * data = QString( "ABC" ).toLatin1().toLower().constData();


QString( "ABC" ) - временный объект, который будет существавоть до конца вычисления значения всего выражения... т.е., как правильно уже сказали, data  уже использовать после этой строки нельзя...


Название: Динамическая библиотека, использующая Qt
Отправлено: Вудруф от Март 16, 2006, 06:53
Ошибка понятна, всем спасибо!!!