Re: logfile msg: get method and class names
On 29 Jan., 22:34, Joseph M. Newcomer <newco...@flounder.com> wrote:
See below...
On Sat, 29 Jan 2011 03:01:02 -0800 (PST), Goran <goran.pu...@gmail.com> w=
rote:
On Jan 29, 11:38 am, mfc <mfcp...@googlemail.com> wrote:
Hi,
I`ve a logfile which should contain all errors which can occur in the
programm. My document-class (SDI application) will contain a member-
variable of my logfile-class. If a error occurred in a different
thread than the mainthread I will write a PostMessage() to the window
I`ve installed for the document.
Why? This seems too complex and breaks the order of events. Just wrap
actual logging code into a synchronized block. Logging is one of
lowest-level operations there are, so there's no danger of deadlocking
(if there is, it is going be easy to weed out). You also might want to
make logging a non-throwing operation.
****
No, it doesn't break the order of events; the events appear in the order =
they occurred,
because the PostMessage queue is FIFO. It eliminates having to do sync=
hronization, and I
believe "the best synchronization is no synchronization", which is to say=
that you should
always design so that synchronization is not needed. Explain how using=
PostMessage
"breaks" the order, since it produces, with vastly less effort, the same =
effects as the
more complex synchronized-by-hand method.
****
First of all, thank you for your answer. It`s exactly what I was
searching for.
One last question: is it possible to install this function void
Log(DWORD err, LPCTSTR fn, int line, LPCTSTR file)
in a header-file, so that every thread can execute this function if
it will be necessary? Without any kind of synchronisation is needed?
Or do I have to include this function-definition in every thread?
It would be great if the logfile will contain the information: class-
name, method-name, function-call with the specific GetLastError() if
available. Are there any methods to get the class name as well as the
method name where the error occurred? So that I immediately know where
the error occured if I see the logfile.
void MyThreadClass::MyMethod()
{
int rtn = Methodcall()
if(rtn != SUCCESS)
{ /* failed -> send msg to logfile */
DWORD err = ::GetLastError();
CString *perr = new CString();
perr->Format(_T("%s | %s | %s - %s"), classname, methodname,
call, err);
/* example:
perr ("MyThreadClass | MyMethod | Methodcall -
20(GetLastError) ")
*/
if(m_wnd)
m_wnd->PostMessage(UWM_LOGFILE_MSG, (WPARAM)perr,
(LPARAM)0);
}
}
Another method is to install thousands of defines (each possible error
will get one of these defines).... but that`s not really a good idea,
because it`s hard to update....
Are there any other options to determine where the error (located in
the logfile) occurred?
You could try __FILE__, __LINE__, __FUNCTION__. Alternatively, just
don't use same message text in two places, and you'll know the place
where error occurred by virtue of text being unique.
****
Independent of pretty much any other consideration, this is fundamental. =
There is a
tendency to want to "reuse" messages, and this is foolish. Microsoft p=
rogrammers do this
all the time, and say things like "file open failure" without giving the =
decoded
GetLastError code, which is nothing short of an insult to the intelligenc=
e of the end
user.
Also, a classic failure in the Microsoft universe is to pop up a MessageB=
ox but have no
code by which the MessageBox message can be looked up, and the reader can=
see a long
explanation as to what might have caused it and what might be done to fix=
it; instead, we
get messages like
You can't do that.
or
Please do not press that button again.
or more formal equivalents. These do not help. So if you are poppin=
g up message boxes,
put in a unique code for each one, like M0001, M0002, etc. to help your e=
nd users look
them up in the documentation, or your tech support people look them up in=
their tech
support database.
****
Note that, for low-level routines, that are called from many places,
even if the log shows exactly what went wrong, you often don't have
enough context to know __WHY__ (which is arguably more important than
"what"). To get that, you'll probably need to add more logs as you go
up the stack, or something like that.
****
But it does tell you enough that you can put a breakpoint in the right pl=
ace for
debugging. And, surprisingly, I've found that using unique text to ide=
ntify the location
and giving the GetLastError code (in text form using ::FormatMessage) oft=
en lets me
diagnose the cause. Note that when a file operation is involved in the=
failure, the
filename *must* be given! So it does no good to say
Mumble.cpp(42): whatever::Write: Write operation failed, invalid handle
but it is sometimes a dead giveaway when it says
Mumble.cpp(42): whatever::Write: Write operation on "c:\randomfile.txt" f=
ailed, invalid
handle
because that tells me the user was trying to write to a file in the root =
directory, which
is often protected against writing on most systems (we will not ask why t=
he file
*creation* failed, which is where this error should have been detected, o=
r the fact that
the creation failed meant that the write should not have been attempted; =
the answers to
those kinds of questions are often embarrassing)
****
e.g (I am exaggerating for the purpose of the example; you'll need to
balance the pain and the usefulness of consistently doing what
follows).
bool f1()
{
if (!op())
{
log(failure explanation);
return false;
}
}
bool f2()
{
op1;
op2
op3
if (!f1)
{
log(f2-specific failure explanation)
return false;
}
}
bool f3()
{
op4
op5
if (f2())
{
log(f3-specific failure explanation)
return false;
}
}
Goran.
P.S. "return bool" is for the sake of example. He who uses bool for
error-return in C++ these days, should probably be banned from coding.
****
Sometimes throwing an exception makes life far too miserable, and sometim=
es it is simply
not appropriate, because the problem is an "expected" failure condition. =
And is it an
STL-compatible exception you throw, or an MFC CException-derived exceptio=
n? But I
digress.
joe
****
Joseph M. Newcomer [MVP]
email: newco...@flounder.com
Web:http://www.flounder.com
MVP Tips:http://www.flounder.com/mvp_tips.htm- Zitierten Text ausblenden =
-
- Zitierten Text anzeigen -- Zitierten Text ausblenden -
- Zitierten Text anzeigen -