free() is useless...

J

Jens.Toerring

The above line has a bug in that the buffer is one byte too short.

Sorry, but the sizeof operator is applied here to a literal string
and that, if I am not completely mistaken, includes the trailing
'\0'. Of course, if the OP would have used strlen() instead it
would be a different story.
You are lucky however since malloc generally returns a minimum of 8
bytes.

If the problem would exist he might have been lucky because of that,
but there's no guarantee that all malloc() implementations allocate
at least 8 chars.
Contradicting some other posters, you should cast.

Would you care to tell why?
Regards, Jens
 
G

Gordon Burditt

"return 0;" and "return EXIT_SUCCESS;" are equally valid.
But are they the same?

Not necessarily.
I know what value "return 0;" will return. What value will
"return EXIT_SUCCESS;" return?

The "return 0" might return a status code of 1 to the VMS command
interpreter, or it might return EXIT_SUCCESS_YOU_DONT_GET_FIRED_THIS_WEEK.

"return EXIT_SUCCESS" might return
EXIT_SUCCESS_WITH_PROMOTION_AND_STOCK_OPTIONS.

Gordon L. Burditt
 
K

Keith Thompson

William L. Bahn said:
Keith Thompson said:
William L. Bahn said:
news:1094106488.725114@sj-nntpcache-5... [...]
No need to cast the return value of malloc.

Unless your compiler, like mine, would throw the following error
(not warning):

Compiling JUNKER.C:
Error JUNKER.C 19: Cannot convert 'void *' to 'char *' in
function main()

And that's when it is configured for ANSI compliance

ANSI *what* compliance?

Some compilers assume that a source file suffix of ".C" implies
C++, and ".c" implies C. Change the name from "JUNKER.C" to
"junker.c" and try again.

FWIW - the compiler is Borland TurboC/C++ v4.5,

The compiler always prints the file names in all uppercase.

The filename is all lower case - and, being a DOS/Windows
implementation, the user doesn't have very good control over case
in filenames anyway.

I'm pretty sure that it uses *.c for C files and *.cpp. If you
save it using the compiler supplied filename (and hence a *.cpp
extension) then you definitely get different compile behavior for
certain things.

I don't know how your compiler works; you might check the
documentation. What I do know is this: if a compiler fails to compile
the following:

#include <stdlib.h>
#include <stdio.h>
int main(void)
{
char *ptr = malloc(100);
printf("ptr = %p\n", (void*)ptr);
return 0;
}

it's not acting as a C compiler. (If it complains about not being
able to convert void* to char*, it's probably acting as a C++
compiler.)

It's possible that what matters is the case of the file name you give
to the compiler, but the details are off-topic.
 
F

Flash Gordon

On 2 Sep 2004 15:05:51 -0700
(e-mail address removed) (Matt Gostick) wrote in message


The above line has a bug in that the buffer is one byte too short.
You are lucky however since malloc generally returns a minimum of 8
bytes.

No. sizeof returns the size of the objext which will include the null
termination. If strlen had been used then you would be correct.
Contradicting some other posters, you should cast.

There is no requirement for the cast in C and providing the cast can
hide a failure to include stdlib.h
You don't
need the second sizeof() since malloc takes a number of bytes and
sizeof returns bytes.

<snip>

Correct.
 
K

Keith Thompson

William L. Bahn said:
But are they the same?

I know what value "return 0;" will return. What value will
"return EXIT_SUCCESS;" return?

Executing a return from main() is (nearly) equivalent to calling
exit() with the same argument.

The standard's description of exit() ('*' denoting bold type, '_'
denoting italics) says:

Finally, control is returned to the host environment. If the
value of *status* is zero or *EXIT_SUCCESS*, an
implementation-defined form of the status _successful termination_
is returned. If the value of *status* is *EXIT_FAILURE*, an
implementation-defined form of the status _unsuccessful
termination_ is returned. Otherwise the status returned is
implementation-defined.

There's some debate about whether zero and EXIT_SUCCESS are required
to return the *same* form of a successful termination status.

Incidentally, you probably *don't* know what "return 0;" will return,
at least not on all systems. Under OpenVMS, a program returning an
even value to the environment denotes an error; an odd value denotes
success. The C runtime system maps a "return 0;" to a status of 1.
(It doesn't map "return 1;" to 0, so "return 1;" indicates a
successful status; on Unix, "return 1;" indicates failure.)
 
F

Flash Gordon

On 2 Sep 2004 10:37:32 -0700
(e-mail address removed) (tristan) wrote:

char *blah_3 (void) {
char *buf;
size_t size;

/* the size of a pointer variable! */
size = sizeof("foobar");

No, it's the size of the object "foobar" INCLUDING the null termination.
buf = malloc(size);
/* overflows unless sizeof(char *) >= 7 */
strcpy(buf, "foobar");

return buf;
}


Tristan

markg@brenda ~ $ cat t.c
#include <stdio.h>

int main(void)
{
char *p;

printf("sizeof \"foobar\" = %lu\n",(unsigned long)sizeof "foobar");
printf("sizeof char* = %lu\n",(unsigned long)sizeof p);

return 0;
}

markg@brenda ~ $ gcc -ansi -pedantic -Wall -O -W t.c
markg@brenda ~ $ ./a.out
sizeof "foobar" = 7
sizeof char* = 4
markg@brenda ~ $
 
E

Eric Amick

char *blah_3 (void) {
char *buf;
size_t size;

/* the size of a pointer variable! */
size = sizeof("foobar");

Not so. The type of a string literal is char[], and sizeof returns the
size in bytes of an array given as its operand.
 
K

Keith Thompson

Eric Amick said:
char *blah_3 (void) {
char *buf;
size_t size;

/* the size of a pointer variable! */
size = sizeof("foobar");

Not so. The type of a string literal is char[], and sizeof returns the
size in bytes of an array given as its operand.

No, there's a specific exception for sizeof.

C99 6.3.2.1p3:

Except when it is the operand of the sizeof operator or the unary
& operator, or is a string literal used to initialize an array, an
expression that has type "array of type" is converted to an
expression with type "pointer to type" that points to the initial
element of the array object and is not an lvalue.

sizeof("foobar") yields 7.
 
C

CBFalconer

William L. Bahn said:
.... snip ...

I know what value "return 0;" will return. What value will
"return EXIT_SUCCESS;" return?

They will both return something that means "I did not fail" to the
OS. What exactly that is is not defined in C. It probably is
defined to the OS.
 
C

CBFalconer

Matthew said:
(e-mail address removed) (Matt Gostick) wrote in message


The above line has a bug in that the buffer is one byte too short.
You are lucky however since malloc generally returns a minimum of 8
bytes. Contradicting some other posters, you should cast. You
don't need the second sizeof() since malloc takes a number of bytes
and sizeof returns bytes.

You should have written unlucky, in the erroneous assumption that
you are correct, which you are not. "foobar" is an array of 7
chars, which is what sizeof "foobar" should return. There is no
default minimum for the size allocated by malloc. He should NOT
cast the output of malloc, and sizeof char is always 1 by
definition. Thus the line should read:

s = malloc(sizeof "foobar");

followed by a test of s for NULL, and appropriate error action.

.... snip ...
Dynamic Memory Solutions (my company) sells Dynamic Leak Check for
Solaris and Linux. It checks for memory leaks and a variety of other
errors, www.dynamic-memory.com.

Your errors above cast a doubt on the quality of your software.
 
W

William L. Bahn

Mabden said:
William L. Bahn said:
Keith Thompson said:
[...]
return 0;

return EXIT_SUCCESS :)

"return 0;" and "return EXIT_SUCCESS;" are equally valid.

But are they the same?

I know what value "return 0;" will return. What value will
"return EXIT_SUCCESS;" return?

I want to say, whatever EXIT_SUCCESS is defined as... Or is that too
obvious?

Programmers tend to use zero as a success and other numbers are errors
because there are more ways for something to go wrong than to
go right.

Agreed. But when I use EXIT_SUCCESS, I don't know if that will
return a 0 or not.
 
F

Flash Gordon

Mabden said:
William L. Bahn said:
[...]
return 0;

return EXIT_SUCCESS :)

"return 0;" and "return EXIT_SUCCESS;" are equally valid.

But are they the same?

I know what value "return 0;" will return. What value will
"return EXIT_SUCCESS;" return?

I want to say, whatever EXIT_SUCCESS is defined as... Or is that too
obvious?

Programmers tend to use zero as a success and other numbers are errors
because there are more ways for something to go wrong than to
go right.

Agreed. But when I use EXIT_SUCCESS, I don't know if that will
return a 0 or not.

As has been pointed out else thread you don't know what it will return
if you return 0 either. Under VMS you can be certain it will not return
0 because that would indicate failure and the C standard says that when
you return 0 from main the environment is to get an indication of
successful termination.

<OT>
For some classes of program I deliberately use non-portable return
values because it is more useful to indicate the cause of the failure
than it is to support platforms I don't need to where the values I've
chosen won't work. However, this is a conscious trade-off of portability
for functionality on the systems I need to actively support.
</OT>
 
M

Matthew Fisher

CBFalconer said:
You should have written unlucky, in the erroneous assumption that
you are correct, which you are not. "foobar" is an array of 7
chars, which is what sizeof "foobar" should return. There is no
default minimum for the size allocated by malloc. He should NOT
cast the output of malloc, and sizeof char is always 1 by
definition. Thus the line should read:

s = malloc(sizeof "foobar");

Wondering off topic a bit, why don't you think the cast is wise?
Sloppy type punning is always bad in my opinion. Also, a C++ compiler
will give any error.

You a wrong about minimum sizes returned from malloc. On all systems
that I have worked the minumum size returned is sizeof(double). This
appears to be required since malloc must return aligned memory. In
the example, if malloc were allowed to return a block of 7 bytes what
would it do with the 8th byte? I suppose it could hope for a call of
malloc(1) and assume that no alignment is needed. Do you know of any
such systems?

I am not clear on what the standard calls for. The minimum size may
just be an implementation detail nonetheless it exists.

Matthew
Dynamic Memory Solutions
www.dynamic-memory.com
 
C

Chris Torek

Wondering off topic a bit, why don't [people] think the cast [on
the result of malloc] is wise?

It does nothing in C89 that the language does not already do for
you, and -- in that same standard language -- it hides the frequent
error of failure to #include <stdlib.h>.

C99 requires a diagnostic when calling a function that has not been
declared, so modern C (if one has it available) removes the problem
that omitting the cast solves. (Good C89 compilers may also warn
about calling undeclared functions.) The cast remains useless
adornment, however. Compare with:

int i;
long l;
double d;

... set i to something ...
l = (long)i;
d = (double)i;

Some might argue for just the (double) cast, and some might even
argue for both casts, but I prefer to omit both.
Sloppy type punning is always bad in my opinion.

Casting is not punning -- casting converts values. Punning can be
done via "behind the back" addressing (not always guaranteed to work),
or (works more often but still pretty iffy) unions:

union { unsigned ui; char *cp; } u;
u.cp = "some string";
printf("punned as an int, the string became %x\n", u.ui);
/* WARNING: use of u.ui here is either undefined or, at best,
implementation-defined, although it probably "works" as
long as sizeof(char *) and sizeof(int) are comparable. */

The problem is that a cast is "too strong", overriding
otherwise-required diagnostics for dodgy conversions:

int intfunc();
double *dp;
...
dp = (double *)intfunc(); /* implementation-defined */

This code fragment requires no diagnostics, and usually receives
none.
Also, a C++ compiler will give any error.

A C++ compiler will also do the wrong thing with some C programs.
For instance (note that this program is deliberately constructed,
but similar situations can occur in other, real programs):

#include <stdio.h>

struct A { char c[16]; };

int main(void) {
struct B {
struct A { char c[1024]; } elem;
} localvar;

printf("sizeof(struct A) = %lu\n", sizeof(struct A));
return 0;
}

Predict the output of this program when compiled as C, then again
when compiled as C++. See if your predictions were accurate. :)

(For these reasons, I recommend using C++ compilers to compile C code
about as often as using Fortran or Ada compilers. :) )
You a wrong about minimum sizes returned from malloc. On all systems
that I have worked the minumum size returned is sizeof(double).

I have used systems that round to 2 or 4 bytes, even though
sizeof(double) was 8. These systems used conventional first-fit
or best-fit allocators.

In a system with "bibop" style allocators, in which malloc()s of
different sizes are allocated within different address ranges,
there is of course no requirement that malloc(1) return any more
than a single byte. On the other hand, malloc(9) does appear to
require 8-byte alignment on (e.g.) SPARC systems, where loads or
stores of doubles (whose "sizeof" is 8) must occur on 8-byte
boundaries. (I am not 100% sure of this; these kind of picky
details tend to require careful study of the standards.)
 
M

Matthew Fisher

The above line has a bug in that the buffer is one byte too short.
You are lucky however since malloc generally returns a minimum of 8
bytes. Contradicting some other posters, you should cast. You don't
need the second sizeof() since malloc takes a number of bytes and
sizeof returns bytes.

I goofed sizeof does indeed return 7 for the literal "foobar", it is
strlen that will return 6. Thanks to the followup poster for pointing
this out.

I stand by the rest :)

Matthew
Dynamic Memory Solutions
www.dynamic-memory.com
 
C

CBFalconer

Matthew said:
Wondering off topic a bit, why don't you think the cast is wise?
Sloppy type punning is always bad in my opinion. Also, a C++ compiler
will give any error.

That has been done to death in this very newsgroup. Also see the
cfaq. Basically casting is almost always bad, and hides errors
the compiler can otherwise detect.
You a wrong about minimum sizes returned from malloc. On all systems
that I have worked the minumum size returned is sizeof(double). This
appears to be required since malloc must return aligned memory. In
the example, if malloc were allowed to return a block of 7 bytes what
would it do with the 8th byte? I suppose it could hope for a call of
malloc(1) and assume that no alignment is needed. Do you know of any
such systems?

I am not clear on what the standard calls for. The minimum size may
just be an implementation detail nonetheless it exists.

The standard doesn't call for anything except universal
alignment. You have no idea what the actual code is doing with
the 'excess' storage. It may be keeping its own housekeeping data
in them. It may be using entirely different algorithms for small
and large allocations.

For example, an extremely simple allocator could be made by just
keeping the size and a link somewhere. That somewhere might be,
at least in part, after the allocation in the otherwise unused
bytes. The result would probably not be especially robust, but UB
is UB.
 
C

Chris Torek

printf("sizeof(struct A) = %lu\n", sizeof(struct A));

Oops, late-night-posting syndrome. This should read:

printf("sizeof(struct A) = %lu\n",
(unsigned long)sizeof(struct A));

Without the cast, the effect of the printf() call is undefined
(and can fail in "interesting" ways on some 64-bit systems).
 
C

CBFalconer

Chris said:
Oops, late-night-posting syndrome. This should read:

printf("sizeof(struct A) = %lu\n",
(unsigned long)sizeof(struct A));

Without the cast, the effect of the printf() call is undefined
(and can fail in "interesting" ways on some 64-bit systems).

IIRC the %z descriptor is available for that in C99.
 
G

Gordon Burditt

You a wrong about minimum sizes returned from malloc. On all systems
that I have worked the minumum size returned is sizeof(double). This

That doesn't make the statement that there is no guaranteed minimum
size wrong, even if you can prove that all existing systems do it
that way - someone can build one that doesn't.

As a real counterexample, the Tandy 6000 (68000 based) had 4 bytes
as its strictest alignment, and malloc() rounded the allocation up
to a multiple of 4. Part of the reason for that is that it had no
hardware floating point.
appears to be required since malloc must return aligned memory. In
the example, if malloc were allowed to return a block of 7 bytes what
would it do with the 8th byte? I suppose it could hope for a call of
malloc(1) and assume that no alignment is needed. Do you know of any
such systems?

Alignment doesn't account for everything, either. A lot of versions
(NO, you may NOT assume that all of them do) of malloc() use an
integer or pointer (typically 4 bytes) immediately before the block
the returned pointer points at to contain either the size of the
block or a pointer to the next block. A version of malloc() is
justified in this case in returning a pointer to a block of memory
of usable size of an *ODD* multiple of 4, aligned to a multiple of
8. The 4 bytes after that are arguable allocated by malloc(), but
they are NOT available for you to use.
I am not clear on what the standard calls for. The minimum size may
just be an implementation detail nonetheless it exists.

It exists on some implementations, not all. If you are arguing from
the requirements of alignment, the Intel *86 architecture does
not require alignment. While aligning things may improve speed, it
is not required.

Gordon L. Burditt
 
R

Randy Howard

IIRC the %z descriptor is available for that in C99.

It's the one thing from C99 that seems useful daily, but unavailable
on far too many compilers right now.
 

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

No members online now.

Forum statistics

Threads
474,146
Messages
2,570,832
Members
47,374
Latest member
anuragag27

Latest Threads

Top