By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
448,609 Members | 1,547 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 448,609 IT Pros & Developers. It's quick & easy.

How to use strings for error handling

P: n/a
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
Share this Question
Share on Google+
6 Replies


P: n/a
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

P: n/a
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

P: n/a
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

P: n/a
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

P: n/a
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

P: n/a
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 discussion thread is closed

Replies have been disabled for this discussion.