Hi there,
I've written a function that 'converts' a structure of type timeval to
a c-string:
char *tv2Str(struct timeval tvX)
{
char caStr[20];
char *cpResult;
sprintf(caStr, "%ld.%ld", tvX.tv_sec, tvX.tv_usec);
cpResult = (char *)malloc(sizeof(char)*strlen(caStr));
strcpy(cpResult, caStr);
return cpResult;
}
I use it like this:
printf("%s", tv2Str((struct timeval){123, 456}) );
Question:
How (if at all) does the compiler (gcc) ensure that the memory
allocated in the above function is deallocated after the printf call ?
Thanks,
Cornel
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
0
|
|
|
|
Reply
|
Cornel
|
7/25/2003 11:07:41 AM |
|
"Cornel Arnet" <c.arnet@bluewin.ch> wrote in message
news:3f1fd671@epflnews.epfl.ch...
> Hi there,
>
> I've written a function that 'converts' a structure of type timeval to
> a c-string:
>
> char *tv2Str(struct timeval tvX)
> {
> char caStr[20];
> char *cpResult;
>
> sprintf(caStr, "%ld.%ld", tvX.tv_sec, tvX.tv_usec);
>
> cpResult = (char *)malloc(sizeof(char)*strlen(caStr));
> strcpy(cpResult, caStr);
>
> return cpResult;
> }
>
> I use it like this:
>
> printf("%s", tv2Str((struct timeval){123, 456}) );
>
> Question:
> How (if at all) does the compiler (gcc) ensure that the memory
> allocated in the above function is deallocated after the printf call ?
No, it doesn't. You have just created a memory leak. Any memory
allocated with malloc() must be explicitly deallocated with free(). To
fix the problem you would have to use tv2Str() like this:
timeval t = {123, 456};
char* s = tv2Str(t);
printf("%s", s);
free(s);
As you can see it is a bit cumbersome to do the C way. But since you
asked this question in C++ group, you might as well go for a more C++
like solution:
....
#include <cstdio>
#include <string>
#include <sstream>
std::string tv2Str(const timeval& tv)
{
std::stringstream text;
text << tv.tv_sec << "." << tv.tv_usec;
return text.str();
}
int main()
{
timeval tv = {123, 456};
printf("%s", tv2Str(tv).c_str());
return 0;
}
And to get rid of the C remnants altogether you might do it like this:
....
#include <iostream>
std::ostream& operator<<(std::ostream& out, const timeval& tv)
{
out << tv.tv_sec << "." << tv.tv_usec;
return out;
}
int main()
{
timeval tv = {123, 456};
std::cout << "Time: " << tv;
return 0;
}
--
Peter van Merkerk
peter.van.merkerk(at)dse.nl
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
0
|
|
|
|
Reply
|
Peter
|
7/26/2003 12:45:54 PM
|
|
On Fri, 25 Jul 2003 07:07:41 -0400, Cornel Arnet wrote:
> Hi there,
Hi _there_ :-)
> I've written a function that 'converts' a structure of type timeval to a
> c-string:
>
[...]
> cpResult = (char *)malloc(sizeof(char)*strlen(caStr));
> strcpy(cpResult, caStr);
strcpy copies strlen(caStr)+1 chars to the buffer. You allocated one less.
(There are a few other deficiencies in this function, which I won't
address now.)
BTW: sizeof(char) is 1 by definition.
> return cpResult;
> }
>
> I use it like this:
>
> printf("%s", tv2Str((struct timeval){123, 456}) );
GCC-specific syntax. BTW, what's wrong with puts? I see no need for printf
here.
> Question:
> How (if at all) does the compiler (gcc) ensure that the memory allocated
> in the above function is deallocated after the printf call ?
Not at all. You didn't tell it to deallocate anything, so it won't. The
canonical solution is called std::string, which encapsulates memory
management. This means a) automatic deallocation when the buffer is no
longer needed and b) No possibility of one-off errors like the one you
committed above. Please look up strings in your favorite C++ textbook. :-)
--
Best Regards, | Hi! I'm a .signature virus. Copy me into
Sebastian | your ~/.signature to help me spread!
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
0
|
|
|
|
Reply
|
Sebastian
|
7/26/2003 1:06:09 PM
|
|
<snip>
> cpResult = (char *)malloc(sizeof(char)*strlen(caStr));
<snip>
> How (if at all) does the compiler (gcc) ensure that the memory
> allocated in the above function is deallocated after the printf call ?
Hi :
Simple answer ... it doesn't . The caller of this
function will be responsible for deleting the memory.
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
0
|
|
|
|
Reply
|
steve
|
7/26/2003 1:12:11 PM
|
|
Hi,
> char *tv2Str(struct timeval tvX)
> {
> char caStr[20];
> char *cpResult;
> sprintf(caStr, "%ld.%ld", tvX.tv_sec, tvX.tv_usec);
> cpResult = (char *)malloc(sizeof(char)*strlen(caStr));
> strcpy(cpResult, caStr);
> return cpResult;
> }
> I use it like this:
> printf("%s", tv2Str((struct timeval){123, 456}) );
> Question:
> How (if at all) does the compiler (gcc) ensure that the memory
> allocated in the above function is deallocated after the printf call ?
As simple as it is: It doesn't. It is released as soon as the tv2Str
function is left because it is an automatic variable, thus rendering the
pointer invalid and making your use of the function dangerous. It
"might" appear to work sometimes, but don't count on it.
To prevent this trouble, you'd either
i) declare the string buffer as static and hence giving it a global
lifetime, understanding that there will be only one buffer in the
program and later calls will invalidate the buffers passed out earlier,
ii) manage the memory itself by allocating a buffer in tv2Str and
requiring for the caller to release it after it's done,
iii) use the string class
Greetings,
Thomas
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
0
|
|
|
|
Reply
|
Thomas
|
7/26/2003 4:05:23 PM
|
|
In message <3f1fd671@epflnews.epfl.ch>, Cornel Arnet
<c.arnet@bluewin.ch> writes
>I've written a function that 'converts' a structure of type timeval to
>a c-string:
>
>char *tv2Str(struct timeval tvX)
>{
> char caStr[20];
> char *cpResult;
>
> sprintf(caStr, "%ld.%ld", tvX.tv_sec, tvX.tv_usec);
>
> cpResult = (char *)malloc(sizeof(char)*strlen(caStr));
> strcpy(cpResult, caStr);
>
> return cpResult;
>}
>
>I use it like this:
>
>printf("%s", tv2Str((struct timeval){123, 456}) );
>
>Question:
>How (if at all) does the compiler (gcc) ensure that the memory
>allocated in the above function is deallocated after the printf call ?
It doesn't and it isn't. And you have a real problem in C (which your
code looks like) because there is nothing you can do about it. C++
provides you many solutions, most of which centre round avoiding that
explicit allocation of dynamic resources. Here is a minimalist amendment
to your code (far from being a stylistically elegant solution):
string tv2Str(struct timeval tvX)
{
char caStr[20];
sprintf(caStr, "%ld.%ld", tvX.tv_sec, tvX.tv_usec);
return caStr;
}
cout << tv2Str(timeval(123, 456));
assuming that you provide timeval with a ctor.
If you cannot use a C++ solution, then please post to
comp.lang.c.moderated instead.
--
ACCU Spring Conference 2003 April 2-5
The Conference you should not have missed
ACCU Spring Conference 2004 Late April
Francis Glassborow ACCU
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
0
|
|
|
|
Reply
|
Francis
|
7/26/2003 4:06:37 PM
|
|
In article <pan.2003.07.25.15.30.20.50854@gammaray.dyndns.org>,
on 26 Jul 2003 09:06:09 -0400,
Sebastian Kapfer <sebastian_kapfer@web.de> wrote:
> On Fri, 25 Jul 2003 07:07:41 -0400, Cornel Arnet wrote:
>
> > printf("%s", tv2Str((struct timeval){123, 456}) );
>
> BTW, what's wrong with puts? I see no need for printf
> here.
puts always adds a '\n' to the end of the output, which printf
doesn't. The right thing here (assuming the GCC extention) is:
fputs( tv2Str((struct timeval){123, 456}), stdout );
I strongly suspect that the addtional '\n' provided by puts (but not by
fputs) is why so many C programmers use printf as their "default" output
function, even when puts (or similar) would serve them better. I've
always considered this mismatch between puts/fputs to be a major flaw in
the C library.
Regards,
Andy S
--
"Light thinks it travels faster than anything but it is wrong. No matter
how fast light travels it finds the darkness has always got there first,
and is waiting for it." -- Terry Pratchett, Reaper Man
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
0
|
|
|
|
Reply
|
Andy
|
7/27/2003 10:38:57 AM
|
|
Cornel Arnet wrote:
> char *tv2Str(struct timeval tvX)
> {
> char caStr[20];
> char *cpResult;
>
> sprintf(caStr, "%ld.%ld", tvX.tv_sec, tvX.tv_usec);
>
> cpResult = (char *)malloc(sizeof(char)*strlen(caStr));
> strcpy(cpResult, caStr);
>
> return cpResult;
> }
>
> I use it like this:
>
> printf("%s", tv2Str((struct timeval){123, 456}) );
>
> Question:
> How (if at all) does the compiler (gcc) ensure that the memory
> allocated in the above function is deallocated after the printf call ?
It doesn't, you have a memory leak.
Uli
--
Questions ?
see C++-FAQ Lite: http://parashift.com/c++-faq-lite/ first !
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
0
|
|
|
|
Reply
|
Ulrich
|
7/27/2003 11:32:26 AM
|
|
Ben Hutchings wrote:
> In article <3f1fd671@epflnews.epfl.ch>, Cornel Arnet wrote:
> > Hi there,
> >
> > I've written a function that 'converts' a structure of type timeval
> to > a c-string: >
> > char *tv2Str(struct timeval tvX)
> > {
> > char caStr[20];
> > char *cpResult;
> >
> > sprintf(caStr, "%ld.%ld", tvX.tv_sec, tvX.tv_usec);
> >
> > cpResult = (char *)malloc(sizeof(char)*strlen(caStr));
> > strcpy(cpResult, caStr);
> > return cpResult;
> > }
>
> This looks very much like a C program, though it is valid in C++ too.
> Are you sure you posted to the right group?
>
> > I use it like this:
> >
> > printf("%s", tv2Str((struct timeval){123, 456}) );
>
> Struct literals are a GNU extension.
Also present in C99, I bleive, and under consideration
for C++0x, with a proposal before the committee.
-- James.
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
0
|
|
|
|
Reply
|
James
|
7/27/2003 5:01:51 PM
|
|
"Peter van Merkerk" <merkerk@deadspam.com> wrote in message
news:bfr8ru$hu004$1@ID-
> #include <cstdio>
> #include <string>
> #include <sstream>
> timeval tv = {123, 456};
> printf("%s", tv2Str(tv).c_str());
Because you include <cstdio> that should be std::printf.
--
+++++++++++
Siemel Naran
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
0
|
|
|
|
Reply
|
Siemel
|
7/27/2003 5:09:18 PM
|
|
On Sun, 27 Jul 2003 06:38:57 -0400, Andy Sawyer wrote:
> > > printf("%s", tv2Str((struct timeval){123, 456}) );
> >
> > BTW, what's wrong with puts? I see no need for printf here.
>
> puts always adds a '\n' to the end of the output, which printf doesn't.
Yes, I should have used fputs. Sorry.
> I strongly suspect that the addtional '\n' provided by puts (but not by
> fputs) is why so many C programmers use printf as their "default" output
> function, even when puts (or similar) would serve them better. I've
> always considered this mismatch between puts/fputs to be a major flaw in
> the C library.
puts and friends are ill-designed, that's right.
int putchar(int c);
int puts(const char *s);
int putc(int c, FILE *stream);
int fputs(const char *s, FILE *stream);
int fputc(int c, FILE *stream);
AFAIK these all are ISO C. IMO putc "may be implemented as a macro",
that's all what makes it different from fputc. putc does take a FILE
pointer, but its function name doesn't begin with "f". puts appends "\n",
fputs does not.
Sometimes, I think evolution should be forbidden :-)
--
Best Regards, | Hi! I'm a .signature virus. Copy me into
Sebastian | your ~/.signature to help me spread!
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
0
|
|
|
|
Reply
|
Sebastian
|
7/27/2003 5:18:09 PM
|
|
|
10 Replies
98 Views
(page loaded in 0.439 seconds)
Similiar Articles: comp.lang.c++.moderated - page 12memory deallocation 10 60 (7/25/2003 11:07:41 AM) Hi there, I've written a function that 'converts' a structure of type timeval to a c-string: char *tv2Str(struct ... Allocatable versus automatic arrays - comp.lang.fortran... increasing arrays); and when the total required memory by static allocation gets significant with respect to the total available memory, then allocation/deallocation ... Annoying kernel memory leak in U6? - comp.unix.solarisOther than that, there are (or at least there were) debug settings for /etc/system which cause kernel to track every memory allocation and deallocation. keyboard/mouse programming - comp.lang.asm.x86There exist implementations (e.g. x86 architecture when using far or huge data memory models and the AS/400) where deallocation of storage causes the _values_ of any ... Examples of C++ in Safety Critical Systems - comp.lang.c++ ...... always work because Ada's Unbounded_String always > deals with heap-based memory in its internal data representation. > It also automatically handles all deallocation ... Conditionally call a program - comp.soft-sys.sas... schematically: If U is used conditionally ... can the ALLOCATION / > DEALLOCATION ... How to check whether malloc has allocated memory properly in case ... > > That's ... Copying rows in a two dimensional array. - comp.lang.ada ...Size)" and perhaps later deallocate them using Unchecked_Deallocation. ... dimensional slice can generate much better code (using a direct memory-memory ... Allocation and Deallocation of Memory - The Caml language: HomeAllocation and Deallocation of Memory Most languages permit dynamic memory allocation, among them C, Pascal, Lisp, ML, SmallTalk, C++, Java, ADA. Dynamic Memory Allocation and DeallocationDynamic Memory Allocation and Deallocation. Dynamic Data; In addition to Static variables and Automatic variables, C and C++ provide a third category of variables ... 7/25/2012 4:32:12 PM
|