Russian Qt Forum
Ноябрь 23, 2024, 22:02 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1]   Вниз
  Печать  
Автор Тема: Динамическая библиотека, использующая Qt  (Прочитано 8605 раз)
Вудруф
Гость
« : Март 14, 2006, 14:13 »

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

Собственно, вопрос:
Как такое возможно? Это же уже откомпилированный код...
Записан
Dendy
Гость
« Ответ #1 : Март 14, 2006, 14:47 »

А программа, загружающая DLL написана тоже на Qt? Работает, скомпиллировав из GCC, но не работает, скомпиллировав из Builder?
Записан
Вудруф
Гость
« Ответ #2 : Март 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);
Записан
Dendy
Гость
« Ответ #3 : Март 15, 2006, 13:59 »

Могу только посоветовать вставить побольше отладочной информации в DLL. На каком именно месте она начинает работать по разному.
Записан
Вудруф
Гость
« Ответ #4 : Март 15, 2006, 15:02 »

На этом:
return http -> readAll().data();

где http - экземпляр QHttp
Записан
Dendy
Гость
« Ответ #5 : Март 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;
}


Веселый
Записан
Hordi
Гость
« Ответ #6 : Март 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';
Записан
Dendy
Гость
« Ответ #7 : Март 15, 2006, 18:07 »

To Hordi
Немного не соглашусь:

Код:
const char * data = http->readAll().constData();
// data already invalid, because QByteArray was destroyed
return data;
Записан
Hordi
Гость
« Ответ #8 : Март 15, 2006, 18:20 »

так я так же и написал - это то же самое, что и мой второй пример
Записан
Dendy
Гость
« Ответ #9 : Март 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. ВьІзьІвается следующая операция после вьІражения. Все данньІе уже уничтоженьІ
Записан
Hordi
Гость
« Ответ #10 : Март 15, 2006, 19:03 »

Будут, но только если return не передается непосредственно в функцию (уничножен при передаче в функцию будет после завершения функции).
Т.е. нижеприведенный код работает правильно (в середине функции func все OK):

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

int main()
{
   func(  QString( "ABC" ).toLatin1().toLower().constData() );
}
Записан
Dendy
Гость
« Ответ #11 : Март 15, 2006, 20:27 »

Согласен. Но стрёмно как-то (-:
Записан
Hordi
Гость
« Ответ #12 : Март 15, 2006, 20:57 »

Почему стремно? Это абсолютно нормально.
Записан
Steven_Orko
Гость
« Ответ #13 : Март 15, 2006, 22:48 »

Цитата: "Dendy"
Согласен. Но стрёмно как-то (-:

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

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


QString( "ABC" ) - временный объект, который будет существавоть до конца вычисления значения всего выражения... т.е., как правильно уже сказали, data  уже использовать после этой строки нельзя...
Записан
Вудруф
Гость
« Ответ #14 : Март 16, 2006, 06:53 »

Ошибка понятна, всем спасибо!!!
Записан
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.049 секунд. Запросов: 20.