473,397 Members | 2,099 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,397 software developers and data experts.

How to use strings for error handling

jma
Hi all,

I want to push some errors on an error stack in my function. The first
parameter of the push function is the name of the function where the
error occured. For example:

int MyFunction()
{
...
if(error1) pushError("MyFunction","Something is wrong");
...
if(error2) pushError("MyFunction","Something else is wrong");
...
if(error3) pushError("MyFunction","Something more is wrong");
}

To make things easier and less cluttered I could define two macros:
#define FUNCNAME(a) static const char funcname[]=#a;
#define PUSHERROR(a) pushError(funcname,#a)

then my function would look like:

int MyFunction()
{
FUNCNAME(MyFunction);
...
if(error1) PUSHERROR(Something is wrong);
...
if(error2) PUSHERROR(Something else is wrong);
...
if(error3) PUSHERROR(Something more is wrong);
}

which is better in terms of getting rid of useless literals but also
makes sure that the correct function name is always used in the error
stack. My question is what would be the resource penalties for doing
that. I assume that a rational compiler would recognize the same
literals in the first case and collapse them to one, which will be
stored in the executable. In the second case, the function name will
be stored only once in the executable as well. But will there be any
difference in memory utilization when the program is executed? I am
pretty sure that in the second case all literals will be loaded to
static memory, even for functions that are never called. Will it be
the same in the first case? Are there any other implications I ignore?

Thanks a lot!

-- dimitris
Aug 20 '08 #1
6 1336
jma wrote:
Hi all,

I want to push some errors on an error stack in my function. The first
parameter of the push function is the name of the function where the
error occured. For example:

int MyFunction()
{
...
if(error1) pushError("MyFunction","Something is wrong");
...
if(error2) pushError("MyFunction","Something else is wrong");
...
if(error3) pushError("MyFunction","Something more is wrong");
}

To make things easier and less cluttered I could define two macros:
#define FUNCNAME(a) static const char funcname[]=#a;
#define PUSHERROR(a) pushError(funcname,#a)

then my function would look like:

int MyFunction()
{
FUNCNAME(MyFunction);
...
if(error1) PUSHERROR(Something is wrong);
...
if(error2) PUSHERROR(Something else is wrong);
...
if(error3) PUSHERROR(Something more is wrong);
}

which is better in terms of getting rid of useless literals but also
makes sure that the correct function name is always used in the error
stack. My question is what would be the resource penalties for doing
that. I assume that a rational compiler would recognize the same
literals in the first case and collapse them to one, ...
Some compilers will, others won't. As memory gets cheaper,
implementations for non-embedded platforms that don't bother
themselves with minor optimizations for reducing memory usage suffer
less of a penalty in the marketplace than they used to.
... which will be
stored in the executable. In the second case, the function name will
be stored only once in the executable as well. But will there be any
difference in memory utilization when the program is executed? I am
pretty sure that in the second case all literals will be loaded to
static memory, even for functions that are never called. Will it be
the same in the first case? Are there any other implications I ignore?
An implementation is free to put the memory allocated for string
literals in a different place than where variables with static
storage duration are stored. In principle, this could cause problems.
In practice, I wouldn't recommend worrying about it; for most
practical purposes the difference won't matter.

Note: If you can afford to restrict the portability of your code to
C99 implementations, you can use the predefined identifier__func__
instead of funcname, and drop the FUNCNAME macro entirely:

6.4.2.2p1: "The identifier __func_ _ shall be implicitly declared by
the translator as if, immediately following the opening brace of each
function definition, the declaration

static const char _ _func_ _[] = "function-name";

appeared, where function-name is the name of the lexically-enclosing
function."
By using __func__, you can avoid any danger of, for instance,
misspelling the argument to FUNCNAME(), or forgetting to update the
argument when the function name is changed.
Aug 20 '08 #2
jma
On Aug 20, 4:26*pm, jameskuy...@verizon.net wrote:
jma wrote:
Hi all,
I want to push some errors on an error stack in my function. The first
parameter of the push function is the name of the function where the
error occured. For example:
int MyFunction()
{
* ...
* * if(error1) pushError("MyFunction","Something is wrong");
* ...
* * if(error2) pushError("MyFunction","Something else is wrong");
* ...
* * if(error3) pushError("MyFunction","Something more is wrong");
}
To make things easier and less cluttered I could define two macros:
#define FUNCNAME(a) static const char funcname[]=#a;
#define PUSHERROR(a) pushError(funcname,#a)
then my function would look like:
int MyFunction()
{
FUNCNAME(MyFunction);
* ...
* * if(error1) PUSHERROR(Something is wrong);
* ...
* * if(error2) PUSHERROR(Something else is wrong);
* ...
* * if(error3) PUSHERROR(Something more is wrong);
}
which is better in terms of getting rid of useless literals but also
makes sure that the correct function name is always used in the error
stack. My question is what would be the resource penalties for doing
that. I assume that a rational compiler would recognize the same
literals in the first case and collapse them to one, ...

Some compilers will, others won't. As memory gets cheaper,
implementations for non-embedded platforms that don't bother
themselves with minor optimizations for reducing memory usage suffer
less of a penalty in the marketplace than they used to.
... which will be
stored in the executable. In the second case, the function name will
be stored only once in the executable as well. But will there be any
difference in memory utilization when the program is executed? I am
pretty sure that in the second case all literals will be loaded to
static memory, even for functions that are never called. Will it be
the same in the first case? Are there any other implications I ignore?

An implementation is free to put the memory allocated for string
literals in a different place than *where variables with static
storage duration are stored. In principle, this could cause problems.
In practice, I wouldn't recommend worrying about it; for most
practical purposes the difference won't matter.

Note: If you can afford to restrict the portability of your code to
C99 implementations, you can use the predefined identifier__func__
instead of funcname, and drop the FUNCNAME macro entirely:

6.4.2.2p1: "The identifier __func_ _ shall be implicitly declared by
the translator as if, immediately following the opening brace of each
function definition, the declaration

* * * * * static const char _ _func_ _[] = "function-name";

appeared, where function-name is the name of the lexically-enclosing
function."

By using __func__, you can avoid any danger of, for instance,
misspelling the argument to FUNCNAME(), or forgetting to update the
argument when the function name is changed.
Hi James,

thanks a lot for the clarifications. Good idea, I will setup a macro
for the compilers I am targeting. You got me looking for that on the
net and found out that boost has something similar: boost/
current_function.hpp I will test that.

Thanks!

Aug 20 '08 #3
jma <ju***********@yahoo.comwrites:
I want to push some errors on an error stack in my function. The first
parameter of the push function is the name of the function where the
error occured. For example:

int MyFunction()
{
...
if(error1) pushError("MyFunction","Something is wrong");
...
if(error2) pushError("MyFunction","Something else is wrong");
...
if(error3) pushError("MyFunction","Something more is wrong");
}

To make things easier and less cluttered I could define two macros:
#define FUNCNAME(a) static const char funcname[]=#a;
#define PUSHERROR(a) pushError(funcname,#a)

then my function would look like:

int MyFunction()
{
FUNCNAME(MyFunction);
...
if(error1) PUSHERROR(Something is wrong);
...
if(error2) PUSHERROR(Something else is wrong);
...
if(error3) PUSHERROR(Something more is wrong);
}

which is better in terms of getting rid of useless literals but also
makes sure that the correct function name is always used in the error
stack.
[...]

Defining the function name in one place is a good idea, but using the
'#' operator to avoid using string literals for error messages is IMHO
ugly.

For example, in the invocation PUSHERROR(Something is wrong); you're
passing one argument consisting of three tokens, the identifiers
``Something'', ``is'', and ``wrong''. I was going to say that this
won't work, but after trying it and checking the standard I'm a bit
surprised to discover that it does; the # operator applies to a macro
argument, not to a single token.

Note that using this method you *can't* have an error message with a
comma in it:

PUSHERROR(Something is wrong, please fix it);

or, for example, an unmatched apostrophe:

PUSHERROR(This doesn't look right);

The rules for the # operator are complex enough (see C99 6.10.3.2)
that someone reading your code is likely to misunderstand it.

My advice: Don't use the # operator; just pass a string literal as the
argument:

PUSHERROR("This doesn't look right, please fix it");

You might consider declaring constants for all your error messages:

static const char *Problem_1 = "Something is wrong, please fix it";
static const char *Problem_2 = "Something else is wrong";

...

PUSHERROR(Problem_1);

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Aug 20 '08 #4
jma


Keith Thompson wrote:
jma <ju***********@yahoo.comwrites:
I want to push some errors on an error stack in my function. The first
parameter of the push function is the name of the function where the
error occured. For example:

int MyFunction()
{
...
if(error1) pushError("MyFunction","Something is wrong");
...
if(error2) pushError("MyFunction","Something else is wrong");
...
if(error3) pushError("MyFunction","Something more is wrong");
}

To make things easier and less cluttered I could define two macros:
#define FUNCNAME(a) static const char funcname[]=#a;
#define PUSHERROR(a) pushError(funcname,#a)

then my function would look like:

int MyFunction()
{
FUNCNAME(MyFunction);
...
if(error1) PUSHERROR(Something is wrong);
...
if(error2) PUSHERROR(Something else is wrong);
...
if(error3) PUSHERROR(Something more is wrong);
}

which is better in terms of getting rid of useless literals but also
makes sure that the correct function name is always used in the error
stack.
[...]

Defining the function name in one place is a good idea, but using the
'#' operator to avoid using string literals for error messages is IMHO
ugly.

For example, in the invocation PUSHERROR(Something is wrong); you're
passing one argument consisting of three tokens, the identifiers
``Something'', ``is'', and ``wrong''. I was going to say that this
won't work, but after trying it and checking the standard I'm a bit
surprised to discover that it does; the # operator applies to a macro
argument, not to a single token.

Note that using this method you *can't* have an error message with a
comma in it:

PUSHERROR(Something is wrong, please fix it);

or, for example, an unmatched apostrophe:

PUSHERROR(This doesn't look right);

The rules for the # operator are complex enough (see C99 6.10.3.2)
that someone reading your code is likely to misunderstand it.

My advice: Don't use the # operator; just pass a string literal as the
argument:

PUSHERROR("This doesn't look right, please fix it");

You might consider declaring constants for all your error messages:

static const char *Problem_1 = "Something is wrong, please fix it";
static const char *Problem_2 = "Something else is wrong";

...

PUSHERROR(Problem_1);

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Hi Keith,

you're right, it's better off without the # operator. I just wrote it
like this as an example that I know it works. In my application I
actually have an array of strings that is addressed with an
enumeration therefore I am actually doing what you're suggesting.

thanks a lot for the answer!

-- dimitris
Aug 21 '08 #5
On Aug 20, 7:26 am, jameskuy...@verizon.net wrote:
jma wrote:
>[wants to get a string containing the current name of the function]
Note: If you can afford to restrict the portability of your code to
C99 implementations, you can use the predefined identifier__func__
instead of funcname, and drop the FUNCNAME macro entirely:

6.4.2.2p1: "The identifier __func_ _ shall be implicitly declared by
the translator as if, immediately following the opening brace of each
function definition, the declaration

static const char _ _func_ _[] = "function-name";

appeared, where function-name is the name of the lexically-enclosing
function."

By using __func__, you can avoid any danger of, for instance,
misspelling the argument to FUNCNAME(), or forgetting to update the
argument when the function name is changed.
I'll just add that if your compiler doesn't have __func__, you might
see if it calls it __FUNCTION__ instead. And if it doesn't have
either, you may find that it has __FILE__ and __LINE__ instead, which
are the current source file name, as a string, and the line number, as
an integer, respectively; this might be good enough for your
purposes. I seem to recall that __FILE__ and __LINE__ were in C90,
but I do not have a copy of the standard to check. I'm sure someone
will correct me if I'm wrong.
Aug 23 '08 #6
fj*****@yahoo.com wrote:
....
purposes. I seem to recall that __FILE__ and __LINE__ were in C90,
but I do not have a copy of the standard to check. I'm sure someone
will correct me if I'm wrong.
Yes, __FILE__ and __LINE__ were present in C90.
Aug 23 '08 #7

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

Similar topics

16
by: Paul Prescod | last post by:
I skimmed the tutorial and something alarmed me. "Strings are a powerful data type in Prothon. Unlike many languages, they can be of unlimited size (constrained only by memory size) and can hold...
5
by: swarsa | last post by:
Hi All, I realize this is not a Palm OS development forum, however, even though my question is about a Palm C program I'm writing, I believe the topics are relevant here. This is because I...
3
by: Blue Man | last post by:
hello I am writing an error handling within different classes in asp.net. the error class reports the Exception E's string to the database. but it cuts big strings, if i just display the error it...
9
by: Steven | last post by:
Hello, I have a question about strcmp(). I have four words, who need to be compared if it were two strings. I tried adding the comparison values like '(strcmp(w1, w2) + strcmp(w3, w4))', where...
89
by: scroopy | last post by:
Hi, I've always used std::string but I'm having to use a 3rd party library that returns const char*s. Given: char* pString1 = "Blah "; const char* pString2 = "Blah Blah"; How do I append...
12
by: Kim Hellan | last post by:
I come from C# development, but I have to make a .NET WinForm application in C++. I'm having some troubles handling strings in C++, which seems a lot more problematic than in C#. Lets say I want...
19
by: pkirk25 | last post by:
I wonder if anyone has time to write a small example program based on this data or to critique my own effort? A file called Realm List.html contains the following data: Bladefist-Horde...
95
by: hstagni | last post by:
Where can I find a library to created text-based windows applications? Im looking for a library that can make windows and buttons inside console.. Many old apps were make like this, i guess ...
16
by: InDepth | last post by:
Now that .NET is at it's fourth release (3.5 is coming soon), my very humble question to the gurus is: "What have we won with the decision to have string objects immutable? Or did we won?" ...
5
by: Kelth.Raptor | last post by:
Im having some difficulty with strings here, I hope someone is kind enough to help, I do appreciate it. Im working on a grade point average calculator for my intro to programming class and I...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
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
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
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
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...
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...
0
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing,...

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.