Whenever I run a program through the debugger it will no longer allow my debug messages that I send to the windows API function OutputDebugString() to go where they are normally supposed to go (an external application that logs them). Somehow the debugger seems to entirely catch these debug messages and does not allow them to go through. Can I somehow disable this without entirely disabling the debugger?
Mailing lists / lazarus / 2010-07
disable the debugger capturing the OutputDebugString() messages
38 messages · 8 people · –
- BBernd 13
- SSven Barth 6
- RReimar Grabowski 5
- MMarc Weustink 4
- MMichael Van Canneyt 4
- MMichael Schnell 3
- +2 more
Reply by email Subscribe to this list Your subscription
Read-only archive. Use j and k to move between messages.
Bernd wrote 7 lines
OutputDebugString is meant to be captured by a debugger. Unfortunately this isn't shown anyware in Lazarus
Marc
2010/7/18 Marc Weustink :
OutputDebugString is meant to be captured by a debugger. Unfortunately this isn't shown anyware in Lazarus
Normally I use DebugView for that, its a little application that is extremely useful, I use the OutputDebugString() / DebugView combination for all kinds of development in other languages too, whenever I cannot easily use stdout for debugging I make myself a little drop-in replacement for the printf() or its equivalent in the used language and use that to format and output debug messages.
It is absolutely not understandable why GDB captures these messages while it is completely unable to display them in any meaningful manner. It will capture the messages (it will replace and eat the whole function call, not only the message!) and then declare them wrongly as "warnings" and bury them in all the other warnings it does generate, Lazarus does not have any chance to extract only the debug messages from the output of GDB even if it wanted to. These messages are basically lost, once GDB gets its hands on them. GDB completely sabotages the usage of OutputDebugString().
If there is no way to tell GDB to either stop intercepting these messages or at least display them in a more meaningful way or pass them on to where they were meant to go (the windows API) instead of silently *eating* the whole function call, then this is a bug in GDB. These debug messages are none of GDB's business as long as it does not provide any way do actually *display* them in a meaningful way.
Attached at the end is the debug output of the standard Lazarus empty one form project with one button and a debug message as it is seen in the debug output window.
My debug message is almost at the end.
If GDB cannot be made to stop its unwanted behavior would it then make sense to make Lazarus (optionally) filter out all messages that start with '&"warning: ' and display them separately? Maybe in the messages window?
Or alternatively to make it more generic make the debug-output window itself be able to filter the messages by type, make a list of checkboxes to tick for all the different types of messages (hide the prompt, input from lazarus to GDB, info, warning, error or everything else that can be easily distinguished)?
(gdb)
<-gdb-set confirm off>
^done
(gdb)
<-gdb-set new-console off>
^done
(gdb)
<-gdb-version>
~"GNU gdb (GDB) 7.0\n"
~"Copyright (C) 2009 Free Software Foundation, Inc.\n" ~"License GPLv3+: GNU GPL version 3 or later
<http://gnu.org/licenses/gpl.html>\n"
~"This is free software: you are free to change and redistribute it.\n" ~"There is NO WARRANTY, to the extent permitted by law. Type \"show copying\"\n"
~"and \"show warranty\" for details.\n"
~"This GDB was configured as \"mingw32\".\n"
~"For bug reporting instructions, please see:\n"
~"<http://www.gnu.org/software/gdb/bugs/>.\n"
^done
(gdb)
<-gdb-version>
~"GNU gdb (GDB) 7.0\n"
~"Copyright (C) 2009 Free Software Foundation, Inc.\n" ~"License GPLv3+: GNU GPL version 3 or later
<http://gnu.org/licenses/gpl.html>\n"
~"This is free software: you are free to change and redistribute it.\n" ~"There is NO WARRANTY, to the extent permitted by law. Type \"show copying\"\n"
~"and \"show warranty\" for details.\n"
~"This GDB was configured as \"mingw32\".\n"
~"For bug reporting instructions, please see:\n"
~"<http://www.gnu.org/software/gdb/bugs/>.\n"
^done
(gdb)
<-gdb-set env ALLUSERSPROFILE=C:\Dokumente und Einstellungen\All Users> ^done
(gdb)
<-gdb-set env APPDATA=C:\Dokumente und Einstellungen\bernd\Anwendungsdaten> ^done
(gdb)
<-gdb-set env CLIENTNAME=Console>
^done
(gdb)
<-gdb-set env CommonProgramFiles=C:\Programme\Gemeinsame Dateien> ^done
(gdb)
<-gdb-set env COMPUTERNAME=VBOX-577961E4>
^done
(gdb)
<-gdb-set env ComSpec=C:\WINDOWS\system32\cmd.exe> ^done
(gdb)
<-gdb-set env FP_NO_HOST_CHECK=NO>
^done
(gdb)
<-gdb-set env HOMEDRIVE=C:>
^done
(gdb)
<-gdb-set env HOMEPATH=\Dokumente und Einstellungen\bernd> ^done
(gdb)
<-gdb-set env LOGONSERVER=\\VBOX-577961E4>
^done
(gdb)
<-gdb-set env NUMBER_OF_PROCESSORS=1>
^done
(gdb)
<-gdb-set env OS=Windows_NT>
^done
(gdb)
<-gdb-set env Path=C:\WINDOWS\system32;C:\WINDOWS;C:\WINDOWS\System32\Wbem;;C:\FPC\2.2.4\bin\i386-Win32> ^done
(gdb)
<-gdb-set env PATHEXT=.COM;.EXE;.BAT;.CMD;.VBS;.VBE;.JS;.JSE;.WSF;.WSH> ^done
(gdb)
<-gdb-set env PROCESSOR_ARCHITECTURE=x86>
^done
(gdb)
<-gdb-set env PROCESSOR_IDENTIFIER=x86 Family 6 Model 9 Stepping 5, GenuineIntel>
^done
(gdb)
<-gdb-set env PROCESSOR_LEVEL=6>
^done
(gdb)
<-gdb-set env PROCESSOR_REVISION=0905>
^done
(gdb)
<-gdb-set env ProgramFiles=C:\Programme>
^done
(gdb)
<-gdb-set env SESSIONNAME=Console>
^done
(gdb)
<-gdb-set env SystemDrive=C:>
^done
(gdb)
<-gdb-set env SystemRoot=C:\WINDOWS>
^done
(gdb)
<-gdb-set env TEMP=C:\DOKUME~1\bernd\LOKALE~1\Temp> ^done
(gdb)
<-gdb-set env TMP=C:\DOKUME~1\bernd\LOKALE~1\Temp> ^done
(gdb)
<-gdb-set env USERDOMAIN=VBOX-577961E4>
^done
(gdb)
<-gdb-set env USERNAME=bernd>
^done
(gdb)
<-gdb-set env USERPROFILE=C:\Dokumente und Einstellungen\bernd> ^done
(gdb)
<-gdb-set env windir=C:\WINDOWS>
^done
(gdb)
<-file-exec-and-symbols "C:/lazarus/Temp/lib/i386-win32/project1.exe"> ^done
(gdb)
<-environment-cd .>
^done
(gdb)
<-environment-cd "C:/lazarus/Temp/lib/i386-win32/"> ^done
(gdb)
<-data-evaluate-expression FPC_THREADVAR_RELOCATE_PROC> ^error,msg="No symbol table is loaded. Use the \"file\" command." (gdb)
<info functions FPC_CPUINIT>
&"info functions FPC_CPUINIT\n"
~"All functions matching regular expression \"FPC_CPUINIT\":\n" ^done
(gdb)
<info functions $$_RUNERROR$>
&"info functions $$_RUNERROR$\n"
~"All functions matching regular expression \"$$_RUNERROR$\":\n" ^done
(gdb)
<-exec-arguments >
^done
(gdb)
<set width 50000>
&"set width 50000\n"
^done
(gdb)
<-gdb-set language pascal>
^done
(gdb)
<info address main>
&"info address main\n"
&"No symbol \"main\" in current context.\n"
^error,msg="No symbol \"main\" in current context." (gdb)
<-break-insert -t main>
^error,msg="No symbol table is loaded. Use the \"file\" command." (gdb)
<ptype TObject>
&"ptype TObject\n"
&"No symbol table is loaded. Use the \"file\" command.\n" ^error,msg="No symbol table is loaded. Use the \"file\" command." (gdb)
<info address FPC_RAISEEXCEPTION>
&"info address FPC_RAISEEXCEPTION\n"
&"No symbol \"FPC_RAISEEXCEPTION\" in current context.\n" ^error,msg="No symbol \"FPC_RAISEEXCEPTION\" in current context." (gdb)
<-break-insert FPC_RAISEEXCEPTION>
^error,msg="No symbol table is loaded. Use the \"file\" command." (gdb)
<info address FPC_BREAK_ERROR>
&"info address FPC_BREAK_ERROR\n"
&"No symbol \"FPC_BREAK_ERROR\" in current context.\n" ^error,msg="No symbol \"FPC_BREAK_ERROR\" in current context." (gdb)
<-break-insert FPC_BREAK_ERROR>
^error,msg="No symbol table is loaded. Use the \"file\" command." (gdb)
<info address FPC_RUNERROR>
&"info address FPC_RUNERROR\n"
&"No symbol \"FPC_RUNERROR\" in current context.\n" ^error,msg="No symbol \"FPC_RUNERROR\" in current context." (gdb)
<-break-insert FPC_RUNERROR>
^error,msg="No symbol table is loaded. Use the \"file\" command." (gdb)
<info file>
&"info file\n"
~"Symbols from \"C:/lazarus/Temp/lib/i386-win32/project1.exe\".\n" ~"Local exec file:\n"
~"\t`C:/lazarus/Temp/lib/i386-win32/project1.exe', file type pei-i386.\n" ~"\tEntry point: 0x518340\n"
~"\t0x00401000 - 0x00518370 is .text\n"
~"\t0x00519000 - 0x0055deb0 is .data\n"
~"\t0x0055e000 - 0x0055e040 is .rdata\n"
~"\t0x0055f000 - 0x00563fd4 is .bss\n"
~"\t0x00564000 - 0x00566a34 is .idata\n"
~"\t0x00567000 - 0x0058a96c is .rsrc\n"
^done
(gdb)
<-break-insert -t *5342016>
^done,bkpt={number="1",type="breakpoint",disp="del",enabled="y",addr="0x00518340",at="",times="0",original-location="*5342016"} (gdb)
<-break-insert -f foo>
&"No symbol table is loaded. Use the \"file\" command.\n" ^done,bkpt={number="2",type="breakpoint",disp="keep",enabled="y",addr="<PENDING>",pending="foo",times="0",original-location="foo"} (gdb)
<-break-delete 2>
^done
(gdb)
<-exec-run>
=thread-group-created,id="3188"
=thread-created,id="1",group-id="3188"
~"[New Thread 3188.0xc90]\n"
^running
*running,thread-id="all"
(gdb)
&"warning: Can not parse XML library list; XML support was disabled at compile time\n"
*stopped,reason="breakpoint-hit",disp="del",bkptno="1",frame={addr="0x00518340",func="??",args=[]},thread-id="1",stopped-threads="all" (gdb)
<info program>
&"info program\n"
~"\tUsing the running image of child Thread 3188.0xc90.\n" ~"Program stopped at 0x518340.\n"
~"It stopped at a breakpoint that has since been deleted.\n" ~"Type \"info stack\" or \"info registers\" for more information.\n" ^done
(gdb)
<-exec-continue>
^running
*running,thread-id="all"
(gdb)
=thread-created,id="2",group-id="3188"
~"[New Thread 3188.0x9c0]\n"
*running,thread-id="all"
~"[Switching to Thread 3188.0x9c0]\n"
*stopped,reason="signal-received",signal-name="SIGTRAP",signal-meaning="Trace/breakpoint trap",frame={addr="0x7c911231",func="??",args=[]},thread-id="2",stopped-threads="all" =thread-selected,id="2"
(gdb)
<info program>
&"info program\n"
~"\tUsing the running image of child Thread 3188.0x9c0.\n" ~"Program stopped at 0x7c911231.\n"
~"It stopped with signal SIGTRAP, Trace/breakpoint trap.\n" ~"Type \"info stack\" or \"info registers\" for more information.\n" ^done
(gdb)
<-symbol-list-lines unit1.pas>
^error,msg="mi_cmd_symbol_list_lines: Unknown source file name." (gdb)
<-exec-continue>
^running
*running,thread-id="all"
(gdb)
=thread-exited,id="2",group-id="3188"
&"warning: this is a debug message sent from my program because I clicked the button\n"
=thread-exited,id="1",group-id="3188"
=thread-group-exited,id="3188"
*stopped,reason="exited-normally"
(gdb)
<-file-exec-and-symbols >
^done
(gdb)
Hi!
Bernd wrote 16 lines
GDB registers itself as a debugger with Windows for that application and thus Windows itself is routing all messages that are sent with OutputDebugString to that registered debugger. DebugView does the same (registering itself as a debugger for an application) but does only print the OutputDebugString messages without doing anything else that a debugger might do. You can only run one debugger at a time attached to a single application. It's not a bug in GDB but a rule of Windows and its API.
The only possible way to "fix" this in GDB would be to let it output all messages it got with OutputDebugString itself and attaching DebugView to GDB (this would be needed to be done in the GDB source though).
Regards,
Sven
2010/7/18 Sven Barth :
Show quoted text 5 lines
register for these messages as long as there is another program already registered and running. I can start DebugView and it will work and continue to capture messages from other applications *before* and *during* the run of GDB, so GDB cannot use the normal mechanism. It must somehow intercept these calls before they reach the windows API. At least this is the only explanation I have to explain the observed behavior.
Hi! GDB registers itself as a debugger with Windows for that application and thus Windows…
2010/7/18 Sven Barth :
and attaching DebugView to GDB
DebugView is not attached to a specific application, it is simply acquiring a global windows resource that exists system-wide and only once and can be held by only one application at a time. It will then receive messages from windows and read the text from a shared memory block that it holds exclusively during the whole time it is running and that exists only once. A DebugView-like application will receive *all* messages from all running applications on the system.
2010/7/18 Sven Barth : register for these messages as long as there is another program…
Hi again!
Bernd wrote 13 lines
Now you got me to digging deeper into it and I took a look at the source of OutputDebugString in ReactOS (see here:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/kernel32/debug/output.c?revision=40558&view=markup ).
It basically does the following:
1) Raise an exception containing the message. If a user mode debugger is attached (e. g. GDB), that one will catch the exception, will see that it's a OutputDebugString one and will do something with the contained message (e.g. Print in case of GDB).
2) If the exception is not catched by the debugger the except handler will be executed which will try to print the message for the global debug message monitor (in your case DebugView) which is basically a memory mapped file.
3) If that fails, too, the message is sent to the kernel debugger which will normally print it.
So in your situation GDB is catching the OutputDebugString exception of your application and thus prints the message that is contained in it. All other applications don't have a debugger attached and thus the messages are written into the shared file and read by DebugView.
You might copy the "print to shared file" approach from kernel32.dll in a Pascal variant (e. g. called "PrintToDebugMonitor") too circumvent GDB catching the exception. Take a look at the C code to do this.
Regards,
Sven
2010/7/18 Sven Barth :
It basically does the following: 1) Raise an exception containing the message.
OK, this seems to be the missing piece of the puzzle for understanding whats going on. I was basing all my theories only on this: http://unixwiz.net/techtips/outputdebugstring.html and there they don't mention the exceptions.
I have just posted a question about how this mechanism works on the GDB mailing list. One option to solve my dilemma would be that GDB would be modified so that it itself calls OutputDebugString() again to propagate the messages originating from such exceptions and the other one would be to label them differently when they are outputted to the console so they could easily be grepped and separately displayed in an IDE window. AFAIK Delphi also has the possibility to display these messages conveniently in an IDE window.
Hi!
Bernd wrote 8 lines
That's why I like to dig into source myself: to see how it really works. :D
Show quoted text 7 lines
Well... you could always try to mimic the sending part of OutputDebugString as seen in the source link I've send you. Might be easier than to convince the GDB people to include this. And even if they'd include it, you must wait for a new release or build it yourself.
AFAIK Delphi also has the possibility to display these messages conveniently in an IDE window.
That's because Delphi contains its own debugger which catches the exceptions that are raised by OutputDebugString.
Regards,
Sven
2010/7/18 Sven Barth : OK, this seems to be the missing piece of the puzzle for…
Hi again!
I took the time to implement a OutputToDebugMonitor myself. It prints the message directly to e.g. DebugView even if a debugger like GDB is attached to the process.
The only problem with that code is the license... it's based on the GPL code from ReactOS so I don't know whether it is considered a derived work or not. If it is, I'm afraid that you must use it in terms of the GPLv2 license or you must "cleanly reimplement" it to be on the safe side. If it isn't, then you're hereby free to use it under whatever terms you like.
Regards,
Sven
-------------- next part --------------
A non-text attachment was scrubbed...
Name: debugmonitor.pas
Type: text/x-pascal
Size: 3376 bytes
Desc: not available
URL: <http://lists.lazarus.freepascal.org/pipermail/lazarus/attachments/20100718/5f24d3c2/attachment.bin>
2010/7/18 Sven Barth :
Show quoted text 5 lines
Wow! That was fast! I didn't even consider implementing this myself after looking at the code for a while.
(* first try to open the mutex, if that fails call OutputDebugString, which
will create that for us (we can't do that ourselves easily) *)
mutex := OpenMutexW(SYNCHRONIZE or READ_CONTROL or MUTANT_QUERY_STATE, True,
PWideChar(DBWinMutex));
if mutex = 0 then begin
OutputDebugStringA(PChar(aStr));
Exit;
end;Does this really create the mutex or wouldn't the original OutputDebugString() just raise the debug exception and invoke the debugger and then return before it even comes to the point where the mutex is needed?
Hi!
Bernd wrote 9 lines
I was bored...
And afterall it was a pretty simple conversion from C to Pascal... not much thinking involved ^^
Show quoted text 13 lines
Good point... in that case there are only two things we can do:
1) Rely on the fact that OutputDebugString got at least called once since the system started while no debugger was attached.
2) Create the mutex by ourselves if we can't open it.
I personally would chose 1, because for 2 I don't know whether all Windows versions create the Mutex with the same security attributes as ReactOS does.
To ensure that OutputDebugString was "successfully" called at least once we could write a really simple (maybe even C) application that calls OutputDebugString and which is started from our process (thus no debugger attached). This is done if OpenMutexW fails. After that we try to open the mutex again and if that fails as well we'll have to give up (or simply call OutputDebugString to get the message anywhere).
Better: this dummy process is started once at the beginning of your own application and thus OpenMutexW should be successful no matter what (if not we simply exit the OutputToDebugMonitor procedure).
Regards,
Sven
Hi! That's why I like to dig into source myself: to see how it really works. :D Well...…
Sven Barth wrote 32 lines
In theory Lazarus can display them too, it's only not implemented.
Marc
Hi!
Marc Weustink wrote 7 lines
You mean by parsing the output of GDB, do you?
If so: is that output that relyable that you'll only get OutputDebugString messages?
If not: what approach do you think of?
Regards,
Sven
Sven Barth wrote 12 lines
IIRC it is part of the gdb mi messages.
If so: is that output that relyable that you'll only get OutputDebugString messages?
the lazarus gdb interface is mainly developed on linux, where such string doesn't exist. iirc, ive seen some docs on debugstrings on windows. If this is the case, they can become part of the debug events window.
If not: what approach do you think of?
If gdb doesn't give them to me, they wont get displayed.
Marc
2010/7/19 Marc Weustink :
If gdb doesn't give them to me, they wont get displayed.
They show up in the debug messages as warnings. Making the debug message window able to show/hide all the different types of messages would probably already be enough. Here is an example. Try to find the line with the debug message ;-)
[...]
(gdb)
<-exec-continue>
^running
*running,thread-id="all"
(gdb)
=thread-exited,id="2",group-id="3188"
&"warning: this is a debug message sent from my program because I clicked the button\n"
=thread-exited,id="1",group-id="3188"
=thread-group-exited,id="3188"
*stopped,reason="exited-normally"
(gdb)
<-file-exec-and-symbols >
^done
(gdb)
[...]
2010/7/19 Marc Weustink : They show up in the debug messages as warnings. Making the debug
Bernd wrote 7 lines
This window has the purpose of showing all internal output. It is not meant for "normal" debugging. These messages should go to the eventlog.
Show quoted text 9 lines
I hoped on a bit more recognizable MI output.
& messages are stdoutput, so the "warning: ..." could have been a writeln too.
Marc
2010/7/20 Marc Weustink :
I hoped on a bit more recognizable MI output. & messages are stdoutput, so the "warning: ..." could have been a writeln too.
Hmm... I cannot get it to show writelns in the debugger window.
either they show up in the black console window that opens when i have compild without -WG or the standard output will not be available at all and the program will fail with a runtime error. In the screenshot in my previous posting these were not normal writelns, i had all output redirected so that every writeln goes directly to OutpuDebugString(). Somethiing like that:
unit debugwriteln;{use this unit and all writeln will go directly
to the attached debugger or to the system-wide
debug monitor if no debugger is attached}
{$mode objfpc}
interface
implementationuses
Classes,
StreamIO,
SysUtils,
Windows;type
TDebugStream = class(TStream)
function Write(const Buffer; Count: LongInt): LongInt; override;
end;
var
DebugStream: TDebugStream;
function TDebugStream.Write(const Buffer; Count: LongInt): LongInt;
var
Msg: Ansistring;
begin
Result := Count;
SetLength(msg, Count);
move(Buffer, PChar(Msg)[0], Count);
OutputDebugString(PChar(TrimRight(Msg)));
end;
initialization
DebugStream := TDebugStream.Create();
AssignStream(Output, DebugStream);
Rewrite(Output);
end.OutputDebugString() has been increadibly useful for me already in situations where neither a debugger can be used nor stdout is available, not only in FPC/Lazarus but also in other languages. Only in standalone Lazarus applications it always seems easier to write to stdout instead.
Maybe a feature request at the GDB project would be appropriate. I'm sure I am not the only one who would like to be able to make better usage of this feature.
Another interesting alternative would be to include a cross platform variant of Sven's re-implementation of OutputDebugString() (which is completely bypassing the debugger and talking directly to the debug monitor) in the System unit and and give Lazarus the ability to act as a regular debug monitor on windows and use some other IPC mechanisms on other OS to capture and display such messages. Standard output could then by default always be redirected to this mechanism if compiled with the -WG switch. This would be quite neat: Writeln in GUI apps would then always go to an IDE window if the IDE is running or simply go nowhere if no IDE and no debug monitor is present.
We could even establish an open standard for such debug monitoring on linux because there doesn't seem to be one already.
</dream>
Bernd
We could even establish an open standard for such debug monitoring on linux because there doesn't seem to be one already.
Most likely because noone ever missed it. But this is just my personal opinion and I prefer using gdb directly and seldom use it from within lazarus. And writeln() or debugln() are good enough for my debugging output needs.
a at b:~$ ./myprog >> debug.log works quite well, too.
Why I need a program (debug monitor) to capture stdout output is beyond me. So please enlighten me. What are the benefits of such a debug monitor? Perhaps I am missing something.
R.
Show quoted text 12 lines
Searching, filtering, highlighting and comparing with former runs.
Mattias
Searching, filtering, highlighting and comparing with former runs.
Sounds good, but ...
The first and last work with simple text files, only little gain there. Filtering is valid and highlighting I don't understand. Are you talking about shiny colors? Or is 'highlighting and comparing' one point? And do you mean that you actually cannot do this with stdout and therefor need a new standard?
Presenting stdout with some nice features (search, filter, etc.) inside lazarus is actually something I would like to see myself. But I don't get the need for another stdXXX (OutputDebugString()) like windows has.
R.
On Tue, 20 Jul 2010 11:47:22 +0200 Most likely because noone ever missed it. But this is…
Reimar Grabowski wroteMost likely because noone ever missed it.
I do miss (something like) this badly !.
With MSEIDE you can see the standard output of a program ( writeln() ) in a window, With Lazarus this is not available.
I did not know about "OutputDebugString", it would be very appropriate to have it as well on Windows as on Linux.
-Michael
On Tue, 20 Jul 2010 13:42:39 +0200 Sounds good, but ... The first and last work with…
Show quoted text 10 lines
Yes, Linux has pretty good terminal tools, it just would be more comfortable if they are integrated in the IDE. For me a good output window is the most missing feature of the debugger in the IDE.
Mattias
Yes, Linux has pretty good terminal tools,
Agreed.
it just would be more comfortable if they are integrated in the IDE.
Waiting nearly 10 years for this. :)
Every other Linux IDE I know has at least a terminal tab/window where stdout is displayed.
For me a good output window is the most missing feature of the debugger in the IDE.
Actually the reason I don't use the debugger in the IDE. But on Linux the workaround is just a terminal away. Perhaps I just got too used to my many open terminals.
R.
I do miss (something like) this badly !. With MSEIDE you can see the standard output of a…
I do miss (something like) this badly !. With MSEIDE you can see the standard output of a program ( writeln() ) in a window, With Lazarus this is not available.
That is not the same and actually a really useful feature I miss myself.
I did not know about "OutputDebugString", it would be very appropriate to have it as well on Windows as on Linux.
I actually fail to see the benefit over stdout (other than windows problems with stdout), but I am not against it. It is no problem to replace my writeln() with outputDbgStr(). If it will be implemented I would like to add a feature request:
outputDbgStr(tag, message: String);It's very useful to include a tag to indicate which unit/class/method/etc created the message. Got used to it while coding for android devices as there is such system in place as stdout is only reachable on the device itself.
R.
On Tue, 20 Jul 2010 13:38:46 +0200 Searching, filtering, highlighting and comparing with…
2010/7/20 Mattias Gaertner :
> So please enlighten me. What are the benefits of such a debug monitor? Perhaps I am missing something.
Sometimes you simply don't have a stdout to write to. I just have one such occasion where I'm working on a plugin dll for another application on windows and I didn't find a way to write to stdout an the other half of the plugin which is written in the application's built in scripting language uses OutputDebugString() for all debugging output. On windows this is simply the most comfortable way to quickly spew out some debug messages from any kind of application and have them all nicely arrive in one central easily accessible place and displayed and filtered in realtime. Many windows programmers use this API because it is so much easier than having to experience the pain of using the windows command prompt to navigate through folders or installing all the cygwin tools to do even the most basic command line stuff like tail -f | grep and friends.
It is true that with a standalone Lazarus application on windows and how things currently are the best (and only) available option is writeln to stdout or a log file, simply because the windows debug output API is sabotaged by GDB's way of not recognizing these messages and treating them as what they really are.
Most often (and also all other languages I use) I find myself simply completely not using a debugger at all and doing all my debugging by outputting simple messages to trace the program flow and some variables I am interested in. And on Windows I like to output them to where it is most easy to watch them and filter them, and this is certainly *not* stdout. And this is exactly what I'm currently doing in Lazarus: I have disabled the debugger because it will disturb my debugging.
It would just be nice to have this all somehow unified and more *comfortably* usable in Lazarus. On windows I almost exclusively use OutputDebugString() for everything that is (or runs inside) a GUI app and has no stdout available (basically everything in windows). Only the Lazarus/GDB combination will not easily allow this and this is because GDB originates from the *ix world and there no such API exists and working from the command line and with log files is a hundred times easier with all the available tools and much more the norm than in windows.
After All Lazarus is a graphical IDE and it should not force me to mess around with the clumsy windows command line and/or 3rd pary tools to tail and grep log files. comfortable outputting to a debug monitor in a GUI environment where there simply is no easily accessible stdout and no easy way to tail -f some file should be the norm in a GUI based development+debugging environment.
The first step and immediate help would be to filter all &"Warning: " messages from GDB output and display them separately. and in parallel maybe try to convince the GDB people for some future release of GDB to recognize these messages correctly as what they really are, label them separately and not throw them as ordinary warnings to stdout.
Bernd wrote 14 lines
I suggest you look at the debugserver tool and the dbugintf units in FPC.
SendDebug('Some message');
SendDebugFmt('variable A : %s',[A]);Program flow is easily monitored with
SendMethodEnter('Entering MyMethod');
SendmethodExit('Exiting mymethod');It nicely indents/de-indents the messages in the output.
It works as you describe it, does not interfere with the debugger at all and is cross-platform to boot. I use it since 12 years, also in Delphi, where it is part of gexperts.
I couldn't develop without it.
Michael.
2010/7/20 Mattias Gaertner : Sometimes you simply don't have a stdout to write to. I just…
On Tue, 20 Jul 2010 15:17:32 +0200
Bernd wrote:
Thanks for the lengthy explanation, but if you had read my mail carefully, you would have seen that I never doubted that windows needs something like this with its crappy cmdln. I was just looking at the Linux side as my qoute should have made clear. I wanted to know why Linux needs a new 'debug monitoring standard' not why windows su... aehm I mean has problems. This I knew already. My conclusion is that Linux does not need a new standard but Lazarus debug output can be improved. Perhaps mplemented via OutputDebugString() on windows and some stdout magic on real ...aehm I mean other operating systems or a self made cross-plattform solution. We agree that we want a better debug output but the problem is more pressing on Win than on Linux, as there are easy workarounds on the *nix side. I just don't like bringing windows solutions to Linux where the problem simply does not exist.
R.
I suggest you look at the debugserver tool and the dbugintf units in FPC. SendDebug('Some…
2010/7/20 Michael Van Canneyt :
I suggest you look at the debugserver tool and the dbugintf units in FPC.
Lazarus still keeps surprising me :-) Are there more such useful things that are still hiding from me deep down in some subdirectories I that I have never visited?
My first impression was: This little gem would deserve to be directly available from the tools menu in every standard installation of Lazarus or even directly integrated in the IDE itself and accessible from the debug menu. It does *exactly* what OutputDebugString() + DebugView does for me on windows and could serve as a complete replacement.
Many thanks for pointing my nose at this useful little tool that was already sitting on my harddisk and waiting for me all the time ;-)
Bernd
Bernd wrote 7 lines
Undoubtedly :-)
Show quoted text 7 lines
I happen to agree with you, but the decision on that is for the lazarus devels.
I even have some special code templates:
sendd -> {$ifdef debug}SendDebug('|');{$endif}
sendf -> {$ifdef debug}SendDebugFmt('|',[]);{$endif} sendu -> {$ifdef debug}dbugintf,{$endif}
sendb -> {$ifdef debug}SendMethodEnter('|');{$endif} sende -> {$ifdef debug}SendMethodExit('|');{$endif}
Makes it a lot easier to add debugging statements.
Many thanks for pointing my nose at this useful little tool that was already sitting on my harddisk and waiting for me all the time ;-)
Glad to be of help :-)
Michael.
Michael, If I have a patch for the debugserver can I send it directly to you (your name is in the source) or does it have to go directly to the bug tracker?
Bernd wroteMichael, If I have a patch for the debugserver can I send it directly to you (your name is in the source) or does it have to go directly to the bug tracker?
You can send it to me.
Michael.
I suggest you look at the debugserver tool and the dbugintf units in FPC. SendDebug('Some…
Michael Van Canneyt wroteI suggest you look at the debugserver tool and the dbugintf units in FPC.
Where to find the "dbugsrv executable" ?
Thanks
-Michael
Michael Schnell wrote 5 lines
lazarus\tools\debugserver\debugserver.lpi
Howard
Howard Page-Clark wrote 10 lines
Great ! Works ! Thanks !
I have been searching for dbugsr, as the program exception says same is not found.
It might be a good idea to synchronize the error message and the file name required,
-Michael
Michael Schnell wrote 16 lines
I will do so.
Michael.
I suggest you look at the debugserver tool and the dbugintf units in FPC. SendDebug('Some…
The following program will silently terminate as soon as the debugserver is terminated while the program is still running. There are no exceptions or any other messages, it just silently exits back to the command prompt. I haven't yet tried with GDB to see where exactly this happens. IIRC when I tried this on Windows yesterday this didn't happen. (don't have a windows box available now to test it).
program debugservertest;
{$mode objfpc}{$H+}
uses
dbugintf, sysutils;
var
count : Integer;
begin
count := 0;
repeat
SendDebug(IntToStr(count));
writeln(count);
count += 1;
Sleep(1000);
until False;
end.