473,395 Members | 1,554 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,395 software developers and data experts.

Passing information to printf like functions

hg
I have a function called logprintf that take a printf-like syntax.
On top of that I want to implement a debug-printf function which calls
logprintf but prefix the information using a string:

void _dbglogprintf(const char *szFormat, ...)
{
char szOutput[4096];
va_list arglist;

sprintf(szOutput, "DEBUG: ");

va_start(arglist, szFormat);
vsprintf(szOutput + strlen(szOutput), szFormat, arglist);
va_end(arglist);

logprintf(szOutput);
}

The following works but will obviously cause a buffer overflow when
the string becomes too long.
I want to avoid such problems.
However the obstacle is that logprintf must be called only once since
it prints out information such as time-stamps. If it would be called
twice it would duplicate this information without any good reason.
However I couldn't see if there is a function which allows me to take
the existing arglist and combine it with my own strings.

Thanks.

-- Henrik

Nov 13 '07 #1
3 2039
hg@x-formation.com wrote:
....
However I couldn't see if there is a function which allows me to take
the existing arglist and combine it with my own strings.
There is a vsnprintf method.

The problems you cite are one reason why the C++ stream methods are what
they are. The logging interfaces that I have used more recently have
moved totally away from the printf.

A little off topic is another chunk of advice. I have found that the
format of the log information should not be embedded throughout the
application code - it makes it much harder to implement automated log
management tools. The Austria C++ logging interface does things
differently. This is what a typical "log" looks like:
AT_STARTLOG( l_lm, l_loglevel, AT_LOGLEVEL_SEVERE,"SomeDescription" )
at_log("Some Variable") << 55 << 123.456;
at_log("Some Other Variable") << "YUP";
AT_ENDLOG

-or-

AT_LOG( l_lm, l_loglevel, AT_LOGLEVEL_SEVERE,"SomeDescription" )

Yes, AT_STARTLOG and AT_ENDLOG are macros, there are reasons why it
makes sense to do that too. In a large body of code using the logging
interface, you want to catch problems with mis-use - the macros make it
easy to do that.

OK - notice that the "at_log" object is local to the body of code
between AT_STARTLOG and AT_ENDLOG. This means you can place any complex
information processing inside the log block and not pay the penalty
otherwise.

I'll stop the rave there... If you can drop the printf model for
logging, drop it now !
Nov 13 '07 #2
On Nov 13, 12:08 pm, Gianni Mariani <gi4nos...@mariani.wswrote:
h...@x-formation.com wrote:
...
However I couldn't see if there is a function which allows me to take
the existing arglist and combine it with my own strings.
There is a vsnprintf method.
The problems you cite are one reason why the C++ stream
methods are what they are. The logging interfaces that I have
used more recently have moved totally away from the printf.
Drop the recently, and that corresponds to my experience as
well. The rare cases which did try to use a printf like log
always ended up in trouble. The iostream idiom, on the other
hand, while sometimes a little awkward for some types of
formatting (e.g. tables), is perfect for logs.
A little off topic is another chunk of advice. I have found
that the format of the log information should not be embedded
throughout the application code - it makes it much harder to
implement automated log management tools.
By this, I presume you mean that if it is embedded through the
application code, the format won't be identical everywhere, so
automated tools won't be able to handle it.

In my own work (using the ostream model, of course), the actual
formatting is usually handled by a filtering streambuf. Done
correctly, this can allow different formatting for different
destinations (email, syslog, a file, etc.). More importantly,
it allows multiple destinations, and can ensure synchronization.
The Austria C++ logging interface does things
differently. This is what a typical "log" looks like:
AT_STARTLOG( l_lm, l_loglevel, AT_LOGLEVEL_SEVERE,"SomeDescription" )
at_log("Some Variable") << 55 << 123.456;
at_log("Some Other Variable") << "YUP";
AT_ENDLOG
-or-
AT_LOG( l_lm, l_loglevel, AT_LOGLEVEL_SEVERE,"SomeDescription" )
Yes, AT_STARTLOG and AT_ENDLOG are macros, there are reasons
why it makes sense to do that too.
If for no other reason that you want to automatically make
__FILE__ and __LINE__ available to the logger.

I'm not sure I like the block, though. I use something like:

LOG( severity ) << ...

My experience has been that the more the programmer has to write
to log something, the less will be logged, so I try to keep it
as simple as possible.
In a large body of code using the logging interface, you want
to catch problems with mis-use - the macros make it easy to do
that.
OK - notice that the "at_log" object is local to the body of
code between AT_STARTLOG and AT_ENDLOG. This means you can
place any complex information processing inside the log block
and not pay the penalty otherwise.
The AT_STARTLOG macro contains an "if () {"?

I'm generally very opposed to macros modifying syntax, but I
sort of like this idea. I'll have to check if I can configure
my editor to recognize the strings as opening and closing
blocks, however, so that it will indent correctly.

In practice, I've not had any real problems with my idiom,
above. The operator<< are called for each argument, but they
are inline, and don't do anything if logging is not active, so
in practice, all it means is that I get three or four tests of
the variable, rather than only one. (It also means that if the
programmer outputs complicated expressions in the log, then
these are evaluated. It's been my experience that they don't.)

--
James Kanze (GABI Software) email:ja*********@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

Nov 14 '07 #3
James Kanze wrote:
On Nov 13, 12:08 pm, Gianni Mariani <gi4nos...@mariani.wswrote:
>h...@x-formation.com wrote:
....
>A little off topic is another chunk of advice. I have found
that the format of the log information should not be embedded
throughout the application code - it makes it much harder to
implement automated log management tools.

By this, I presume you mean that if it is embedded through the
application code, the format won't be identical everywhere, so
automated tools won't be able to handle it.

In my own work (using the ostream model, of course), the actual
formatting is usually handled by a filtering streambuf. Done
correctly, this can allow different formatting for different
destinations (email, syslog, a file, etc.). More importantly,
it allows multiple destinations, and can ensure synchronization.
Yes - exactly.
>
>The Austria C++ logging interface does things
differently. This is what a typical "log" looks like:
>AT_STARTLOG( l_lm, l_loglevel, AT_LOGLEVEL_SEVERE,"SomeDescription" )
at_log("Some Variable") << 55 << 123.456;
at_log("Some Other Variable") << "YUP";
AT_ENDLOG
>-or-
>AT_LOG( l_lm, l_loglevel, AT_LOGLEVEL_SEVERE,"SomeDescription" )
>Yes, AT_STARTLOG and AT_ENDLOG are macros, there are reasons
why it makes sense to do that too.

If for no other reason that you want to automatically make
__FILE__ and __LINE__ available to the logger.

I'm not sure I like the block, though. I use something like:

LOG( severity ) << ...
The AT_STARTLOG macro is an if that can be used to eliminate whole
levels of logging code - which removes the whole - "I don't like to do
logging because it slows down the code" issue from the discussion.
>
My experience has been that the more the programmer has to write
to log something, the less will be logged, so I try to keep it
as simple as possible.
If it's a cut-n-paste mostly, then it's not an issue.

The first time I did the logging interface we did something like:

STARTLOG( ... ) { at_log("A") << aval; }

The problem was the carelessness of the "}" - it was prone to looking
like regular code. We never ever had an issue with that in the
STARTLOG/ENDLOG paradigm.

>
>In a large body of code using the logging interface, you want
to catch problems with mis-use - the macros make it easy to do
that.
>OK - notice that the "at_log" object is local to the body of
code between AT_STARTLOG and AT_ENDLOG. This means you can
place any complex information processing inside the log block
and not pay the penalty otherwise.

The AT_STARTLOG macro contains an "if () {"?

I'm generally very opposed to macros modifying syntax, but I
sort of like this idea. I'll have to check if I can configure
my editor to recognize the strings as opening and closing
blocks, however, so that it will indent correctly.

In practice, I've not had any real problems with my idiom,
above. The operator<< are called for each argument, but they
are inline, and don't do anything if logging is not active, so
in practice, all it means is that I get three or four tests of
the variable, rather than only one. (It also means that if the
programmer outputs complicated expressions in the log, then
these are evaluated. It's been my experience that they don't.)
Best
Nov 14 '07 #4

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

10
by: Pete | last post by:
Can someone please help, I'm trying to pass an array to a function, do some operation on that array, then return it for further use. The errors I am getting for the following code are, differences...
3
by: ehabaziz2001 | last post by:
I know one of the pointer benefit is that we can return more than one value from a function . The down program has an error that I can not discover . That is the call of the function : The Call:...
3
by: tigrfire | last post by:
I don't want to use global variables to do this, but I'm stumped on how to pass a variable between one function to another, so if someone could help out, that'd be appreciated. Here's an example of...
2
by: jeniffer | last post by:
gcc -c test.c gcc -o test test.c ./test i=6 0 14 22 42 48 e6 014224248ffffffe6 ea =
3
by: dice | last post by:
Hi, In order to use an external api call that requires a function pointer I am currently creating static wrappers to call my objects functions. I want to re-jig this so I only need 1 static...
1
by: Dave Kelly | last post by:
I'm posting on this again. Sorry I am so thick heading but I do not understand why this failure. I have put in some 'printf' statements for debugging and some comments. And some questions. ...
7
by: James | last post by:
Hello, First off, I know this code will not compile and am not asking for someone to solve it for me. What I am asking is from the code below, how does one first define an array as a...
10
by: ptq2238 | last post by:
Hi, Tried this code to assist my understanding of strings and functions but I'm not sure why the errors are occurring and hope someone can shed some light to my learning. #include <stdio.h>...
8
by: S. | last post by:
Hi all, Can someone please help me with this? I have the following struct: typedef struct { char *name; int age; } Student;
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
0
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.