Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Visual C++/MFC/WTL > Помогите разобраться с dll


Автор: suvolod 17.2.2006, 11:55
Помогите решить следующую задачку. В книге "Петзольда Программирование для Windows 95, том 2, глава 19" приведен пример программы, как создать dll, у которой есть некоторая общая область данных, видимая всем программам, которые используют данную dll. Выглядит этот примерно так :
Код

#pragma data_seg("shared")
PSTR pszStrings[MAX_STRINGS] = { NULL };
int iTotal = 0;
#pragma data_seg() 
#pragma comment(linker, "/section:shared,rws")

Затем приложение, которое использует данную dll, добавляет в массив pszStrings строки, и эти строки отображаются в клиентской части окна всех копий приложения, запущенных в данный момент.
Проблема заключается в том, что у меня при попытке запустить вторую копию приложения она просто вылетает. Если же убрать в коде dll строчку " #pragma comment(linker, "/section:shared,rws") ", то копия2 (и последующие) запускаются нормально, но каждый использует и выводит в окно свой собственный массив pszStrings. Работаю я под VC++ 6.0 SP6, ОС- WinXP SP1
На всякий случай - вот здесь исходники: suvolod.mail2k.ru/proect.rar . Весит немного - около 70 Kb
STRLIB - это исходники библиотеки
STRPROG - это исходники программы, использующие STRLIB.dll

Автор: Earnest 17.2.2006, 14:24
Либо в книжке ошибка, либо ты что-то не так понял.
Общая память должна охватывать каждый байт общих данных, а у тебя только адреса строкю А сами строки где хранится будут? Ясно же, что память выделенная в одном приложении, не доступна в другом... Вот она и падает.
В данном случае (если хочешь именно набор строк сделать общедоступным) нужно выделить буфер символов достаточно большого размера, и копировать строки туда.
Чтобы просто понять как работает общий сегмент данных, заведи для начала простые переменные, массив интов, например.

Автор: suvolod 17.2.2006, 18:34
И все-таки я не понял, в чем моя ошибка … Может кто-то глянет сам код?
Самое интересное, что я нашел-таки исходники от самого Петзольда, и у него та-же самая ошибка: если запустить, к примеру, 4 копии приложения, а затем, используя одну из них, добавить строку - все остальные копии тут-же вылетают, хотя у него ясно написано, что директива типа #pragma comment(linker, "/section:shared,rws") делает все переменные этого раздела общими… Мучает смутное подозрение, что его код тоже рабочий, но только под Windows95, а под NT такой способ создания "общего раздела" не прокатывает.

А насчет замечания "а у тебя только адреса строкю А сами строки где хранится будут" – строки добавляются к массиву pszStrings через функцию библиотеки STRLIB
На всякий случай вот ее код:
Код

//добавление строк в через DLL
EXPORT BOOL CALLBACK AddString(PSTR pStringIn)
{
HANDLE hString;
PSTR pString;
int i, iLength, iCompare;
if(iTotal == MAX_STRINGS - 1)    //общее количество строк не должно быть больше 256
return FALSE;
iLength = strlen(pStringIn);    
if(iLength == 0)            //нельзя добавлять пустую строку
return FALSE;
hString = CreateFileMapping(    //создаем спроецированный в память файл
(HANDLE) -1, NULL, PAGE_READWRITE,0, 1 + iLength, NULL);        
if(hString == NULL)                //не получилось создать
return FALSE;
pString =(PSTR) MapViewOfFile(hString,    FILE_MAP_WRITE,    0, 0, 0);
strcpy(pString, pStringIn);        //скопировали строку в проецируемый файл
AnsiUpper(pString);            //перевели в верхний регистр

for(i = iTotal; i > 0; i--)
{
iCompare = strcmpi(pStringIn, pszStrings[i - 1]);
if(iCompare >= 0)
break;
pszStrings [i] = pszStrings[i - 1];
}
pszStrings[i] = pString;
iTotal++;
return TRUE;
}


Автор: Earnest 17.2.2006, 20:49
suvolod, pragma comment нормально работает во всех виндовсах. И не в ней суть - это всего лишь удобный способ передать опции линкеру. То же самое можно сделать и в командной строке или в настройках проекта. Суть в создании именованной секции данных и объявлении ее общей (разделяемой).
ТОЛЬКО ТО, ЧТО НАХОДИТСЯ В СЕКЦИИ, РАЗДЕЛЯЕТСЯ.
А в секции у тебя находятся АДРЕСА СТРОК, а не сами строки. Адрес строки - это просто число, с точки зрения другого экземпляра, по этому адресу ничего никогда не было.
Не знаю, почему у Петцольда это работало, возможно дело в проецированных в память файлах. Но все равно не понимаю, какой смысл указатель в MapView одного процесса может иметь в контексте другого.
Если ты в разделяемую секцию поместишь такую переменную:
char szBuf[MAX_SIZE] = "AAAAAAAAAAAAAA";
то к ее содержимому можно будет обращаться из любого экземпляра.

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