PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : MFC/C++ Programm Kontrollausgabe Variablenwert


Matrix316
2005-08-18, 19:18:18
Gibts eine schnelle und einfache Möglichkeit, dass ich während eines MFC Programms, also so schön mit Fenster und allem drum und dran, im Ausgabebereich vom Visual Studio oder so mir den Wert einer Variable ausgeben lassen kann? Cout funktioniert irgendwie nicht. Oder gibts schnell ne schnelle Methode für ein schnelles Fenster was sich parallel zum Hauptprogramm öffnet und in das ich den Wert einer Variable ausgeben kann?

Coda
2005-08-18, 19:30:59
OutputDebugString

Matrix316
2005-08-18, 21:07:56
Juhu! Danke.

Matrix316
2005-08-19, 00:26:46
Hmmm, weißt du oder jemand anderes vielleicht, warum ich einen int Wert nicht casten bzw. ausgeben kann? Dass es einen Wert gibt, weiß ich weil er mit if abgefragt werden kann. Der Wert wird als Parameter einer statischen Callbackfunktion übergeben:

int blabla(int diff)
{
if (diff > 250 && diff < 300)
{
OutputDebugString("Diff Wert > 250 oder < 300");
OutputDebugString((LPCTSTR) diff);
}
OutputDebugString("Diff nicht im Bereich");
OutputDebugString((LPCTSTR) diff);
return NoError;
}

Als Fehler gibts diesen hier:


Diff nicht im Bereich
OutputDebugString faulted during output
Nicht abgefangene Ausnahme in Blabla.exe (KERNEL32.DLL): 0xC0000005: Access Violation.
Nicht abgefangene Ausnahme in Blabla.exe (KERNEL32.DLL): 0xC0000005: Access Violation.
Diff Wert > 250 oder < 300
OutputDebugString faulted during output
Diff nicht im Bereich
OutputDebugString faulted during output
Nicht abgefangene Ausnahme in Blabla.exe (KERNEL32.DLL): 0xC0000005: Access Violation.
Nicht abgefangene Ausnahme in Blabla.exe (KERNEL32.DLL): 0xC0000005: Access Violation.
Nicht abgefangene Ausnahme in Blabla.exe (KERNEL32.DLL): 0xC0000005: Access Violation.
Nicht abgefangene Ausnahme in Blabla.exe (KERNEL32.DLL): 0xC0000005: Access Violation.

Matrix316
2005-08-19, 11:11:27
Ok, ich weiß warums einen Fehler gab. Weiß zufällig jemand wie man int zu LPCSTR casten kann?

EDIT: Hat sich erledigt. :rolleyes:

Coda
2005-08-19, 13:18:28
Du hast noch nicht viel C/C++ Erfahrung oder? Du kannst doch nicht einfach einen int auf einen pointer casten und erwarten, dass etwas sinnvolles dabei rauskommt ;)

Für solche Dinge ist die STL+Boost recht praktisch:

#include <boost/lexical_cast.hpp>
#include <string>

...

std::string output = boost::lexical_cast<std::string>(diff);
OutputDebugString(output.c_str());Edit: Der CString von den MFC sollte das aber auch können.

Matrix316
2005-08-19, 14:53:27
Sagen wir mal so ich hab den Wald nicht vor Bäumen gesehen, bzw. nicht dran gedacht dass LPCSTR ja ein Pointer ist. ;)

Ich habs jetzt mit itoa(...) gemacht.


int blabla(int diff)
{
LPCTSTR variable;
char buffer[20];
itoa(diff, buffer, 10);
variable = (LPCTSTR) buffer;
.
.

Coda
2005-08-19, 19:23:43
Waaaa... *wegrenn* ;)

ShadowXX
2005-08-19, 19:55:34
Sagen wir mal so ich hab den Wald nicht vor Bäumen gesehen, bzw. nicht dran gedacht dass LPCSTR ja ein Pointer ist. ;)

Ich habs jetzt mit itoa(...) gemacht.


int blabla(int diff)
{
LPCTSTR variable;
char buffer[20];
itoa(diff, buffer, 10);
variable = (LPCTSTR) buffer;
.
.


Nimm doch einfach das TRACE-Macro.

TRACE1("%ld",diff);

Codas Variate ist natürlich auch sehr schön...mit einem CString würde es dann so aussehen:

CString out;

For(......
{
.
.
out.Format("%ld",diff);
OutputDebugString(out); // oder TRACE(out);
.
.
}

Matrix316
2005-08-20, 13:44:56
Also der Code ist eigentlich egal, weil es nicht zum Programm dazu gehört, sondern wie schon gesagt ich nur wissen wollte welcher Wert eine Variable hat.

Coda
2005-08-20, 16:54:27
Das sieht man doch aber auch so im Debugger :|

Matrix316
2005-08-20, 17:26:42
Das sieht man doch aber auch so im Debugger :|
Mitm Debugger kenn ich mich nicht so aus. Hab ich bis jetzt noch nie gebraucht. :wink:

Neomi
2005-08-20, 17:50:09
Mitm Debugger kenn ich mich nicht so aus. Hab ich bis jetzt noch nie gebraucht. :wink:

Dann solltest du dich schnell ranmachen an den Debugger. Ein mächtiges Werkzeug, das man nutzen können sollte, bevor man darauf angewiesen (und unter Zeitdruck) ist.

Matrix316
2005-08-22, 19:22:56
Nur hilft mir der Debugger auch nicht, wenn er irgend einen Assemblertext einblendet. Ich hab hier z.B. einen Fehler wo ich weiß an welcher Stelle der Fehler passiert im Code und den dazugehörigen Assemblertext, aber wie kann der Debugger mir jetzt helfen?

0xC0000005: Access Violation

Wie hilft mir der Debugger damit?

Neomi
2005-08-22, 20:17:08
Wenn du eine Release-Exe ausführst und dich dann bei einem solchen Fehler mit dem Debugger einklinkst, bringt das wirklich nicht viel. Du kannst aber das Programm im Debugmodus starten, da kannst du dann die Anweisungen im Originalquelltext Schritt für Schritt durchgehen und Werte anzeigen lassen.

Matrix316
2005-08-22, 22:02:32
Und wie? Wo wird denn da was angezeigt?

Coda
2005-08-22, 22:18:18
Ich nehm mal an du hast Visual Studio. Wenn du eine Debug-Executable kompiliert hast, siehst du bei einer Access-Violation entweder die Code-Zeile die sie verursacht hat oder du kannst im Call-Stack zu dem Aufruf zurückgehen der sie verursacht hat.

Neomi
2005-08-22, 22:20:40
Das ist viel zu umfangreich, um es in einer kurzen Antwort abzuhandeln. Schau dich mal hier um, da wirst du fündig...
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vsdebug/html/_asug_how_do_i_topics3a_debugging.asp

Matrix316
2005-08-22, 22:49:37
Ich nehm mal an du hast Visual Studio. Wenn du eine Debug-Executable kompiliert hast, siehst du bei einer Access-Violation entweder die Code-Zeile die sie verursacht hat oder du kannst im Call-Stack zu dem Aufruf zurückgehen der sie verursacht hat.

Aber wenn ich weiß welche Zeile den Fehler verursacht, aber nicht warum? Besonders wenn die gleiche Zeile schon woanders im Programm verwendet wird und dort funktioniert?

Neomi
2005-08-22, 23:03:22
Aber wenn ich weiß welche Zeile den Fehler verursacht, aber nicht warum? Besonders wenn die gleiche Zeile schon woanders im Programm verwendet wird und dort funktioniert?

Der Debugger kann dir nur helfen, lösen mußt du die Probleme als Programmierer aber selbst. Woher sollte der Debugger auch wissen, was genau du mit deinem Code bezweckst?

Eine Zeile Programmcode steht selten für sich alleine, der Kontext ist sehr wichtig. Deshalb kann das, was an der einen Stelle richtig ist, an der anderen Probleme verursachen.

Matrix316
2005-08-23, 16:02:32
Gibts eigentlich ne Möglichkeit aus einer statischen Callbackfunktion auf nichtstatische Funktionen/Variablen/Objekte zuzugreifen?

Ich hab schonmal was probiert um über eine "Wrapperfunction" die eigentliche Callbackfunktion non-static zu machen (in der Wrapperfunktion wird eine Variable und ein Zeiger auf die eigentliche Funktion übergeben), was in der Theorie auch geht, aber wenn ich eine bestimmte Methode in der non-static Callbackfunktion aufrufe stürzt es ab, während die gleiche Weise in einer Funktion der gleichen Klasse auch benutzt wird und dort nicht abstürzt - allerdings ist das keine Callbackfunktion...

Neomi
2005-08-23, 16:48:26
Gibts eigentlich ne Möglichkeit aus einer statischen Callbackfunktion auf nichtstatische Funktionen/Variablen/Objekte zuzugreifen?

Wenn du einen Pointer auf das Objekt hast, ja. Hier ein kurzes Beispiel:

class Dings
{
public:
static int DingsCallback (int iDings1, int iDings2, LPARAM lParam);

int TheRealCallback (int iDings1, int iDings2);
int CallTheCallback (int iDings1, int iDings2);
};

int Dings::DingsCallback (int iDings1, int iDings2, LPARAM lParam)
{
return ((Dings *) lParam)->TheRealCallback (iDings1, iDings2);
}

int Dings::TheRealCallback (int iDings1, int iDings2)
{
return 42;
}

int Dings::CallTheCallback (int iDings1, int iDings2)
{
return DingsCallback (iDings1, iDings2, (LPARAM) this);
}

Matrix316
2005-08-23, 19:34:04
Ja so hab ich das mit der "Wrapperfunction" gemacht. (hier: DingsCallback)

Nur was ist wenn ich in TheRealCallback eine Funktion aufrufe, die in der statischen Callbackfunktion nicht gehen würde (wenn dann kommt: Fehler, aufruf einer nonstatic member function nicht möglich). Kann es da irgendwie Probleme geben?

Matrix316
2005-08-26, 22:29:51
Gibts eigentlich einen bestimmten Grund warum ein MFC programmiertes Programm einfriert? Also einfach stehen bleibt und nix mehr macht. Gibts da irgendein Trick wie man das aktuelle "Document" aktivieren kann?

Ich hab hier eine Methode die einen Vorgang abbricht. Den kann ich über einen Button aktivieren. Wenn ich jetzt aber irgendwo im Programm ein Object einer Klasse erstelle und mit diesem die Methode aufrufe:

object->irgendwas->irgendwo->StopDingens();

hört es zwar auf, aber das Programm ist gefreezed und muss über den Taskmanager beendet werden.

Gibts da eine allgemeine Lösung oder hängts am Programm selbst?

Diese Zeile wird in einer Callbackfunktion aufgerufen. Sie ist aber ähnlicherweise auch in anderen Methoden in anderen Klassen vorhanden, nur fehlt da das object. Also da gehts so:

irgendwas->irgendwo->StopDingens();

Wieso freezed es bei der ersten Version und beim zweiten gehts?

Neomi
2005-08-27, 00:11:42
Nur was ist wenn ich in TheRealCallback eine Funktion aufrufe, die in der statischen Callbackfunktion nicht gehen würde (wenn dann kommt: Fehler, aufruf einer nonstatic member function nicht möglich). Kann es da irgendwie Probleme geben?

Da du über den Pointer (übergeben per lParam) die Objektbindung hast, kannst du natürlich aus dieser nicht-statischen Methode auch jede andere nicht-statische Methode aufrufen.

Was dein Problem mit dem Freeze angeht: nein, es gibt keine allgemeine Lösung für Probleme. Ohne Quelltexte läßt sich da nichts genaueres sagen.

Gast
2005-08-27, 04:26:43
Gibts eigentlich einen bestimmten Grund warum ein MFC programmiertes Programm einfriert? Also einfach stehen bleibt und nix mehr macht. Gibts da irgendein Trick wie man das aktuelle "Document" aktivieren kann?

Ich hab hier eine Methode die einen Vorgang abbricht. Den kann ich über einen Button aktivieren. Wenn ich jetzt aber irgendwo im Programm ein Object einer Klasse erstelle und mit diesem die Methode aufrufe:

object->irgendwas->irgendwo->StopDingens();

hört es zwar auf, aber das Programm ist gefreezed und muss über den Taskmanager beendet werden. ohne dein Problem jetzt wirklich ganz verstanden zu haben klingt das für mich so als würdest du da einen zeitaufwändigen Vorgang laufen haben. Bei einem solchen freezed das Programmfenster für den Zeitraum, in dem der Vorgang läuft, wenn du nicht dafür sorgst, daß das Programm während des laufenden Vorganges seine Ereigniswarteschlange abfragen kann.

Um dies zu gewährleisten, gibt es zwei Möglichkeiten:

1) du programmierst den Vorgang so, daß er an klar definierten Stellen unterbrochen wird, und während der Unterbrechung dann die Ereigniswarteschlange abgefragt wird. In der MFC gibt es hierzu die Methode OnIdle(), ich glaub von der Klasse CWinApp. Diese Methode mußt du überschreiben. Nimm z.B. an, dein Vorgang addiert alle ganzen Zahlen von 0 bis 1000000000. Das ließe sich dann etwa so realisieren

...::OnIdle()
{
static int i=0;
static double dSum=0;
static int loop=0;
int iSumsPerLoop=1000000;
int iNeededLoops = 1000000000 / iSumsPerLoop;

if (loop < iNeededLoops)
{
for (i = loop*iSumsPerLoop; i < (loop+1)*iSumsPerLoop; i++)
{
dSum += i;
}
loop++;
}
}

der Summationsprozeß wird so immer nach 1000000 Summationen unterbrochen, die Ereigniswarteschlange abgefragt, und der Prozeß dann fortgesetzt. i, dSum und loop sind statisch, damit sie nach dem ersten Durchlauf von OnIdle() nicht wieder neu initialisiert werden, sondern ihre Werte aus dem vorigen Durchlauf behalten.

2) die modernere Methode arbeitet mit Multithreading. Du legst für den zeitaufwändigen Vorgang einen eigenen Thread an, der parallel zum Hauptthread läuft, in dem u.a. die Ereigniswarteschlange versorgt wird. Windows erledigt dann intern das Umschalten zwischen den beiden Threads. Nachteil: du kannst nicht wissen, wann genau das Umschalten zwischen den Threads passiert. Das ist kritisch, wenn beide Threads auf die gleichen Daten zugreifen, z.B. wenn der Nebenthread etwas auf das Programmfenster ausgibt, das ja vom Hauptthread kontrolliert wird. Stichworte sind hier Thread-Safety und Critical Section.

Matrix316
2005-08-27, 20:58:57
Hmmm... irgendwie kompliziert. Gibts keine irgendwelche Methode die quasi weiter gibt, dass die Sache die gerade gemacht wird fertig ist und das Programm freigegeben wird? In Java gibts doch glaube ich sowas...

Das komische ist, dass die Sache in anderen Methoden ebenfalls aufgerufen wird, aber es dort keine Probleme gibt. Nur in meiner Callbackfunktion gibts entweder ein Access Violation oder es hängt sich fest. Wenn ich es dem object der eigenen Klasse zuweise hängt es fest, wenns zu einem object einer anderen Klasse ist (auf die man zugreifen kann) gibts den AccessViolation Dingens Fehler.

EDIT: Ich hab mal was probiert mit Critical Section http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vclib/html/_MFC_CCriticalSection.asp hat aber auch nicht funktioniert.

Matrix316
2005-08-28, 02:38:06
Kann es sein, dass es Probleme gibt, wenn in einer aufgerufenen Methode eine Variable oder so protected ist?

Coda
2005-08-28, 03:06:23
"eine Variable oder so protected ist" :|

Geht das auch etwas genauer?

Matrix316
2005-08-28, 15:17:58
"eine Variable oder so protected ist" :|

Geht das auch etwas genauer?

Stell dir vor:


class irgendwas
{
private:
int blablabla

protected:
int variabledieprotectedistoderso
};

:wink: