* how to implement routines that return general strings?
@ 2006-08-10 14:10 Robert P. J. Day
2006-08-10 17:12 ` Scott
2006-08-10 21:07 ` Glynn Clements
0 siblings, 2 replies; 10+ messages in thread
From: Robert P. J. Day @ 2006-08-10 14:10 UTC (permalink / raw)
To: C programming list
i'm about to design and implement a number of routines that return
strings and, as far as i can tell, i have two general design choices.
int func(char* buf, int bufsiz) ;
char* func() ;
that first form obviously accepts the address of a buffer (and its
size) into which to copy the result, and leaves the "int" return value
to be used perhaps as an error code. perfectly reasonable, but it
forces every invocation to first have a buffer ready to go.
the second form would be intuitively more natural, but is affected
by the scope of the result. the approach i would use there might be:
char*
func()
{
static buf[128] ; // or whatever size is appropriate
... copy result into buf ...
return buf ;
}
an error of some kind might be implemented by returning NULL, but that
will restrict the range of error codes i can pass back.
are there compelling arguments either way? while i like the natural
feel of the second form, i have to admit the first form is more
informative. thoughts?
rday
^ permalink raw reply [flat|nested] 10+ messages in thread
* RE: how to implement routines that return general strings?
@ 2006-08-10 16:51 Khan, Ahmer
0 siblings, 0 replies; 10+ messages in thread
From: Khan, Ahmer @ 2006-08-10 16:51 UTC (permalink / raw)
To: Robert P. J. Day, C programming list
It really depends on what func() is doing inside. If it's only
allocating memory and copying contents, then you can have the
char* func()
if it's doing other stuff too, like validating contents against various
rules, which can result in different error codes, then you should
consider using the
int func(...)
form. I think both approaches are otherwise ok.
Ahmer
-----Original Message-----
From: linux-c-programming-owner@vger.kernel.org
[mailto:linux-c-programming-owner@vger.kernel.org] On Behalf Of Robert
P. J. Day
Sent: Thursday, August 10, 2006 7:10 AM
To: C programming list
Subject: how to implement routines that return general strings?
i'm about to design and implement a number of routines that return
strings and, as far as i can tell, i have two general design choices.
int func(char* buf, int bufsiz) ;
char* func() ;
that first form obviously accepts the address of a buffer (and its
size) into which to copy the result, and leaves the "int" return value
to be used perhaps as an error code. perfectly reasonable, but it
forces every invocation to first have a buffer ready to go.
the second form would be intuitively more natural, but is affected
by the scope of the result. the approach i would use there might be:
char*
func()
{
static buf[128] ; // or whatever size is appropriate
... copy result into buf ...
return buf ;
}
an error of some kind might be implemented by returning NULL, but that
will restrict the range of error codes i can pass back.
are there compelling arguments either way? while i like the natural
feel of the second form, i have to admit the first form is more
informative. thoughts?
rday
-
To unsubscribe from this list: send the line "unsubscribe
linux-c-programming" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: how to implement routines that return general strings?
2006-08-10 14:10 how to implement routines that return general strings? Robert P. J. Day
@ 2006-08-10 17:12 ` Scott
2006-08-10 19:04 ` David Rientjes
2006-08-11 20:06 ` Kelly Burkhart
2006-08-10 21:07 ` Glynn Clements
1 sibling, 2 replies; 10+ messages in thread
From: Scott @ 2006-08-10 17:12 UTC (permalink / raw)
To: Robert P. J. Day, linux-c-programming
On Thu, Aug 10, 2006 at 10:10:21AM -0400, Robert P. J. Day wrote:
>
> i'm about to design and implement a number of routines that return
> strings and, as far as i can tell, i have two general design choices.
>
> int func(char* buf, int bufsiz) ;
> char* func() ;
>
With the caveat that I haven't done any serious programming in C for
many years: As I recall, I always used a protocol halfway between
these, as:
char *func(size_t bufsiz)
{
char *retval = malloc (bufsiz);
if (retval == NULL) return (NULL);
/* whatever */
return (retval);
}
My thinking being that the low-level memory allocation (or a static
buffer, if that is appropriate) is better handled in the lower-level
routine. NULL vs valid pointer was usually good enough, though I do
recall hacking something together with one of these to where a static
error-code was recorded in the routine if something went wrong, which
could be retrieved by sending a magic value for bufsiz:
char *foo = func(128);
if (foo == NULL) {
errcode = (int) func(0xFFFF);
.....
}
I suppose violating all precepts of proper coding, but it used to
work.....
Good luck, and I'd appreciate hearing what your final decision is!
Scott Swanson
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: how to implement routines that return general strings?
2006-08-10 17:12 ` Scott
@ 2006-08-10 19:04 ` David Rientjes
2006-08-11 20:06 ` Kelly Burkhart
1 sibling, 0 replies; 10+ messages in thread
From: David Rientjes @ 2006-08-10 19:04 UTC (permalink / raw)
To: Scott; +Cc: Robert P. J. Day, linux-c-programming
On 8/10/06, Scott <drmemory@3rivers.net> wrote:
> With the caveat that I haven't done any serious programming in C for
> many years: As I recall, I always used a protocol halfway between
> these, as:
>
> char *func(size_t bufsiz)
> {
> char *retval = malloc (bufsiz);
> if (retval == NULL) return (NULL);
> /* whatever */
> return (retval);
> }
>
It looks like this would lead to memory leaks that would be difficult
to track down along a wide variety of code paths upon return.
I recommend the first style: int func(char *buf, size_t bufsize). All
malloc and frees are then encouraged to sandwich this call.
David
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: how to implement routines that return general strings?
2006-08-10 14:10 how to implement routines that return general strings? Robert P. J. Day
2006-08-10 17:12 ` Scott
@ 2006-08-10 21:07 ` Glynn Clements
2006-08-11 7:03 ` Raseel Bhagat
1 sibling, 1 reply; 10+ messages in thread
From: Glynn Clements @ 2006-08-10 21:07 UTC (permalink / raw)
To: Robert P. J. Day; +Cc: C programming list
Robert P. J. Day wrote:
> i'm about to design and implement a number of routines that return
> strings and, as far as i can tell, i have two general design choices.
>
> int func(char* buf, int bufsiz) ;
> char* func() ;
>
> that first form obviously accepts the address of a buffer (and its
> size) into which to copy the result, and leaves the "int" return value
> to be used perhaps as an error code. perfectly reasonable, but it
> forces every invocation to first have a buffer ready to go.
>
> the second form would be intuitively more natural, but is affected
> by the scope of the result. the approach i would use there might be:
>
> char*
> func()
> {
> static buf[128] ; // or whatever size is appropriate
> ... copy result into buf ...
> return buf ;
> }
>
> an error of some kind might be implemented by returning NULL, but that
> will restrict the range of error codes i can pass back.
>
> are there compelling arguments either way? while i like the natural
> feel of the second form, i have to admit the first form is more
> informative. thoughts?
Avoid the second form. Apart from not being re-entrant, it can lead to
bugs which can be hard to find, particularly if the function in
question is relatively general-purpose and may be used from various
places in your code.
The first form should be used whenever you can determine in advance a
reasonable size for the buffer. Otherwise, use malloc().
--
Glynn Clements <glynn@gclements.plus.com>
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: how to implement routines that return general strings?
2006-08-10 21:07 ` Glynn Clements
@ 2006-08-11 7:03 ` Raseel Bhagat
2006-08-11 18:36 ` Shorty Porty
0 siblings, 1 reply; 10+ messages in thread
From: Raseel Bhagat @ 2006-08-11 7:03 UTC (permalink / raw)
To: C programming list
Hi Glynn,
On 8/11/06, Glynn Clements <glynn@gclements.plus.com> wrote:
> Avoid the second form. Apart from not being re-entrant, it can lead to
> bugs which can be hard to find, particularly if the function in
> question is relatively general-purpose and may be used from various
> places in your code.
Can you please ellaborate how you came to the conclusion that that
second form cannot be re-entrant and thus implying the first form is
?
--
Raseel.
http://osd.byethost8.com
http://raseel.livejournal.com
^ permalink raw reply [flat|nested] 10+ messages in thread
* RE: how to implement routines that return general strings?
2006-08-11 7:03 ` Raseel Bhagat
@ 2006-08-11 18:36 ` Shorty Porty
0 siblings, 0 replies; 10+ messages in thread
From: Shorty Porty @ 2006-08-11 18:36 UTC (permalink / raw)
To: 'Raseel Bhagat', 'C programming list'
On 8/11/06, Glynn Clements <glynn@gclements.plus.com> wrote:
> Avoid the second form. Apart from not being re-entrant, it can lead to
> bugs which can be hard to find, particularly if the function in
> question is relatively general-purpose and may be used from various
> places in your code.
char*
func()
{
static buf[128] ; // or whatever size is appropriate
... copy result into buf ...
return buf ;
}
It isn't re-entrant, because of the static buffer. In a process, all threads
will get the same copy of the static buffer, so if one thread calls the
function and hasn't copied the string contents before another threads calls
the function, they will both get the string from the 2nd call. If both
threads are inside that function at the same time, they are both going to be
playing with that buf[] at the same time. Icky.
Shorty
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: how to implement routines that return general strings?
2006-08-10 17:12 ` Scott
2006-08-10 19:04 ` David Rientjes
@ 2006-08-11 20:06 ` Kelly Burkhart
2006-08-12 9:36 ` Robert P. J. Day
1 sibling, 1 reply; 10+ messages in thread
From: Kelly Burkhart @ 2006-08-11 20:06 UTC (permalink / raw)
To: linux-c-programming
On 8/10/06, Scott <drmemory@3rivers.net> wrote:
> With the caveat that I haven't done any serious programming in C for
> many years: As I recall, I always used a protocol halfway between
> these, as:
>
> char *func(size_t bufsiz)
> {
> char *retval = malloc (bufsiz);
> if (retval == NULL) return (NULL);
> /* whatever */
> return (retval);
> }
This code is to live in a shared library and you wish for it to be
portable then you may want to keep in mind the difficulties on some
platforms of allocating memory in one shared library and freeing in
another. If this concern is relevant to you, the above must be paired
with void funcCleanup(char*).
This approach is also nice if the calling function can't know the
amount of memory necessary to allocate.
-K
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: how to implement routines that return general strings?
2006-08-11 20:06 ` Kelly Burkhart
@ 2006-08-12 9:36 ` Robert P. J. Day
2006-08-14 18:15 ` Scott
0 siblings, 1 reply; 10+ messages in thread
From: Robert P. J. Day @ 2006-08-12 9:36 UTC (permalink / raw)
To: Kelly Burkhart; +Cc: linux-c-programming
On Fri, 11 Aug 2006, Kelly Burkhart wrote:
> On 8/10/06, Scott <drmemory@3rivers.net> wrote:
> > With the caveat that I haven't done any serious programming in C for
> > many years: As I recall, I always used a protocol halfway between
> > these, as:
> >
> > char *func(size_t bufsiz)
> > {
> > char *retval = malloc (bufsiz);
> > if (retval == NULL) return (NULL);
> > /* whatever */
> > return (retval);
> > }
>
> This code is to live in a shared library and you wish for it to be
> portable then you may want to keep in mind the difficulties on some
> platforms of allocating memory in one shared library and freeing in
> another. If this concern is relevant to you, the above must be
> paired with void funcCleanup(char*).
obviously, if i chose to do it this way, i'd first check if a malloc()
had already been done, so i don't keep malloc()ing unnecessarily
(keeping a static pointer, naturally).
that would seem to be functionally equivalent to just declaring a
static array of characters within that routine, anyway.
rday
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: how to implement routines that return general strings?
2006-08-12 9:36 ` Robert P. J. Day
@ 2006-08-14 18:15 ` Scott
0 siblings, 0 replies; 10+ messages in thread
From: Scott @ 2006-08-14 18:15 UTC (permalink / raw)
To: linux-c-programming
On Sat, Aug 12, 2006 at 05:36:51AM -0400, Robert P. J. Day wrote:
> On Fri, 11 Aug 2006, Kelly Burkhart wrote:
>
> > On 8/10/06, Scott <drmemory@3rivers.net> wrote:
> > > With the caveat that I haven't done any serious programming in C for
> > > many years: As I recall, I always used a protocol halfway between
> > > these, as:
> > >
> > > char *func(size_t bufsiz)
> > > {
> > > char *retval = malloc (bufsiz);
> > > if (retval == NULL) return (NULL);
> > > /* whatever */
> > > return (retval);
> > > }
> >
> > This code is to live in a shared library and you wish for it to be
> > portable then you may want to keep in mind the difficulties on some
> > platforms of allocating memory in one shared library and freeing in
> > another. If this concern is relevant to you, the above must be
> > paired with void funcCleanup(char*).
>
> obviously, if i chose to do it this way, i'd first check if a malloc()
> had already been done, so i don't keep malloc()ing unnecessarily
> (keeping a static pointer, naturally).
>
> that would seem to be functionally equivalent to just declaring a
> static array of characters within that routine, anyway.
I guess I assumed that the caller of a library routine like this would
*want* a brand-new array. And of course with that want comes the
responsibilty for taking care of it and letting it swim back into the
memory pool when you are finished with it. Use a static (whether array
or pointer) and you are back to problems with re-entrancy.
Scott Swanson
^ permalink raw reply [flat|nested] 10+ messages in thread
end of thread, other threads:[~2006-08-14 18:15 UTC | newest]
Thread overview: 10+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2006-08-10 14:10 how to implement routines that return general strings? Robert P. J. Day
2006-08-10 17:12 ` Scott
2006-08-10 19:04 ` David Rientjes
2006-08-11 20:06 ` Kelly Burkhart
2006-08-12 9:36 ` Robert P. J. Day
2006-08-14 18:15 ` Scott
2006-08-10 21:07 ` Glynn Clements
2006-08-11 7:03 ` Raseel Bhagat
2006-08-11 18:36 ` Shorty Porty
-- strict thread matches above, loose matches on Subject: below --
2006-08-10 16:51 Khan, Ahmer
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).