Форум программистов «Весельчак У»
  *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

  • Рекомендуем проверить настройки временной зоны в вашем профиле (страница "Внешний вид форума", пункт "Часовой пояс:").
  • У нас больше нет рассылок. Если вам приходят письма от наших бывших рассылок mail.ru и subscribe.ru, то знайте, что это не мы рассылаем.
   Начало  
Наши сайты
Помощь Поиск Календарь Почта Войти Регистрация  
 
Страниц: [1]   Вниз
  Печать  
Автор Тема: DLL и память  (Прочитано 12040 раз)
0 Пользователей и 1 Гость смотрят эту тему.
ezus
Опытный

il
Offline Offline

« : 13-06-2011 13:52 » 

Добрый день.

Есть DLL, обращение к которой выполняется через  LoadLibrary и GetProcAddress.
И DLL, и программа написаны на С++ 6.0.

Вопросы:
1. Тело DLL размещается в своем адресном пространстве или в адресном пространстве вызывающей программы?
2. Может ли вызывающая программа в процессе подготовки данных испортить тело  DLL?

Спасибо.
Записан
Finch
Спокойный
Администратор

il
Offline Offline
Пол: Мужской
Пролетал мимо


« Ответ #1 : 13-06-2011 14:38 » 

Код DLL размешается в расшаренной памяти. Т.е. для всех процессов Dll загружается только 1 раз. Потом система только расшаривает код. Ты с юзер мода не сможеш что либо затереть в коде DLL. Вот область переменных для каждого процесса своя.
Записан

Не будите спашяго дракона.
             Джаффар (Коша)
ezus
Опытный

il
Offline Offline

« Ответ #2 : 13-06-2011 15:10 » 

Тогда, что может быть причиной падения?
Программа падает на операторе
Код:
           memcpy(str2,Conditions->GetAt(j),LEN_FM_DESCRIP);
что в кодах
Код:
     102198F1   jb          CopyUnwindUp (1021991c)
=>   102198F3   rep movs    dword ptr [edi],dword ptr [esi]
     102198F5   jmp         dword ptr [edx*4+10219A08h]
Записан
Finch
Спокойный
Администратор

il
Offline Offline
Пол: Мужской
Пролетал мимо


« Ответ #3 : 13-06-2011 15:14 » 

ezus, А что есть str2. Что возвращает Conditions->GetAt(j). Ну и что есть LEN_FM_DESCRIP?
Записан

Не будите спашяго дракона.
             Джаффар (Коша)
Dimka
Деятель
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #4 : 13-06-2011 20:43 » 

Для DLL, хотя она находится в адресном пространстве процесса, есть ньюансы с выделением и освобождением памяти. Кратко всё сводится к правилу: где выделил память, там и освободи. На выделенную в основной программе память можно передать указатель в DLL, чтобы та могла читать или писать в эту память. Но освобождать память должна также основная программа. Если DLL выделяет память, она может передать указатель в основную программу, чтобы та могла читать или писать в эту память. Но освобождать память должна также DLL.

А в случае memcpy может банальный выход за границы принимающего буфера, который меньше размера копируемых данных.
Записан

Программировать - значит понимать (К. Нюгард)
Невывернутое лучше, чем вправленное (М. Аврелий)
Многие готовы скорее умереть, чем подумать (Б. Рассел)
Ochkarik
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #5 : 14-06-2011 00:17 » 

Dimka, серьезно? по поводу выделения-освобождения памяти?
всегда считал что разницы не должно быть - кто выделяет а кто освобождает....
почему так? где почитать можно?
Записан

RTFM уже хоть раз наконец!  RTFM :[ ну или хотя бы STFW...
Антон (LogRus)
Глобальный модератор

ru
Offline Offline
Пол: Мужской
Внимание! Люблю сахар в кубиках!


WWW
« Ответ #6 : 14-06-2011 03:03 » 

Ochkarik, потому, что аллокаторы, умные указали, буфер на стеке и т.д. и т.п. Улыбаюсь
Тоже может касаться не только dll, но и статик библиотек и даже классов с функциями

Ты не знаешь, какием способом была выделена память и выделялась ли вообще, может это был malloc, а не new или библиотека заранее создала 10 элементов одним массивом и отдала тебе только один элемент, а ты решил, что его можно грохнуть через delete
Записан

Странно всё это....
Dimka
Деятель
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #7 : 14-06-2011 04:35 » 

Ochkarik, где почитать - не знаю. "И опыт - сын ошибок трудных..." Устное предание Улыбаюсь

Если основная программа собрана, допустим, в Debug, а DLL - в Release, то в этих режимах сборки выделение памяти происходит по-разному (в Debug память выделяется с запасом). Поэтому такой невинный на первый взгляд подход, как выделение памяти в программе, а освобождение - в DLL, приводит к access violation. EXE и DLL - разные исполняемые файлы, и в них влинкованы собственные экземпляры стандартной и прочих статических библиотек, или же идёт обращение к разным версиям DLL из Microsoft'овских библиотека (с суффиксом D и без оного).
« Последнее редактирование: 14-06-2011 08:03 от Dimka » Записан

Программировать - значит понимать (К. Нюгард)
Невывернутое лучше, чем вправленное (М. Аврелий)
Многие готовы скорее умереть, чем подумать (Б. Рассел)
ezus
Опытный

il
Offline Offline

« Ответ #8 : 14-06-2011 05:25 » 

А в случае memcpy может банальный выход за границы принимающего буфера, который меньше размера копируемых данных.

Это действительно банальный, но действенный вывод, хотя я считал, что memcpy не проверяет выход за границу, а сбой на нем может быть только при залезании в запретные зоны, кратные страницам памяти. Поэтому размер принимающего буфера тут неважен.
Записан
RXL
Технический
Администратор

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #9 : 14-06-2011 05:47 » 

ezus, очень наивно. Это как кидать мусор из окна, считая, что до своего этажа куча еще не скоро дорастет.
Размер нужно высчитывать точно, или брать с запасом. Либо проверять перед копированием - сравнивать длину данных и размер буфера. Если это действительно строка, то добавь еще место для терминирующего нуля.
Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.

Хз, я не очень просто не очень во всё это верю, во всякие там сатурны и прочую поебень.
ezus
Опытный

il
Offline Offline

« Ответ #10 : 14-06-2011 05:50 » 

А что есть str2. Что возвращает Conditions->GetAt(j). Ну и что есть LEN_FM_DESCRIP?
Я знал, что такие вопросы возникнут, но не хотел пудрить мозги уважаемому сообществу всякими мелочами, надеялся, что ответа на основной вопрос мне хватит.
Но видимо придется поподробничать.

Большая программа, множество DLLs и LIBs.
Моя проблема возникает в следующей ситуации:
Выполняется два шага, каждый из которых запускается независимо своими пунктами в меню.

1-ый - это расчет. Большой, может продолжаться часами и жрать море памяти. Результаты сохраняет в MS Access. Комментировать:fie:.Решение не мое.

2-ой - это отчет по результатам расчета. Исходные данные читает из MS Access.

Расчет расположен в головной программе, а отчет в DLL.

Программа падает, если запускать отчет после расчета.
По отдельности все работает. Т.е., если запускать отчет после рестарта программы, то все ОК.

Сам сбой возникает только при работе с одним из 30 проектов, с остальными все нормально. Причем и с этим чертовым проектом не все однозначно, играясь с данными можно заставить его напечататься.

Загрузка DLL выполняется непосредственно перед вызовом функции печати на втором шаге.

У меня уже крыша едет. Я никак не могу нашупать идеи.

Буду благодарен любым подсказкам, мыслям, ассоциациям.

Добавлено через 3 минуты и 49 секунд:
очень наивно. Это как кидать мусор из окна, считая, что до своего этажа куча еще не скоро дорастет.
Размер нужно высчитывать точно, или брать с запасом. Либо проверять перед копированием - сравнивать длину данных и размер буфера. Если это действительно строка, то добавь еще место для терминирующего нуля.
Все верно, но проблема ведь не в этом.
Если в поле под 10 символов я запишу 20, то программа от этого не упадет на операторе записи. Она может упасть потом(дай б-г), когда затертая память будет использоваться, но не в момент записи, как у меня.
« Последнее редактирование: 14-06-2011 05:54 от ezus » Записан
RXL
Технический
Администратор

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #11 : 14-06-2011 06:13 » 

Цитата
Если в поле под 10 символов я запишу 20, то программа от этого не упадет на операторе записи. Она может упасть потом(дай б-г), когда затертая память будет использоваться, но не в момент записи, как у меня.

Ну-ну. Удачной охоты за багами.
Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.

Хз, я не очень просто не очень во всё это верю, во всякие там сатурны и прочую поебень.
ezus
Опытный

il
Offline Offline

« Ответ #12 : 14-06-2011 06:30 » 

Цитата
Если в поле под 10 символов я запишу 20, то программа от этого не упадет на операторе записи. Она может упасть потом(дай б-г), когда затертая память будет использоваться, но не в момент записи, как у меня.

Ну-ну. Удачной охоты за багами.
Не понял Я был не прав?
Программа упадет в момент выхода за границы?
Записан
RXL
Технический
Администратор

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #13 : 14-06-2011 07:16 » 

Какая разница?! Она будет функционировать не верно и это главное. А если она не упадет сразу, то результат работы дальнейшей работы будет непредсказуем.
Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.

Хз, я не очень просто не очень во всё это верю, во всякие там сатурны и прочую поебень.
ezus
Опытный

il
Offline Offline

« Ответ #14 : 14-06-2011 07:22 » 

Какая разница?! Она будет функционировать не верно и это главное. А если она не упадет сразу, то результат работы дальнейшей работы будет непредсказуем.
Да, большая разница!!!
В данный момент у меня цель другая, не написать программу без ошибок, а НАЙТИ УЖЕ существующую ошибку, чтобы исправивь ее получить "предсказуемую" программу.
Я ищу причину, по которой программа падает. Поэтому, если превышение размеров буфера не приводит к мгновенному падению, то это не моя ошибка, надо искать, что-то другое.
Записан
RXL
Технический
Администратор

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #15 : 14-06-2011 07:52 » 

Проверь:
1. Размер буфера назначения.
2. Корректность указателя источника.

Поставь в отладчике точку останова и просмотри память источника.
Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.

Хз, я не очень просто не очень во всё это верю, во всякие там сатурны и прочую поебень.
Dimka
Деятель
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #16 : 14-06-2011 08:09 » 

ezus, ты привёл одну строчку кода. Больше мы ничего не знаем. Тебе говорят о том, что в этой строчке может быть проблемным. Кроме сказанного, в ней ничего другого проблемного нет и быть не может. Не хочешь проверять, не хочешь разбираться - чего тогда спрашиваешь?

Или вся тема - не просьба помочь, а способ пожаловаться на трудную жизнь? Ну тогда я лично сочувствую, скорблю и т.д.
Записан

Программировать - значит понимать (К. Нюгард)
Невывернутое лучше, чем вправленное (М. Аврелий)
Многие готовы скорее умереть, чем подумать (Б. Рассел)
Ochkarik
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #17 : 14-06-2011 08:47 » 

Антон (LogRus), Dimka, понял)
каждый раз забываю, что память можно не только через API выделять Жжешь
Записан

RTFM уже хоть раз наконец!  RTFM :[ ну или хотя бы STFW...
ezus
Опытный

il
Offline Offline

« Ответ #18 : 14-06-2011 10:31 » 

Всем спасибо и за помощь и за сочувствие.
Код не мой, поэтому не сразу обратил внимание, что источник CString.
Записан
Алексей++
кот глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #19 : 14-09-2011 18:55 » 

прошёлся по дурацким граблям, часа 2 выяснял причину Жаль

Есть программа на C++ и DLL на C++

передавал в DLL из программы указатель на std::string , функция в DLL заполняла контейнер. А в дебаге , в деструкторе контейнера программа валилась (в релизе не валилась)

Оказалось, что если в контейнере, принадлежащем программе, после передачи указателя в DLL производилась переаллокация, то вот тогда этот падёж и возникал. Если зарезервировать нужный объём, а в DLL не переступать границу capacity , то всё ок
Записан

Dimka
Деятель
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #20 : 14-09-2011 19:46 » 

Это частный случай другой темы - о выделении и освобождении памяти в DLL и EXE.
Записан

Программировать - значит понимать (К. Нюгард)
Невывернутое лучше, чем вправленное (М. Аврелий)
Многие готовы скорее умереть, чем подумать (Б. Рассел)
Алексей++
кот глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #21 : 14-09-2011 20:04 » 

Dimka, где почитать ?
Записан

Вад
Модератор

ru
Offline Offline
Пол: Мужской

« Ответ #22 : 14-09-2011 20:47 » 

Так а что тут читать? При линковке dll получает свою копию функций аллокации, а exe - свою. В общем случае, версии этих функций могут различаться, и в релизе будет валиться тоже. Валиться будет и в том случае, если функции имеют side-effect - то есть, аллокация/освобождение памяти сопровождаются изменением каких-то глобальных переменных: собственно, в debug так и происходит, поскольку там есть дополнительные проверки насчёт того, выделялась ли вообще освобождаемая память, и нужно ли по этому поводу вызывать деструктор(ы).

Вообще, экспорт типов (в том числе, и std::string) из dll должен помогать. По крайней мере, мне, помнится, приходилось подобным образом решать проблему работы контейнеров через границу модуля: наследовал какой-то стандартный контейнер и делал экспорт/импорт (если не ошибаюсь, можно и напрямую экспортировать). Как результат, весь код компилируется в составе dll, и методы контейнера (в их числе, разумеется, и производящие аллокацию) вызываются из кода dll. Хотя это может быть не очень удобно в общем случае.
« Последнее редактирование: 14-09-2011 20:52 от Вад » Записан
Алексей++
кот глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #23 : 15-09-2011 04:38 » 

Вад, ну суть то я понял, почему так произошло )

>>экспорт типов (в том числе, и std::string) из dll должен помогать.
а это как делается ?
Записан

Вад
Модератор

ru
Offline Offline
Пол: Мужской

« Ответ #24 : 15-09-2011 08:13 » 

>>экспорт типов (в том числе, и std::string) из dll должен помогать.
а это как делается ?
http://support.microsoft.com/kb/168958/en-us (не люблю майкрософтовский автоматический перевод на suppot-е, он корявый какой-то)
Записан
Алексей++
кот глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #25 : 15-09-2011 08:25 » 

Вад, спасибо, щас почитаю. А перевод - это да, вечная там подстава, и не всегда сразу найдёшь, как инглиш переключить ))

хотя, я заметил, если ссылка оканчивается на "en-us" , то насильного перевода не происходит
Записан

Страниц: [1]   Вверх
  Печать  
 

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines