Kann sich irgend jemand dieses Phänomen erklären - unbeh. Ausnahme ADO/Oracle



  • Hallo zusammen,

    ich bin zwar neu in C++/MFC, aber so etwas habe ich noch nicht gesehen. Vielleicht steigt ja einer von euch da durch.

    Habe mit ner Klasse für Datenbank-Verbindung etc. angefangen. Zu erst einmal die Cpp der Klasse:

    .
    .
    .
    #import "C:\Progs\Common\System\ado\msado26.tlb" no_namespace rename( "EOF", "EndOfFile" )
    .
    .
    
    CConDB::CConDB()
    {
    	CoInitialize(NULL);
    	pRS.CreateInstance(__uuidof(Recordset));
    	pCN.CreateInstance(__uuidof(Connection));
    	pCOM.CreateInstance(__uuidof(Command));
    	//m_CnString = "Provider=SQLOLEDB.1;Persist Security Info=False;User ID=x;Password=x;Initial Catalog=x;Data Source=(local);Integrated Security=SSPI;";
    	m_CnString = "Provider=MSDAORA;data source=x;user id=x;password=x;";
    }
    
    CConDB::~CConDB()
    {
    	pCN->Close();
    	CoUninitialize();
    	pRS = NULL;
    	pCN = NULL;
    	pCOM = NULL;
    	AfxMessageBox("zerstört");
    }
    
    void CConDB::Select(const _bstr_t SQLStatement)
    {
    	pCN->CursorLocation = adUseClient;
    	pCN->Open(m_CnString,"","",NULL);
    	pCOM->ActiveConnection = pCN;
    	pCOM->CommandType = adCmdText;
    	pCOM->CommandText = SQLStatement;
    	pRS = pCOM->Execute(NULL,NULL,NULL);
    }
    

    In der View versuche ich nun wie folgt die Daten zu lesen usw.

    int CChildView::OnCreate(LPCREATESTRUCT lpCreateStruct)
    {
    	if (CWnd::OnCreate(lpCreateStruct) == -1)
    		return -1;
    
    			//TreeView zeichnen	
    		m_WndTreeView.Create(WS_CHILD|WS_VISIBLE|TVS_LINESATROOT|TVS_HASBUTTONS|TVS_HASLINES|WS_BORDER,CRect(20, 20, 300, 200),this,0);
    		CConDB* RS = new CConDB();
    		RS->Select("Select * from ems$ta_userdata");
    
    		_bstr_t valField1;	
    		if (!RS->pRS->EndOfFile || !RS->pRS->BOF)
    		{
    			while(!RS->pRS->EndOfFile)
    			{
    				valField1 = RS->pRS->Fields->GetItem("nname")->Value;
    				HTREEITEM hNode1 = m_WndTreeView.InsertItem(valField1);
    				RS->pRS->MoveNext();
    			}
    		}
    
    		AfxMessageBox("ENDE");
    		//delete(RS);
    
    		return 0;
    }
    

    Lasse ich so wie es oben steht, das delete auskommentiert, läuft alles prima.
    Will ich jedoch den Destruktor mit dem delete aufsuchen, kommt die folgende unbehandelte Ausnahme, die im Disassembler dort steht:

    778813B1 CC int 3

    Der QuickWatch sagt mir:

    778813B1 CC CXX0013: Error: missing operator

    Das war aber noch nicht alles. Mit dem SQL Server bekomme ich diesen Fehler nicht. Mit oder ohne delete spielt dabei kein Rolle.

    Dann habe ich noch mit Oracle getestet, was passiert, wenn ich im Destruktor alles auskommentiere. Auch hier, gleicher Effekt, gleiche FM. Und ich habe es mit virtual gestestet. Ebenfalls Fehlermeldung. Usw. Das war nicht alles was ich getestet habe. Unter anderem noch, direkt mit nem RS.Open. Oder aber mit verschiedenen Types. Es ist immer dasselbe. Mit SQL Server keine probleme. Mit Oracle diese Fehlermeldung.

    Mit net framework auch getestet. Da habe ich bei oracle ebenfalls keine Probleme. Habe auch alle ADO-versionen durchgetestet.

    ICH WEISS NICHT MEHR WEITER. HILFE 🙂



  • Warum machst du bei dem delete Klammern um RS ?

    [edit]
    zu
    RS->pRS->EndOfFile || !RS->pRS->BOF

    Sind EndOfFile und BOF Variablen oder Funktionen ?
    [/edit]



  • weil das so in allen schlauen Büchern drin steht. Kannst die Klammern aber auch weglassen, hat mit dem Problem nix zu tun 🙂



  • Da sind mir ein paar Kleinigkeiten aufgefallen:

    1.) Bist du sicher das du bei jedem Konstruktor/Destruktor wirklich CoInitialize/CoUninitialize
    aufrufen willst. Üblicherweise macht man sowas nur einmal pro Anwendung, es sei denn
    das ganze ist ne Multithreaded Application. Weisst du überhaupt wofür diese
    Funktionen gut sind.

    2.) Handelt es sich bei:
    pRS = NULL;
    pCN = NULL;
    pCOM = NULL;
    um Smart-Pointer. Wenn nein, produziert obiger Code Speicherleichen, andernfalls
    kannst du das NULL-Setzen dann gleich ganz weglassen.

    3.) Alle COM-Aufrufe können COM-Errors auslösen die du unbedingt abhandeln
    solltest.
    Andernfalls steht dein Programm Ruckzuck im Wald.

    Offensichtlich bist du neu in C++/MFC, denn du weisst augenscheinlich nicht
    was du da tust. Zum (erfolgreichen) Programmieren ist dummerweise mehr nötig
    als auf ein paar Knöpfe in einem Wizard zu drücken. Und ein Thema wie COM ist
    wirklich nicht trivial. 🙄 🙄



  • @Chew-Z:
    Habe zwar keinen einzigen Wizard-Knopf gedrückt, aber bitte schön.
    Und eine Beantwortung meiner Frage ist es ebenfalls nicht.



  • isabeau schrieb:

    [edit]
    zu
    RS->pRS->EndOfFile || !RS->pRS->BOF

    Sind EndOfFile und BOF Variablen oder Funktionen ?
    [/edit]

    Attribute



  • Ich hatte vor meinem Resumee noch mehrere Fragen hast du die dir mal durchgelesen
    oder verträgst du keine Kritik.

    "int 3" ist übrigen der Assemblercode für "DebugBreak". Und dafür können durchaus
    die angeführten Missverständnisse verantwortlich sein.
    Und das .NET was völlig anders ist, ist dir hoffentlich klar.



  • Chew-Z schrieb:

    Ich hatte vor meinem Resumee noch mehrere Fragen hast du die dir mal durchgelesen
    oder verträgst du keine Kritik.

    "int 3" ist übrigen der Assemblercode für "DebugBreak". Und dafür können durchaus
    die angeführten Missverständnisse verantwortlich sein.
    Und das .NET was völlig anders ist, ist dir hoffentlich klar.

    Um das mal mit dir abzuschliessen. Ich brauche dir auf die ersten beiden Punkte nicht antworten, da die Antworten eigentlich schon im Thread stehen
    a) Angefangen C++/MFC
    b) Angefangen mit Klasse

    Des Weiteren habe ich deinen Beitrag nicht als Kritik verstanden. Und wenn du meinen Thread richtig gelesen hättest, dann wüsstest du danach, dass deine angesprochenen Punkte nicht dafür verantwortlich sein können.

    Thema .Net kenne ich mich gut aus, hilft mir aber hier ebenfalls nicht weiter.
    Warum ich dotnet angesprochen habe, ist ebenfalls in meinem Thread nachlesbar.



  • Da sind definitiv keine Antworten auf meine Fragen die du vielleicht gelesen, aber offentsichtlich nicht verstanden hast. Aber da du ja sowieso alles besser weisst.



  • Chew-Z schrieb:

    Da sind definitiv keine Antworten auf meine Fragen die du vielleicht gelesen, aber offentsichtlich nicht verstanden hast. Aber da du ja sowieso alles besser weisst.

    Ganz genau, ich habe deine Fragen nicht verstanden. Vor allem habe ich einen Thread aufgemacht, der da hieß, stellt mir bitte Fragen. Du solltest, bevor du andere Menschen irgendwo in die Ecke stellst, erst einmal anfangen über dich und deine Art und Weise nach zu denken. Das wird dir vielleicht in Zukunft helfen, anderen Menschen zu helfen. Du versucht meiner Meinung nach keine Hilfe anzubieten. Wenn du mein Problem lösen könntest, hättest du geschrieben, woran es liegt.

    Wenn ich also in meinem Beitrag klar und deutlich formuliere, dass dieser Fehler augenscheinlich nur mit Oracle auftritt, wird es wohl kaum daran liegen, dass ich jetzt CoInitialize im Konstruktor aufrufe und diesen besser nur eimal aufrufe usw. Ebenfalls ist nachzulesen, dass ich den Kosntruktor auch leer lassen kann, und habe trotzdem bei Oracle diese FM, bei anderen Datenbanken eben nicht.

    Wenn du es jetzt immer noch nicht mein Anliegen verstanden hast, dann ist es doch ok, dann sag bitte auch nix mehr. Ich will hier keine Grundsatzdiskussionen führen. In diesem Sinne, danke für deine Beiträge.



  • Mag schon sein, dass das nur bei Oracle auftritt. Solange du aber keine Fehlerwerte abfragst, wirst du nie herausbekommen, warum.



  • Ringding schrieb:

    Mag schon sein, dass das nur bei Oracle auftritt. Solange du aber keine Fehlerwerte abfragst, wirst du nie herausbekommen, warum.

    Vorsicht, habe ich auch schon vorgeschlagen, aber Anregungen dieser Art, die ja
    nichts mit seinem Problem zu tun haben, mag er nicht. 😃 😃



  • wie soll ich das eurer meinung nach, anstellen. was genau soll ich abfangen. bevor ich gepostet habe, hatte ich auch u.a. try und catch drin, aber das ding lief nie in den catch, sondern es erschien immer nur die geschriebene fehlermeldung nach dem catch vor dem return.



  • Jede COM-Funktion liefert einen Fehlercode zurück. Dieser muss irgendwie abgefragt werden. "Irgendwie" schreibe ich deshalb, weil du schauen musst, ob die Wrapper vom #import das schon machen - dann wird nämlich im Fehlerfall eine Exception geworfen, die du dann fangen kannst.



  • hatte ich mit

    try und catch(_com_error err) versucht. da lief nix auf fehler. dann habe ich zum testen, das sql-statement einfach falsch geschrieben, dann lief er dort rein. somit wusste ich also, dass zu mindestens dort bei fehler (wenn com) rein gesprungen wird. im moment kann ich also nur vermuten, dass es sich dabei nicht um einen com-fehler handelt. ich werde morgen noch mal umbauen, um zu gucken, ob ich irgendwie einen fehler abfangen kann, dann melde ich mich noch mal.

    thx an alle, bis dahin, auch an dich Chew-Z, ich meinte es sicher nicht böse 🙂



  • Falls du die durch #import generierten Smart-Pointer verwendest, werden
    üblicherweise Exceptions vom Typ _com_error geworfen. Falls du die
    raw-Interfaces benutzt musst den zurückgelieferten HRESULT auswerten.
    Erst wenn du sichergestellt hast das ALL deine COM-Aufrufe fehlerfrei
    durchgehen kann man das weitere Vorgehen diskutieren.



  • so habe noch mal ein bißchen was getestet, aber das ergebnis bleibt wie gestern schon geschildert, immer dasselbe. es handelt sich also wohl nicht um einen com-fehler.

    der ablauf sieht so aus: es erscheint die meldung "vor delete". Dann kommt die Meldung aus dem Destruktor "Destruktor" und dann kommt der Fehler. Die spannende Frage ist, warum tritt das nur bei Oracle auf und alle anderen Datenbanken laufen durch den Destruktor und geben dann die meldung "nach delete" aus.

    int CChildView::OnCreate(LPCREATESTRUCT lpCreateStruct)
    {
    	if (CWnd::OnCreate(lpCreateStruct) == -1)
    		return -1;
    
    	try
    	{
    		m_WndTreeView.Create(WS_CHILD|WS_VISIBLE|TVS_LINESATROOT|TVS_HASBUTTONS|TVS_HASLINES|WS_BORDER,CRect(20, 20, 300, 200),this,0);
    		CConDB* RS = new CConDB();
    		RS->Select("Select * from ems$ta_userdata");
    		AfxMessageBox("vor delete");
    		delete RS;
    		AfxMessageBox("nach delete");
    	}
    	catch(_com_error err)
    	{
    		_bstr_t str(err.Description());
    		AfxMessageBox(str);
    	}
    		return 0;
    }
    
    CConDB::CConDB()
    {
    	pRS.CreateInstance(__uuidof(Recordset));
    	pCN.CreateInstance(__uuidof(Connection));
    	pCOM.CreateInstance(__uuidof(Command));
    	//m_CnString = "Provider=SQLOLEDB.1;Persist Security Info=False;User ID=x;Password=x;Initial Catalog=x;Data Source=(local);Integrated Security=SSPI;";
    	m_CnString = "Provider=MSDAORA;data source=x;user id=x;password=x;";
    }
    
    CConDB::~CConDB()
    {
    	try
    	{
    	AfxMessageBox("Destruktor");
    	//pCN->Close();
    	//CoUninitialize();
    	}
    	catch(_com_error err)
    	{
    		_bstr_t str(err.Description());
    		AfxMessageBox(str);
    	}
    }
    
    void CConDB::Select(const _bstr_t SQLStatement)
    {
    	pCN->CursorLocation = adUseClient;
    	pCN->Open(m_CnString,"","",NULL);
    	pCOM->ActiveConnection = pCN;
    	pCOM->CommandType = adCmdText;
    	pCOM->CommandText = SQLStatement;
    	pRS = pCOM->Execute(NULL,NULL,adCmdText);
    }
    


  • Habe das ganze mal im Release-Modus gestartet. Da taucht der Fehler nicht mehr auf, dafür aber ein anderer. Und zwar in der wincore.cpp, wenn ich die ganze App schliesse, in:

    [cpp]
    LRESULT CWnd::WindowProc(UINT message, WPARAM wParam, LPARAM lParam)
    {
    // OnWndMsg does most of the work, except for DefWindowProc call
    LRESULT lResult = 0;
    if (!OnWndMsg(message, wParam, lParam, &lResult))
    lResult = DefWindowProc(message, wParam, lParam);
    return lResult;
    }
    [/cpp]


Anmelden zum Antworten