Velocity Reviews

Velocity Reviews (http://www.velocityreviews.com/forums/index.php)
-   C Programming (http://www.velocityreviews.com/forums/f42-c-programming.html)
-   -   How should I create verbose error information description (http://www.velocityreviews.com/forums/t436026-how-should-i-create-verbose-error-information-description.html)

Eric Lilja 12-02-2004 06:03 PM

How should I create verbose error information description
 
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



Dave Vandervies 12-02-2004 06:30 PM

Re: How should I create verbose error information description
 
In article <conle2$aln$1@news.island.liu.se>,
Eric Lilja <ericlilja_remove_this@yahoo.com> wrote:
>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 dj3vande@csclub.uwaterloo.ca
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

Eric Lilja 12-02-2004 07:43 PM

Re: How should I create verbose error information description
 

"Dave Vandervies" wrote:> In article <conle2$aln$1@news.island.liu.se>,
> Eric Lilja <ericlilja_remove_this@yahoo.com> wrote:
>>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 dj3vande@csclub.uwaterloo.ca
> 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



Eric Lilja 12-02-2004 08:06 PM

Re: How should I create verbose error information description
 

"Eric Lilja" <ericlilja_remove_this@yahoo.com> wrote in message
news:conr8s$c38$1@news.island.liu.se...
>
> "Dave Vandervies" wrote:> In article <conle2$aln$1@news.island.liu.se>,
>> Eric Lilja <ericlilja_remove_this@yahoo.com> wrote:
>>>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 dj3vande@csclub.uwaterloo.ca
>> 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



Eric Sosman 12-02-2004 08:11 PM

Re: How should I create verbose error information description
 
Eric Lilja wrote:
> "Dave Vandervies" wrote:> In article <conle2$aln$1@news.island.liu.se>,
>
>>Eric Lilja <ericlilja_remove_this@yahoo.com> wrote:
>>
>>>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.

--
Eric.Sosman@sun.com



Eric Lilja 12-02-2004 08:28 PM

Re: How should I create verbose error information description
 

"Eric Sosman" wrote:
> Eric Lilja wrote:
>> "Dave Vandervies" wrote:> In article <conle2$aln$1@news.island.liu.se>,
>>
>>>Eric Lilja <ericlilja_remove_this@yahoo.com> wrote:
>>>
>>>>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.
>
> --
> Eric.Sosman@sun.com
>
>


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



CBFalconer 12-03-2004 07:04 AM

Re: How should I create verbose error information description
 
Eric Lilja wrote:
>

.... 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.

--
Chuck F (cbfalconer@yahoo.com) (cbfalconer@worldnet.att.net)
Available for consulting/temporary embedded and systems.
<http://cbfalconer.home.att.net> USE worldnet address!



mef526 12-05-2004 09:03 AM

Re: How should I create verbose error information description
 

> 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);



Michael Mair 12-05-2004 12:16 PM

Re: How should I create verbose error information description
 
mef526 wrote:

>>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);


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
--
E-Mail: Mine is an /at/ gmx /dot/ de address.

Old Wolf 12-05-2004 08:34 PM

Re: How should I create verbose error information description
 
"Eric Lilja" <ericlilja_remove_this@yahoo.com> wrote:
> 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.


All times are GMT. The time now is 10:03 AM.

Powered by vBulletin®. Copyright ©2000 - 2014, vBulletin Solutions, Inc.
SEO by vBSEO ©2010, Crawlability, Inc.