How should I create verbose error information description

E

Eric Lilja

Hello, I'm a novice C++ programmer and now I have the task of converting
a number of C++ functions to C. Some of the functions I'm converting takes a
parameter
of type reference-to-std::string that stores verbose error information if an
error occurs in
the function.

How should I implement that in C? A pointer to a fixed-size array of chars
runs the risk
of overflowing. Having the function take a char** and allocate memory as
necessary
seems a poor idea too...reallocations might be needed and the user must
remember that
deallocate.

Any suggestions?

/ Eric
 
D

Dave Vandervies

Hello, I'm a novice C++ programmer and now I have the task of converting
a number of C++ functions to C. Some of the functions I'm converting takes a
parameter
of type reference-to-std::string that stores verbose error information if an
error occurs in
the function.
How should I implement that in C? A pointer to a fixed-size array of chars
runs the risk
of overflowing. Having the function take a char** and allocate memory as
necessary
seems a poor idea too...reallocations might be needed and the user must
remember that
deallocate.

Any suggestions?

I assume that you need to dynamically generate the verbose error
information; otherwise just taking a char** and pointing the char*
it points to at a string literal will work:
--------
if(errstring)
*errstring="Verbose error information";
--------

If you can put a reasonable upper bound on the length of the information
you need to return, you can statically allocate a buffer and return a
pointer to that:
--------
if(errstring)
{
/*static means it will stick around after we return, which is what we
want.
Note that this also means the caller will need to extract any
useful information before calling this code again, as another
error will overwrite it.
*/
static char errbuf[BIG_ENOUGH];

/*Using snprintf just to be paranoid
Note that snprintf is new in C99. It's also available as a GNU
extension, with different return value semantics (return value
isn't used here, so the difference won't cause problems).
If snprintf isn't available, check your maximum format length more
carefully and use sprintf.
*/
snprintf(errbuf,BIG_ENOUGH,"Verbose error info: foo is %d, bar is %g",foo,bar);
*errstring=errbuf;
}
--------

If you don't have a way to know at compile time how long the string
can get, you'll need to somehow allocate memory for it at run time.
Keeping a static pointer to that buffer in your code (similar to just
keeping a static buffer) will let the caller not need to worry about
deallocating it, as you can recycle it (resizing it if necessary) the
next time you need it.


dave
 
E

Eric Lilja

Dave Vandervies" wrote:> In article said:
Eric Lilja said:
Hello, I'm a novice C++ programmer and now I have the task of converting
a number of C++ functions to C. Some of the functions I'm converting takes
a
parameter
of type reference-to-std::string that stores verbose error information if
an
error occurs in
the function.
How should I implement that in C? A pointer to a fixed-size array of chars
runs the risk
of overflowing. Having the function take a char** and allocate memory as
necessary
seems a poor idea too...reallocations might be needed and the user must
remember that
deallocate.

Any suggestions?

I assume that you need to dynamically generate the verbose error
information; otherwise just taking a char** and pointing the char*
it points to at a string literal will work:
--------
if(errstring)
*errstring="Verbose error information";
--------

If you can put a reasonable upper bound on the length of the information
you need to return, you can statically allocate a buffer and return a
pointer to that:
--------
if(errstring)
{
/*static means it will stick around after we return, which is what we
want.
Note that this also means the caller will need to extract any
useful information before calling this code again, as another
error will overwrite it.
*/
static char errbuf[BIG_ENOUGH];

/*Using snprintf just to be paranoid
Note that snprintf is new in C99. It's also available as a GNU
extension, with different return value semantics (return value
isn't used here, so the difference won't cause problems).
If snprintf isn't available, check your maximum format length more
carefully and use sprintf.
*/
snprintf(errbuf,BIG_ENOUGH,"Verbose error info: foo is %d, bar is
%g",foo,bar);
*errstring=errbuf;
}
--------

If you don't have a way to know at compile time how long the string
can get, you'll need to somehow allocate memory for it at run time.
Keeping a static pointer to that buffer in your code (similar to just
keeping a static buffer) will let the caller not need to worry about
deallocating it, as you can recycle it (resizing it if necessary) the
next time you need it.


dave

--
Dave Vandervies (e-mail address removed)
I'd better change my domain then; I'm in .net, and I'm physically
somewhere on the Net; it's far too easy for folks to guess *that*.
--Anthony de Boer in the scary devil monastery

Thanks for your input, Dave. Pondering my alternatives here...the thing
is that I need to make this thread-safe and that rules out any static
variables,
I guess. And having the user call free() after each time he/she calls a
function,
wanting detailed error information seems cumbersome for the user. I guess
I have to make sure the error information generated never exceeds a certain
size and really point out in the documentation that this function requires a
buffer
of at least x amout of bytes.

/ Eric
 
E

Eric Lilja

Eric Lilja said:
Dave Vandervies" wrote:> In article said:
Eric Lilja said:
Hello, I'm a novice C++ programmer and now I have the task of converting
a number of C++ functions to C. Some of the functions I'm converting
takes a
parameter
of type reference-to-std::string that stores verbose error information if
an
error occurs in
the function.
How should I implement that in C? A pointer to a fixed-size array of
chars
runs the risk
of overflowing. Having the function take a char** and allocate memory as
necessary
seems a poor idea too...reallocations might be needed and the user must
remember that
deallocate.

Any suggestions?

I assume that you need to dynamically generate the verbose error
information; otherwise just taking a char** and pointing the char*
it points to at a string literal will work:
--------
if(errstring)
*errstring="Verbose error information";
--------

If you can put a reasonable upper bound on the length of the information
you need to return, you can statically allocate a buffer and return a
pointer to that:
--------
if(errstring)
{
/*static means it will stick around after we return, which is what we
want.
Note that this also means the caller will need to extract any
useful information before calling this code again, as another
error will overwrite it.
*/
static char errbuf[BIG_ENOUGH];

/*Using snprintf just to be paranoid
Note that snprintf is new in C99. It's also available as a GNU
extension, with different return value semantics (return value
isn't used here, so the difference won't cause problems).
If snprintf isn't available, check your maximum format length more
carefully and use sprintf.
*/
snprintf(errbuf,BIG_ENOUGH,"Verbose error info: foo is %d, bar is
%g",foo,bar);
*errstring=errbuf;
}
--------

If you don't have a way to know at compile time how long the string
can get, you'll need to somehow allocate memory for it at run time.
Keeping a static pointer to that buffer in your code (similar to just
keeping a static buffer) will let the caller not need to worry about
deallocating it, as you can recycle it (resizing it if necessary) the
next time you need it.


dave

--
Dave Vandervies (e-mail address removed)
I'd better change my domain then; I'm in .net, and I'm physically
somewhere on the Net; it's far too easy for folks to guess *that*.
--Anthony de Boer in the scary devil monastery

Thanks for your input, Dave. Pondering my alternatives here...the thing
is that I need to make this thread-safe and that rules out any static
variables,
I guess. And having the user call free() after each time he/she calls a
function,
wanting detailed error information seems cumbersome for the user. I guess
I have to make sure the error information generated never exceeds a
certain
size and really point out in the documentation that this function requires
a buffer
of at least x amout of bytes.

/ Eric

Unfortunately, snprintf() wasn't available on one of the two compilers I
have to
work with so I guess I have to write something that mimics its behaviour.
Some
strings are of known length, some are generated during runtime by calling os
layer
api functions.

/ Eric
 
E

Eric Sosman

Eric said:
Dave Vandervies" wrote:> In article said:
Eric Lilja said:
Hello, I'm a novice C++ programmer and now I have the task of converting
a number of C++ functions to C. Some of the functions I'm converting takes
a
parameter
of type reference-to-std::string that stores verbose error information if
an
error occurs in
the function.
How should I implement that in C? A pointer to a fixed-size array of chars
runs the risk
of overflowing. Having the function take a char** and allocate memory as
necessary
seems a poor idea too...reallocations might be needed and the user must
remember that
deallocate.

Any suggestions?

I assume that you need to dynamically generate the verbose error
information; otherwise just taking a char** and pointing the char*
it points to at a string literal will work:
--------
if(errstring)
*errstring="Verbose error information";
--------

If you can put a reasonable upper bound on the length of the information
you need to return, you can statically allocate a buffer and return a
pointer to that:
--------
if(errstring)
{
/*static means it will stick around after we return, which is what we
want.
Note that this also means the caller will need to extract any
useful information before calling this code again, as another
error will overwrite it.
*/
static char errbuf[BIG_ENOUGH];

/*Using snprintf just to be paranoid
Note that snprintf is new in C99. It's also available as a GNU
extension, with different return value semantics (return value
isn't used here, so the difference won't cause problems).
If snprintf isn't available, check your maximum format length more
carefully and use sprintf.
*/
snprintf(errbuf,BIG_ENOUGH,"Verbose error info: foo is %d, bar is
%g",foo,bar);
*errstring=errbuf;
}
--------

If you don't have a way to know at compile time how long the string
can get, you'll need to somehow allocate memory for it at run time.
Keeping a static pointer to that buffer in your code (similar to just
keeping a static buffer) will let the caller not need to worry about
deallocating it, as you can recycle it (resizing it if necessary) the
next time you need it.

Thanks for your input, Dave. Pondering my alternatives here...the thing
is that I need to make this thread-safe and that rules out any static
variables,
I guess. And having the user call free() after each time he/she calls a
function,
wanting detailed error information seems cumbersome for the user. I guess
I have to make sure the error information generated never exceeds a certain
size and really point out in the documentation that this function requires a
buffer
of at least x amout of bytes.

Another possibility might be to let the caller provide
both a pointer to a `char' array and the array's size, then
use snprintf() to generate the message directly into the
caller's buffer. If the buffer is too short the caller gets
a truncated message

frammis.c line 327: giving up after -2147483648 wa

.... but nothing worse happens.
 
E

Eric Lilja

Eric Sosman" said:
Eric said:
Dave Vandervies" wrote:> In article said:
Hello, I'm a novice C++ programmer and now I have the task of converting
a number of C++ functions to C. Some of the functions I'm converting
takes
a
parameter
of type reference-to-std::string that stores verbose error information
if
an
error occurs in
the function.

How should I implement that in C? A pointer to a fixed-size array of
chars
runs the risk
of overflowing. Having the function take a char** and allocate memory as
necessary
seems a poor idea too...reallocations might be needed and the user must
remember that
deallocate.

Any suggestions?

I assume that you need to dynamically generate the verbose error
information; otherwise just taking a char** and pointing the char*
it points to at a string literal will work:
--------
if(errstring)
*errstring="Verbose error information";
--------

If you can put a reasonable upper bound on the length of the information
you need to return, you can statically allocate a buffer and return a
pointer to that:
--------
if(errstring)
{
/*static means it will stick around after we return, which is what we
want.
Note that this also means the caller will need to extract any
useful information before calling this code again, as another
error will overwrite it.
*/
static char errbuf[BIG_ENOUGH];

/*Using snprintf just to be paranoid
Note that snprintf is new in C99. It's also available as a GNU
extension, with different return value semantics (return value
isn't used here, so the difference won't cause problems).
If snprintf isn't available, check your maximum format length more
carefully and use sprintf.
*/
snprintf(errbuf,BIG_ENOUGH,"Verbose error info: foo is %d, bar is
%g",foo,bar);
*errstring=errbuf;
}
--------

If you don't have a way to know at compile time how long the string
can get, you'll need to somehow allocate memory for it at run time.
Keeping a static pointer to that buffer in your code (similar to just
keeping a static buffer) will let the caller not need to worry about
deallocating it, as you can recycle it (resizing it if necessary) the
next time you need it.

Thanks for your input, Dave. Pondering my alternatives here...the thing
is that I need to make this thread-safe and that rules out any static
variables,
I guess. And having the user call free() after each time he/she calls a
function,
wanting detailed error information seems cumbersome for the user. I guess
I have to make sure the error information generated never exceeds a
certain
size and really point out in the documentation that this function
requires a
buffer
of at least x amout of bytes.

Another possibility might be to let the caller provide
both a pointer to a `char' array and the array's size, then
use snprintf() to generate the message directly into the
caller's buffer. If the buffer is too short the caller gets
a truncated message

frammis.c line 327: giving up after -2147483648 wa

... but nothing worse happens.

Yes, that's another alternative. Seems like an extra argument is worth it so
the user
won't have the remember the value of how small the buffer is allowed to be.
Thank
you for your help.

And, I was wrong before...both compilers I'm working provide extensions that
mimics
the behaviour of C99's snprintf() so I am using a simple preprocessor-macro
in my code
to decide which version should be compiled.

/ Eric
 
C

CBFalconer

Eric said:
.... snip ...

Unfortunately, snprintf() wasn't available on one of the two compilers I
have to
work with so I guess I have to write something that mimics its behaviour.
Some
strings are of known length, some are generated during runtime by calling os
layer
api functions.

snprintf is a C99 function.

If you limit your line lengths to below 80 (better 65) you will
avoid the ugly effects above.
 
M

mef526

Unfortunately, snprintf() wasn't available on one of the two compilers I
have to
work with so I guess I have to write something that mimics its behaviour.
Some
strings are of known length, some are generated during runtime by calling
os layer
api functions.

/ Eric

You can use this:
printf("%*s", MY_BUF_MAX_SIZE, pcMyBuf);
 
M

Michael Mair

mef526 said:
You can use this:
printf("%*s", MY_BUF_MAX_SIZE, pcMyBuf);

Which is completely wrong. The fieldwidth specifies the _minimal_
number of characters written by *printf() for the specified conversion.

What you are looking for is the _precision_ which specifies
the desired upper bound (for %s conversions)
fprintf(stderr, "%.*s", MY_BUF_MAX_SIZE, pcMyBuf);

However, as soon as you do not want to write out possibly truncated
versions of string literals but want to insert additional information,
snprintf() is a good deal easier to use.

-Michael
 
O

Old Wolf

Eric Lilja said:
Hello, I'm a novice C++ programmer and now I have the task of converting
a number of C++ functions to C. Some of the functions I'm converting takes a
parameter of type reference-to-std::string that stores verbose error information > if an error occurs in the function.
Having the function take a char** and allocate memory as
necessary seems a poor idea too...reallocations might be
needed and the user must remember that deallocate.

The obvious thing to do is to emulate std::string in C code.
The user of the function doesn't need to deallocate anything -
if the C++ code passed a reference then the calling function
is responsible for memory management.

I would start off with something like this:
typedef struct {
char *buf;
size_t capacity;
} STRING;
void STRING_construct(STRING *s, char const *initial_text);
void STRING_destruct(STRING *s);
void STRING_append(STRING const *s);
void STRING_assign(char const *text);

That should cover most of the operations that you'll need.
If you want to get fancy you can maintain a 'size_t len' as well.

Then you don't have to redesign any of the code (and
risk creating new bugs), just replace std::string with
STRING everywhere; call 'construct' after each STRING
is declared, and call 'destruct' at the matching
closing-brace after the construction.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
474,156
Messages
2,570,878
Members
47,406
Latest member
ElizabetMo

Latest Threads

Top