Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Общие вопросы > DLL и vector


Автор: alex87 6.3.2008, 14:13
Доброго времени суток.

Есть проблема c работой векторов совместно с dll
 
Код

//DLL file
// функция в dll

__declspec(dllexport) int WINAPI sel(unsigned int hnd, notrecrd * rec, string criterion)
{
    notrecrdcl* obj = (notrecrdcl*)hnd;
    return obj -> select(rec, criterion); // <- вот тут внутри использую вектора (объявление типа vector<vector(string)> > )
       
}



Но после того, как делаю вызов этой функции из программы :

Код


 int rcount = sel(hnd, record, "");



выкидывает :

user posted image

Вот такая проблемка, не знаю что делать, до этого использовал сишные строки и всё работало. 
Может кто подскажет ответ?

dll написана под visual studio 6.0 , вызывается из CBuilder6.
 




 

Автор: Mayk 6.3.2008, 14:31
Цитата(alex87 @  6.3.2008,  18:13 Найти цитируемый пост)
Может кто подскажет ответ?

Скорее всего вязанка и билдер используют разные версии STL. так что не стоит передавать std::string'и да std::vector'а.

Автор: alex87 6.3.2008, 14:44

http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=249870&SiteID=1 - 

нашел кое-что,  но я слабо понимаю о чём они там пишут.

Автор: andrew_121 6.3.2008, 15:00
Вот тебе и ответ...
Код

An especially nice feature of tr1::shared_ptr is that it automatically uses its per-pointer deleter
to eliminate another potential client error, the "cross-DLL problem."  This problem crops up when
an object is created using new in one dynamically linked library (DLL) but is deleted in a different DLL. 
On many platforms, such cross-DLL new/delete pairs lead to runtime errors.
tr1:;shared_ptr avoids the problem, because its default deleter uses delete from the same DLL where the
tr1::shared_ptr is created.

So, I could modify my code such that all allocations and deletions occur in either the client or the DLL
but not both, and pass a shared pointer to cross the boundary.  I haven't tried this yet but will soon.
I'll probably be using a boost shared pointer.  Does Visual Studio provide any tr1 stuff?


Автор: alex87 6.3.2008, 15:05
Цитата

Вот тебе и ответ...
    
An especially nice feature of tr1::shared_ptr is that it automatically uses its per-pointer deleter
to eliminate another potential client error, the "cross-DLL problem."  This problem crops up when
an object is created using new in one dynamically linked library (DLL) but is deleted in a different DLL. 
On many platforms, such cross-DLL new/delete pairs lead to runtime errors.
tr1:;shared_ptr avoids the problem, because its default deleter uses delete from the same DLL where the
tr1::shared_ptr is created.
So, I could modify my code such that all allocations and deletions occur in either the client or the DLL
but not both, and pass a shared pointer to cross the boundary.  I haven't tried this yet but will soon.
I'll probably be using a boost shared pointer.  Does Visual Studio provide any tr1 stuff?



Я же говорю - слабо понимаю английский, да и вообще кто-нибудь объяснит о чём тут написано?

Тестирую dll под вижуалом - всё работает - значит всё -таки проблема с совместимостью STL в билдере и вижуале 

Автор: andrew_121 6.3.2008, 15:38
http://pereklad.online.ua/

Особенно хорошая особенность tr1::shared_ptr есть, что это автоматически использует
его за-указатель deleter, чтобы исключить другую ошибку потенциального клиента, "Проблема ПЕРЕСЕЧЕНИЕ-DLL."
Эта проблема собирает урожай выше того, когда объект создан, используя новым в одном динамически связал
библиотеку (DLL) но удаляется в различном DLL.  На многих платформах, такие ПЕРЕСЕЧЕНИЕ-DLL
пары новости/удаления приводят к ошибкам во время выполнения. tr1:;shared_ptr избегает проблемы, потому что
его заданный по умолчанию deleter использует удаление из того же DLL, где tr1::shared_ptr создан. Так, я мог
изменить свой код такое, что все размещения и вычеркивания появляются или в клиента, или DLL но не как, так и
передают общий указатель, чтобы пересечь границу.  Я havent пробовал это еще но будет скоро. Плохо вероятно
использовать увеличение общий указатель.  Имен устройств Visual Studio обеспечивает любой tr1 материал?

За осмысловку не отвечаю.

Автор: alex87 6.3.2008, 15:42
Спасибо ;)

Автор: vinter 6.3.2008, 16:08
Цитата(andrew_121 @  6.3.2008,  16:38 Найти цитируемый пост)
Эта проблема собирает урожай

 smile  smile  smile 

Автор: andrew_121 6.3.2008, 16:23
Цитата(vinter @ 6.3.2008,  16:08)
Цитата(andrew_121 @  6.3.2008,  16:38 Найти цитируемый пост)
Эта проблема собирает урожай

 smile  smile  smile

Я заметил, но решил оставить, так, для прикола...

Автор: Fazil6 6.3.2008, 17:20
Цитата(alex87 @  6.3.2008,  13:13 Найти цитируемый пост)
Вот такая проблемка, не знаю что делать, до этого использовал сишные строки и всё работало. Может кто подскажет ответ?

ответ прост - не используйте объекты в интерфейсе dll.
использование здесь сишных строк как раз и есть решение проблемы.

Автор: Earnest 6.3.2008, 19:11
Нет, решение не в этом.
Нужно, чтобы и Exe и DLL использовали один и тот же экземпляр Run-time библиотеки (потому что там живут статические переменные, которые управляют кучей). Т.е. run-time тоже должна быть динамической (и одинаковой для всех модулей - в смысле дебажности и мультитредности). Тогда C-куча будет общая. А так - возникают проблемы, когда удаление происходит не в том модуле, где было выделение памяти, что у тебя, скорее всего и есть.
Второй вариант (менее удобный) - писать так, чтобы создание\удаление гарантированно происходило в одном модуле. Т.е. что-то типа оберток CreateVector\DeleteVector. Собственно, примерно это и написано в приведенной цитате (если читать оригинал).
Естественно, с малыми объектами - замучаешься. Да и использовать для обертки вектора shared-Ptr - масло масленное.  Проще добиться нормальной линковки с Run-Time DLL. 

Автор: Fazil6 6.3.2008, 19:46
Цитата(Earnest @  6.3.2008,  18:11 Найти цитируемый пост)
Нет, решение не в этом.

нет, решение как раз в этом. То, что ты описала частный случай, далеко не всегда реализуемый 
см. первый пост
Код

dll написана под visual studio 6.0 , вызывается из CBuilder6.


Автор: alex87 7.3.2008, 10:36
Цитата


ответ прост - не используйте объекты в интерфейсе dll.
использование здесь сишных строк как раз и есть решение проблемы.



С объектами всё работало, речь идёт о реализации внутри объекта .

Автор: Fazil6 7.3.2008, 13:06
Цитата(alex87 @  7.3.2008,  09:36 Найти цитируемый пост)
С объектами всё работало, речь идёт о реализации внутри объекта

не будет у тебя так организованная dll работать нормально. 
1.В интерфейсе либы нужно использовать переносимые типы (ты же не можешь передать std::vector из С)
2.Нужно избегать выделения и освобождения памяти в разных модулях ( создание std::string и передача из фунции в приложение, где он будет разрушен(ЧПОК!!! из-за разных CRT) )

Принципиально можно сделать так как у тебя, но работать нормально будет только если и приложение и dll собраны одной версией компилятора, с одинаковыми настройками и одними и темиже реализациями используемых либ (STL и пр.) 

Автор: alex87 7.3.2008, 13:42
Цитата

1.В интерфейсе либы нужно использовать переносимые типы (ты же не можешь передать std::vector из С)


Ну всё правильно : у меня string в интрефейсе, поэтому и не работало.

Автор: jonie 7.3.2008, 23:50
обернуть в класс и вынести его как COM объект если? ("фтопку просто экпорт)").
да и вообще в COM-е были уже "вектора" ....вроде...

Автор: Earnest 10.3.2008, 17:14
Цитата(Fazil6 @  6.3.2008,  20:46 Найти цитируемый пост)
То, что ты описала частный случай, далеко не всегда реализуемый 
см. первый пост

Да, это я прощелкала... Тогда действительно только одно - создание\удаление в рамках одного модуля. И вовсе необязательно COM, можно любые доморощенные обертки использовать. Но, очевидно, все это не слишком удобно, поэтому по мелочам лучше граниуц модулей не пересекать (со всякими векторами-стрингами) 

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)