Падает ADO при exception
От: _Stranger_  
Дата: 12.01.04 08:34
Оценка:
Бьюсь несколько дней, не могу понять, в чем дело.
Следующий код прекрасно работает, если все хорошо.
Но если в процессе выполнения функций ADO возникает exception, по завершении функции main() вылетает сообщение:

---------------------------
Microsoft Visual C++
---------------------------
Unhandled exception in ADO.exe: 0xC0000005: Access Violation.
---------------------------
OK
---------------------------

Для возникновения exception достаточно изменить (LOCAL) в строке pConnection->ConnectionString на несуществующее имя компьютера.

#import "C:\Program Files\Common Files\System\ADO\msado15.dll" \
    no_namespace rename("EOF", "EndOfFile")

#include <stdio.h>
#include <conio.h>

// Function declarations
inline void TESTHR(HRESULT x) {if FAILED(x) _com_issue_error(x);};
void PrintComError(_com_error &e);

///////////////////////////////////////////////////////////
//                                                       //
//      Main Function                                    //
//                                                       //
///////////////////////////////////////////////////////////

void main()
{
    if(FAILED(::CoInitialize(NULL)))
        return;

    // Define Connection object pointer.
    // Initialize pointers on define.
    // These are in the ADODB::  namespace
    _ConnectionPtr pConnection = NULL;
    _CommandPtr pCmd = NULL;
    _ParameterPtr pPrm = NULL;

    try
    {
        // Open a connection using OLE DB syntax.
        TESTHR(pConnection.CreateInstance(__uuidof(Connection)));
        pConnection->ConnectionString = "Provider=SQLOLEDB.1;Data Source=(LOCAL);Initial Catalog=Pubs;Integrated Security=SSPI";
        pConnection->Open("","","",adConnectUnspecified);

        // Create Command object for stored procedure call
        TESTHR(pCmd.CreateInstance(__uuidof(Command)));
        pCmd->ActiveConnection = pConnection;
        pCmd->CommandText = "byroyalty";

        // Define command parameter
        pPrm = pCmd->CreateParameter("percentage", adInteger, adParamInput, sizeof(long), (long)100);
        pCmd->Parameters->Append(pPrm);

        // Execute stored procedure
        _RecordsetPtr pRs = pCmd->Execute(NULL, NULL, adCmdStoredProc);
        _bstr_t bstrAUID;

        while (!pRs->EndOfFile)
        {
            bstrAUID = pRs->Fields->GetItem("au_id")->Value;
            printf("%s\n", (LPCSTR) bstrAUID);
    
            pRs->MoveNext();
        }

        // Cleanup objects before exit
        pRs->Close();
        pConnection->Close();
    }

    catch(_com_error &e)
    {
        PrintComError(e);
    }

    // Wait here for user to see the output..
    printf("\nPress any key to continue...");
    getch();

    ::CoUninitialize();
}

///////////////////////////////////////////////////////////
//                                                       //
//      PrintComError Function                           //
//                                                       //
///////////////////////////////////////////////////////////

void PrintComError(_com_error &e)
{
    _bstr_t bstrSource(e.Source());
    _bstr_t bstrDescription(e.Description());

    // Print Com errors.  
    printf("Error\n");
    printf("\tCode = %08lx\n", e.Error());
    printf("\tCode meaning = %s\n", e.ErrorMessage());
    printf("\tSource = %s\n", (LPCSTR) bstrSource);
    printf("\tDescription = %s\n", (LPCSTR) bstrDescription);
}
Re: Падает ADO при exception
От: _Stranger_  
Дата: 12.01.04 11:10
Оценка:
Может кто-нибудь проверить у себя выполнение этого кода?
Неужели у меня одного он падает?
Программа практически совпадает с примерами из MSDN.
Пожалуйста!
Re[2]: Падает ADO при exception
От: _Stranger_  
Дата: 12.01.04 11:25
Оценка:
Если кто попробует, пожалуйста, замените
pCmd->CommandText = "byroyalty";

на
pCmd->CommandText = "_byroyalty";

Спасибо заранее.
Re: Падает ADO при exception
От: Demoniada Россия  
Дата: 12.01.04 11:43
Оценка:
"_Stranger_" <forum@rsdn.ru> wrote in message news:503662@news.rsdn.ru...
> Бьюсь несколько дней, не могу понять, в чем дело.
> Следующий код прекрасно работает, если все хорошо.
> Но если в процессе выполнения функций ADO возникает exception, по завершении функции main() вылетает сообщение:

Признаюсь честно, хоть это тебе и не поможет, полгода назад я оказался в таком-же положении, то есть казалось эта ошибка возникает только у меня и ни у кого более. Вот, ты первый обнаруженный мною человек, увидевший ее
Мои исследования ее ни к чему на привели, но по-моему при возникновении исключения рушится стек. Как обойти — не знаю, слава богу в моей ситуации просто не было необходимости продолжать рыть, от этого направления отказались по внешним причинам. На вопросы в форумах в меня кидались сообщениями типа "ты что, сдурел кидать исключения из COM-объекта наружу!", то есть народ просто не понимал либо не хотел понимать.
Так что прими мои соболезнования.
Если найдешь решение — буду очень рад о нем узнать.
Posted via RSDN NNTP Server 1.7 "Bedlam"
Да хранит вас господь в сухом прохладном месте...
Re: Падает ADO при exception
От: KGP http://kornilow.newmail.ru
Дата: 12.01.04 12:00
Оценка:
Здравствуйте, _Stranger_, Вы писали:

Наверное дело в обёртках ... предлагаю ещё так сделать ...
    try    {
        _ConnectionPtr pConnection = NULL;
        _CommandPtr pCmd = NULL;
        _ParameterPtr pPrm = NULL;

        try ...
  } catch(_com_error &e)
  {
     PrintComError(e);
  }

    ::CoUninitialize();

То есть обложи ещё и деструктор Ptr и посмотри что падает
... << RSDN@Home 1.1.0 stable >>
Re[2]: Падает ADO при exception
От: _Stranger_  
Дата: 12.01.04 12:31
Оценка:
Здравствуйте, KGP, Вы писали:

Наверное дело в обёртках ... предлагаю ещё так сделать ...
<skipped>
То есть обложи ещё и деструктор Ptr и посмотри что падает

Попробовал.
Исключение ловится первым catch, то есть проблема не в деструкторе.

В основной программе, в которой были замечены проблемы, действия с ADO производятся в функции, декларированной так:
BOOL CDBStorage::GetApplicationID(const EL_APPINFO *pAppInfo, long &lApplicationID)

Так вот после вызова функции ADO, вызывающей исключение, pAppInfo получает некоторое новое значение, то есть pConnection->Open при возникновении в нем исключение портит стек.
Или я не прав?
Re[2]: Падает ADO при exception
От: _Stranger_  
Дата: 12.01.04 12:38
Оценка:
Здравствуйте, Demoniada, Вы писали:

Вот, ты первый обнаруженный мною человек, увидевший ее

Ага, а ты первый, кто мне поверил

Спасибо за соболезнования.
В моем случае внешних причин не предвидится. Поэтому буду продолжать рыть дальше.
Предположение, что исключение в функциях ADO рушит стек, находит подтверждение. В моем случае после вызова функций ADO в функции, имеющей входные параметры, значения этих параметров становятся неопределенными после возникновения исключения в функции ADO.

Непонятно, как с этим бороться.

Между прочим, в release версии эта программа ОТЛИЧНО работает.
Это меня радует, но не совсем, т.к. реакцию приложения на исключения ADO нужно дебажить, а в дебаге код не работает.

Если найдешь решение — буду очень рад о нем узнать.

Если мои поиски увенчаются результатом — непременно.
Re[3]: Падает ADO при exception
От: Merle Австрия http://rsdn.ru
Дата: 12.01.04 12:44
Оценка:
Здравствуйте, _Stranger_, Вы писали:

_S_>Непонятно, как с этим бороться.

А версия ADO какая?
Попробуй скачать с MS распоследний MDAC, вдруг поможет?
Мы уже победили, просто это еще не так заметно...
Re[4]: Падает ADO при exception
От: _Stranger_  
Дата: 12.01.04 12:49
Оценка:
Здравствуйте, Merle, Вы писали:

А версия ADO какая?

MDAC 2.8 (последний), VC 6.0 SP5, Windows 2000 SP4, MS SQL Server 2000 Developer Edition SP3a
Re[2]: Падает ADO при exception
От: _d_m_  
Дата: 13.01.04 00:08
Оценка:
Здравствуйте, KGP, Вы писали:

KGP>Здравствуйте, _Stranger_, Вы писали:


KGP>Наверное дело в обёртках ... предлагаю ещё так сделать ...


Предлагаю написать свои обертки. Я лично так и делаю.
Re: Падает ADO при exception
От: _Stranger_  
Дата: 13.01.04 07:47
Оценка:
Немного поменял код, перенес работу с ADO в функцию.
Пожалуйста, если кому не сложно, скомпилируйте у себя проект в debug и release версиях.
И вышлите мне весь проект (*.cpp, *.dsp, *.exe) на ALegkikh_at_yandex.ru
Заранее спасибо.

#import "C:\Program Files\Common Files\System\ADO\msado15.dll" \
    no_namespace rename("EOF", "EndOfFile")

#include <stdio.h>
#include <conio.h>

// Function declarations
inline void TESTHR(HRESULT x) {if FAILED(x) _com_issue_error(x);};
void PrintComError(_com_error &e);
void Test(void);

///////////////////////////////////////////////////////////
//                                                       //
//      Main Function                                    //
//                                                       //
///////////////////////////////////////////////////////////

void main()
{
    if(FAILED(::CoInitialize(NULL)))
        return;

    Test();

    // Wait here for user to see the output..
    printf("\nTest completed OK!\n");
    getch();

    ::CoUninitialize();
}

///////////////////////////////////////////////////////////
//                                                       //
//      Test Function                                    //
//                                                       //
///////////////////////////////////////////////////////////

void Test(void)
{
    // Define Connection object pointer.
    // Initialize pointers on define.
    // These are in the ADODB::  namespace
    _ConnectionPtr pConnection = NULL;
    _CommandPtr pCmd = NULL;
    _ParameterPtr pPrm = NULL;
    _RecordsetPtr pRs = NULL;

    try
    {
        // Open a connection using OLE DB syntax.
        TESTHR(pConnection.CreateInstance(__uuidof(Connection)));
        printf("ADO Version: %s\n\n", (LPCSTR)pConnection->Version);
        pConnection->ConnectionString = "Provider=SQLOLEDB.1;Data Source=(LOCAL);Initial Catalog=Pubs;Username=sa;Password=sa";
        pConnection->Open("","","",adConnectUnspecified);

        // Create Command object for stored procedure call
        TESTHR(pCmd.CreateInstance(__uuidof(Command)));
        pCmd->ActiveConnection = pConnection;
        pCmd->CommandText = "byroyalty";

        // Define command parameter
        pPrm = pCmd->CreateParameter("percentage", adInteger, adParamInput, sizeof(long), (long)100);
        pCmd->Parameters->Append(pPrm);

        // Execute stored procedure
        pRs = pCmd->Execute(NULL, NULL, adCmdStoredProc);
        _bstr_t bstrAUID;

        while (!pRs->EndOfFile)
        {
            bstrAUID = pRs->Fields->GetItem("au_id")->Value;
            printf("%s\n", (LPCSTR) bstrAUID);
    
            pRs->MoveNext();
        }

        // Cleanup objects before exit
        pRs->Close();
        pConnection->Close();
    }
    catch(_com_error &e)
    {
        PrintComError(e);
    }
}

///////////////////////////////////////////////////////////
//                                                       //
//      PrintComError Function                           //
//                                                       //
///////////////////////////////////////////////////////////

void PrintComError(_com_error &e)
{
    _bstr_t bstrSource(e.Source());
    _bstr_t bstrDescription(e.Description());

    // Print Com errors.  
    printf("Error\n");
    printf("\tCode = %08lx\n", e.Error());
    printf("\tCode meaning = %s\n", e.ErrorMessage());
    printf("\tSource = %s\n", (LPCSTR) bstrSource);
    printf("\tDescription = %s\n", (LPCSTR) bstrDescription);
}
Re: Падает ADO при exception
От: Юнусов Булат Россия  
Дата: 13.01.04 17:23
Оценка:
Это известная багофича, надо либо занулять их явно после использования
    // вся кухня

    pConnection = NULL;
    pCmd = NULL;
    pPrm = NULL;
    pRs = NULL;

    ::CoUninitialize();
    return 0;
}

либо, как уже было сказано обьявлять в блоке
Re: Падает ADO при exception
От: _Stranger_  
Дата: 14.01.04 11:16
Оценка: 5 (1)
Я победил!

В папке %ProgramFiles%\Microsoft Visual Studio\VC98\Bin есть файл с2.dll.
Как я выяснил, c2.dll идет с Processor Pack.
У меня стоял Processor Pack 5, в котором c2.dll имеет версию 13.0.9044.0.
При замене файла c2.dll на более раннюю версию, проблемы исчезают.
Например, на Processor Pack 4, в котором c2.dll имеет версию 13.0.8943.0.

Всем спасибо за участие и помощь!
Re[2]: Падает ADO при exception
От: Demoniada Россия  
Дата: 14.01.04 11:32
Оценка:
Здравствуйте, _Stranger_, Вы писали:

_S_>Я победил!


_S_>В папке %ProgramFiles%\Microsoft Visual Studio\VC98\Bin есть файл с2.dll.

_S_>Как я выяснил, c2.dll идет с Processor Pack.
_S_>У меня стоял Processor Pack 5, в котором c2.dll имеет версию 13.0.9044.0.
_S_>При замене файла c2.dll на более раннюю версию, проблемы исчезают.
_S_>Например, на Processor Pack 4, в котором c2.dll имеет версию 13.0.8943.0.

_S_>Всем спасибо за участие и помощь!


Монстр!

Толко не осталось как-то полной ясности, а почему тогда
1) более новая версия работает менее правильно
2) мы с тобой — единственные пострадавшие. В конце концов сам микрософт на VB что-ли пишет? Или просто является особым извратом пользоваться ADO в приложениях на C++?
Да хранит вас господь в сухом прохладном месте...
Re[3]: Падает ADO при exception
От: _Stranger_  
Дата: 14.01.04 11:57
Оценка:
Здравствуйте, Demoniada, Вы писали:

1) более новая версия работает менее правильно

Пофиксены старые баги, добавлены новые.

2) мы с тобой — единственные пострадавшие. В конце концов сам микрософт на VB что-ли пишет? Или просто является особым извратом пользоваться ADO в приложениях на C++?

Просто многие не ставят Processor Pack — он, в основном, нужен тем, кто пользуется ассемблерными вставками.
Re[2]: Падает ADO при exception
От: Юнусов Булат Россия  
Дата: 14.01.04 12:10
Оценка:
Здравствуйте, _Stranger_, Вы писали:

Да при чем тут это.
Та же ситуация воспроизведется нижеприведенным кодом если раскомментировать зануление.
Смартпоинтер выходит из области видимости когда ::CoUninitialize() уже вызвано с вытекающими.
int _tmain(int argc, _TCHAR* argv[])
{
    ::CoInitialize(NULL);

    _ConnectionPtr pConnection(__uuidof(Connection));
    // pConnection = NULL;

    ::CoUninitialize();

    return 0;
}
Re[3]: Падает ADO при exception
От: _Stranger_  
Дата: 14.01.04 12:20
Оценка:
Здравствуйте, Юнусов Булат, Вы писали:

Да при чем тут это.
Та же ситуация воспроизведется нижеприведенным кодом если раскомментировать зануление.
Смартпоинтер выходит из области видимости когда ::CoUninitialize() уже вызвано с вытекающими.

Согласен, Ваш пример действительно падает на Access Violation. Но у меня в примере вся работа с объектами ADO сосредоточена в одной функции, вызываемой из main(), смотрите код
Автор: _Stranger_
Дата: 13.01.04
. Как Вы прокомментируете этот пример?
Re[3]: Падает ADO при exception
От: Demoniada Россия  
Дата: 14.01.04 12:28
Оценка:
"Юнусов Булат" <forum@rsdn.ru> wrote in message news:506488@news.rsdn.ru...
> Здравствуйте, _Stranger_, Вы писали:
>
> Да при чем тут это.
> Та же ситуация воспроизведется нижеприведенным кодом если раскомментировать зануление.
> Смартпоинтер выходит из области видимости когда ::CoUninitialize() уже вызвано с вытекающими.
>
> int _tmain(int argc, _TCHAR* argv[])
> {
> ::CoInitialize(NULL);
> 
> _ConnectionPtr pConnection(__uuidof(Connection));
> // pConnection = NULL;
> 
> ::CoUninitialize();
> 
> return 0;
> }
>


Не, не в этом дело.
У меня вообще ошибка возникала в такой структуре кода:

CoInitialize

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

CoUninitialize

Так что как видишь не в этом дело: если ADO-операция выполняется без ошибок — все ок. А вот если возникла ошибка, приложение рушится.
Насколько я помню, это воспроизводилось даже в дебагере.
Posted via RSDN NNTP Server 1.7 "Bedlam"
Да хранит вас господь в сухом прохладном месте...
Re[4]: Падает ADO при exception
От: Юнусов Булат Россия  
Дата: 14.01.04 13:06
Оценка:
Здравствуйте, _Stranger_, Вы писали:

А что, после перекладывания всей адошной кухни (включая обьявления) в функцию (или даже просто "за фигурные скобки"), продолжаем получать АВ? Сильно сомневаюсь.
Re[5]: Падает ADO при exception
От: _Stranger_  
Дата: 15.01.04 07:11
Оценка:
Здравствуйте, Юнусов Булат, Вы писали:

А что, после перекладывания всей адошной кухни (включая обьявления) в функцию (или даже просто "за фигурные скобки"), продолжаем получать АВ? Сильно сомневаюсь.

Именно так. Можете не сомневаться. При этом было установлено, что источник Access Violation находится в том, что при возникновении exception в ADO-шной функции выход из нее осуществляется некорректно, при этом повреждается стек. Отсюда и вытекающие.
В указанном примере Access Violation перестал появляться только после замены C2.DLL на более раннюю версию.
Кстати, предлагаю Вам самим попробовать заменить C2.DLL на ту версию, что идет в Processor Pack 5 и скомпилировать у себя этот
Автор: _Stranger_
Дата: 13.01.04
пример.
Интересно будет сравнить результаты.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.