Страница 1 из 1

Добавлено: 09 авг 2004, 16:42
vg
Есть построенная dll которая прекрасно вызывается из жабы, выполняет необходимые действия и возвращает результат. Все хорошо, пока не срывается exception. При попытке сорвать exception в С коде, используя ThrowNew(...) метод, жаба вываливается с memory access violation exception и все благополучно умирает.
*env-> FindClass находит без ошибок. Может кто сталкивался, хоть в каком направлении грести?
Заранее спасибо всем!
Миша
Джава не знаю вообще. Но, думаю, Вам поможет вот что....
Перехватить обработчиком исключительной ситуации exeption, что происходит в dll возможно, только если используется одна и таже IDE (для кода в адресном пространстве которого выполняется код dll). Да и то не свегда. В целом это порочная практика девелоперов dll (надяться на то, что экзепшн будет правильно обработан в вызывающем коде, т.е. коде, который вызывает код dll).
В связи с этим проф-разработчики почти всегда обрабатывают экзепшн для ключевых ситуаций сами непосредственно в коде dll. Так строят API, COM ...

Короче, я бы обратился к разработчикам dll.

Добавлено: 09 авг 2004, 19:26
vg
Может и так. Но то, что в общем случае исключительную ситуацию, которая возникает в DLL (из-за кривости чего-то там, внутри dll), вы не сможете обрабатывать в общем случае в вызвывающем коде - этот точно. Это работает, если Вы подключаете dll в коде, сделанном в билдере, и сама dll была сделана в билдере. Если вы туже dll (сделанную в билдере) будете подключать в коде Visual Studio - номер не пройдёт.... как VS не подкручивай. В общем случае (если забыть про борланд) - это не работает вообще. Поэтому исключительные ситуации, которые могут возникнуть в dll (причём не важно, что это COM, или обычная дллька) надо обрабатывать в самой DLL. Если возникает в DLL экзепшен, то девелоперу dll надо минимально, например:
1) в текстовую строку записать месагу про экзепшн (если таковая вам понадобится в вызывающем коде, чтобы выкатить диалог про ошибку, например, в вызывающем коде)
2) возвратить код ошибки. лучше в 32-битном кодировании HRESULT.

Та прога, что вызывает функцию должна анализировать HRESULT= ! (rc & S_OK), например, или FAILED(.....). Если девелоперу нужна ещё дополнительная инфа об экзепшн, по её читают обращаясь к некому методу, например, ErrMsg() и т.п., что обработчик экзепшен внутри dll-ки уже запихнул по п.1. (см. выше), до того , как возвратить биты ошибки в HRESULT

Добавлено: 09 авг 2004, 19:37
vg
Ок. На этом форуме принято код давать. :lol: Что б понятно было.
Вот пример, что программер должен делать в Dll для имлементации интерфейсов (не COM):

Код: Выделить всё

//---------------------------------------------------------------------------
HRESULT __stdcall  CI_ADOquery::get_fieldval(LPCTSTR fieldname)
{
		try {
				outval_buf = pQuery->Fields->Item[fieldname]->Value;
...
...
				return S_OK;
		}
		catch (...) {
				error = _TEXT("Can't get field value: ");
				error += fieldname;
				if(msgerror) AfxMessageBox(error);
				return E_FAIL;
		}
}
//---------------------------------------------------------------------------
HRESULT __stdcall  CI_ADOquery::IntegerField(LPCTSTR fieldname, int* outval)
{
		HRESULT rc = get_fieldval(fieldname);
		if ( ! FAILED(rc) ) *outval = outval_buf.intVal;
		return rc;
}
//---------------------------------------------------------------------------
HRESULT __stdcall  CI_ADOquery::StringField(LPCTSTR fieldname, LPTSTR* outval)
{
		HRESULT rc = get_fieldval(fieldname);
		if ( ! FAILED(rc) )
		{
			string_buf = outval_buf;
			*outval = (LPTSTR) ((LPCTSTR) string_buf);
		}
		return rc;
}
//---------------------------------------------------------------------------
...
...
//---------------------------------------------------------------------------
void    __stdcall CI_ADOquery::ErrorMessage(LPTSTR* outval )
{
		*outval = (LPTSTR)((LPCTSTR)error);
}

Добавлено: 09 авг 2004, 21:13
vg
Я, кстати, бывал в Дукате и Омсукчане, в молодые годы
Да, вот шарик-то кругленький какой :lol: Дукат - там Российский бизнес. Омсукчанская компания - там Канадцы и немного наши добывают.

Re: нужна помощь по JNI

Добавлено: 11 авг 2004, 08:10
Lepsik
uncle_Misha писал(а):Может кто сталкивался, хоть в каком направлении грести?

Если по быстрому - напиши wrapper dll на с++ для этого метода.
И в вызывающей функции лови исключение и обрабатывай.

Добавлено: 11 авг 2004, 13:58
vg
Если по быстрому - напиши wrapper dll на с++ для этого метода.
И в вызывающей функции лови исключение и обрабатывай.
Ага. Щас. А ты попробуй сам перехватить исключение в обёртке, вызывающей длл. Не выйдет. Если на стадии компиляции не вставлена защищённая секия кода в коде кривой функции внутри dll, то не вставлена. Сам-то пробовал? Блин.

Добавлено: 12 авг 2004, 09:17
Lepsik
vg писал(а):Если на стадии компиляции не вставлена защищённая секия кода в коде кривой функции внутри dll, то не вставлена. Сам-то пробовал? Блин.
Если у меня произошел exeption в вызываемой функции написанной на С то exeption выловиться функций выше если есть обработчик и если не было фатального случая типа порчи памяти.

У автора проблема с трудностями обработки в Java насколько я понял.

Добавлено: 12 авг 2004, 14:13
vg
Если у меня произошел exeption в вызываемой функции написанной на С то exeption выловиться функций выше если есть обработчик и если не было фатального случая типа порчи памяти.
Интересно обсудить эту тему. Несмотря на то, что у автора вопрос по Java.
Так вот, скорее всего, и DLL, и вызывающий код у тебя написан в Builred-e. Посмотри, выше в нитке - там я постил про это. Действительно в этом случае (не знаю, как), билдер умудряется сделать то, о чём ты постишь.
Но вот ты попробуй собрать DLL, где не обрабатывается экзепшн, в MS компиллере, а обработать эту исключительную ситуацию в вызывающем коде, что сделан Builder, или в том же VS.

ПС. И вообще ... тестовый код в студию.

Добавлено: 16 авг 2004, 15:07
vg
Лепсик,

Если ты ещё здесь,

Мы пообсуждали эту тему ещё с парнями. Мне было интересно. Ещё разок копнуть, да потрещать на эту тему. То хорошие программеры. Надо сказать, что к единой точке зрения, как бы мы и не пришли, если рассматривать вопрос об экзепшн и глобально и с практической точки зрения.
Наверное, в конкретном случае надо сверяться с имплементацией SUH:
http://www.microsoft.com/msj/0197/excep ... ption.aspx

Ты, конечно же прав, когда говоришь, что в большинстве случаев программируя на С++ легко перехватить и обработать экзепшн (что происходит внутри DLL) в вызывающем коде. Хотел, бы отметить, то, что в первом посте было написано – В ОБЩЕМ СЛУЧАЕ (т.е. всегда) НЕВОЗМОЖНО. Т.е. в большинстве случаев (особенно, если программируется всё в одной среде – и DLL, и вызывающий код), таки да… Всё перехватывается и ловится.

Но вот, ниже, пример хакания самого себя в особо извращённой форме в DLL:

Код: Выделить всё

//простая функция DLL, где екзепшн связан с обращением к не проинициализированному указателю

// except.dll

#define EXCEPT_API   extern "C" __declspec(dllexport)

EXCEPT_API int __stdcall fexcept( void )
{
	int rc;
	char * s;

		memset( s, 0, 1024 );
		rc = atoi(s);

	return rc;
}
В консольном приложении test.exe эта функция DLL вызывается, как:
// test.exe

typedef int (__stdcall *pEXCEPT_FUN) ( void );

try
{
pfunc();
}
catch(...)
{
_tprintf(_TEXT("Good. We are in catch (...)\n"));
FreeLibrary(hlib);
return;
}
Если и except.dll, и test.exe изготовлены в одной IDE – проблем не возникает.
Особенно не возникает проблем, если это VS.NET.2003. В этом случае, исключительная ситуация (просто очень исключительная в данном случае) в except.dll отлавливается в test.exe – всё работает нормально.

Но!
1) Если скомпилировать except.dll ( full release ) в Borland C++ Builder 6.0, a test.exe в VS.NET 2003 –
то test.exe _ПРОСТО_МОЛЧАЛИВО_УМИРАЕТ при вызове pfunc(). Даже диалога о недопустимости операций не покажется.
2) Поведение вызывающей программы test.exe ещё зависит не только от того, каким компиллером собрана except.dll, но и с какими опциями – DEBUG, или RELEASE. Впрочем, поведение test.exe будет также зависеть от и опций проекта самого test.exe. (DEBUG, или RELEASE). Может и по неопытности, но я натыкался давно (конечно же в других программах), когда в DEBUG всё работало, а в RELEASE – валилось приложение…

И последнее…. DLL может быть вызвана не только из программы, написанной на С++. Это может быть и VB/VBA. В этом случае описанная «неодинаковость» обработки исключений при использовании разных компиллеров С++ - усугубляется. Необработанность исключения внутри DLL – почти всегда приводит к анормал терминейшн VBA программы. Хотя возможно, я плохо программрую не только на C++, но и на VB. ;(

Посему, вот моя точка зрения (допускаю, что тебе она совершенно по бороде):

1) Если собираем всё в одном и том же языке программирования и используем одну и туже IDE – то экзепшн отлавливается без проблем.

2) Если, предполагается, что DLL будет использована в разных языках программирования (в вызываеющем коде), обязательно обрабатывать исключения внутри самой DLL, где только можно, а возвращать код ошибки. Не надеясь, что экзепшн может быть обработан в вызывающем коде.

3) Народ неоднозначно (если говорить о глобальном концепсьёне) отнёсся к рациональности анализа в вызывающей программе кодов ошибок (хоть то HRESULT, хоть ещё что…). Напомнили историю с оператором new в C++. В связи с этим, и как бы ты не обрабатывал исключительные ситуации внутри кода функций ДЛЛ, хорошие программеры советуют вызывать функции ДЛЛ в try блоке, а не ограничиваться только анализом кода возврата. Для меня это остаётся спорным.

4) И последнее. Если во главу угла ставить переносимость бинарного кода, то современные компиллеры, пока что не позволяют всегда и однозначно перехватывать экзепшн в коде сделанном прои помощи других компиллеров. Это даже не моё мнение. Но я с ним согласен, ибо натыкался на эти грабли чисто по-ламерски.

Вот такие, Лепсик, дела с простым вопросом…. :lol: Про Экзепшен.

Добавлено: 17 авг 2004, 08:45
Lepsik
нечего даже возразить. В общем все верно. Ну и предлагал я "по-быстрому". Собственно установить среду в которой написана dll не сложно. Найти среду тоже - благо их не так много.

Ну и при условии что язык на котором сделана dll содержит конструкции обработки типа try catch.

Вот фортрановские dll которые у меня бывают умирают - тут я уже ничего не могу сделать :( кроме как пинать авторов

Добавлено: 23 авг 2004, 21:52
vg
Оказалось все очень просто, в методе который возвращает значение после срывания исключения, нужно поставить
return NULL;
после этого жаба прекрасно ловит Exceptions

Миша
OK. Здорово, что ты раскопал баг. Хотя .... в слюбыми багами, так или иначе в конце концов всё получается просто :lol: Согласись :lol: