Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C Programming > Newbie question about malloc

Reply
Thread Tools

Newbie question about malloc

 
 
George
Guest
Posts: n/a
 
      12-17-2003
Hello to everybody !!!
Why am i getting always:
size=4 (i understand this)
length=3 (?????)
when i'm executing the following programm?
Should'nt i get always the number of bytes
allocated by "malloc" ??? (in this example 16)
Why is this happening?


#include <stdio.h>
#include <stdlib.h>
#include <string.h>

main()
{
char* name;
name=(char*)malloc(16);
if (!name)
{
printf("Mem Alloc Error.");
exit (0);
}
printf("size=%d \n",sizeof(name));
printf("length=%d",strlen(name));
free(name);
return 0;
}

Many thanks in advance,George
 
Reply With Quote
 
 
 
 
grobbeltje
Guest
Posts: n/a
 
      12-17-2003
George <(E-Mail Removed)> wrote:
> size=4 (i understand this)
> length=3 (?????)

as far as i can see, you never define what is inside 'name',
so it can contain whatever it wants. strlen searches for the
first '\0' and happens to find one at the 4th positions (lucky you!).

> main()
> {
> char* name;
> name=(char*)malloc(16);
> if (!name)
> {
> printf("Mem Alloc Error.");
> exit (0);
> }
> printf("size=%d \n",sizeof(name));
> printf("length=%d",strlen(name));
> free(name);
> return 0;
> }


you could try 'name=calloc(16,sizeof(char));' instead of the line
with malloc, it should make strlen return 0.

good luck!
grobbeltje.
--
If you must choose between two evils, pick the one you've never tried before.
 
Reply With Quote
 
 
 
 
Lew Pitcher
Guest
Posts: n/a
 
      12-17-2003
George wrote:

> Hello to everybody !!!
> Why am i getting always:
> size=4 (i understand this)
> length=3 (?????)
> when i'm executing the following programm?
> Should'nt i get always the number of bytes
> allocated by "malloc" ???


No. See below

> (in this example 16)
> Why is this happening?
>
>
> #include <stdio.h>
> #include <stdlib.h>
> #include <string.h>
>
> main()
> {
> char* name;
> name=(char*)malloc(16);
> if (!name)
> {
> printf("Mem Alloc Error.");
> exit (0);
> }
> printf("size=%d \n",sizeof(name));


sizeof is a C operator that results in a size_t value indicating the size of
the selected data item or type. You got 4 here because the C compiler you
are using implements character pointers as 4-byte quantities.

> printf("length=%d",strlen(name));


strlen() is a C standard function that counts characters. It starts counting
at the address pointed to by it's argument, and stops when it encounters the
first '\0' character. The resulting value may have no correspondance to the
size of the memory block allocated by your malloc() call.

Your use here of strlen() has two flaws:
1) You haven't initialized the block of memory pointed to by name, thus the
memory contains unknown data. It is a programming error to attempt to
call strlen() against an uninitialized data area.

2) the returned value from strlen() does not represent the length of
allocated memory. Instead, it represents the length of the string
pointed to by it's argument. AFAIK, there is /no/ standard function that
will accept a pointer to a malloc()ed array, and return the length of the
malloc().


> free(name);
> return 0;
> }
>
> Many thanks in advance,George



--
Lew Pitcher, IT Consultant, Application Architecture
Enterprise Technology Solutions, TD Bank Financial Group

(Opinions expressed here are my own, not my employer's)

 
Reply With Quote
 
Mark A. Odell
Guest
Posts: n/a
 
      12-17-2003
http://www.velocityreviews.com/forums/(E-Mail Removed) (George) wrote in
news:(E-Mail Removed) om:

> Hello to everybody !!!
> Why am i getting always:
> size=4 (i understand this)
> length=3 (?????)
> when i'm executing the following programm?
> Should'nt i get always the number of bytes
> allocated by "malloc" ??? (in this example 16)
> Why is this happening?
>
>
> #include <stdio.h>
> #include <stdlib.h>
> #include <string.h>
>
> main()


int main(void)

> {
> char* name;
> name=(char*)malloc(16);


name = malloc(16); /* no cast in C, only C++ */

> if (!name)
> {
> printf("Mem Alloc Error.");
> exit (0);

return EXIT_FAILURE; /* why bother with exit */
> }


> printf("size=%d \n",sizeof(name));

printf("size of pointer 'name'=%u\n", (unsinged int) sizeof name);

> printf("length=%d",strlen(name));


printf("length of initialized string is bogus=%u\n",
(unsigned int) strlen(name));

> free(name);
> return 0;
> }
>
> Many thanks in advance,George
>


Now try again.

#define NEEDED_SIZE 1024

int main(void)
{
int failure = EXIT_FAILURE;
char *pName = malloc(NEEDED_SIZE);

if (pName)
{
/* Initialize to something
*/
strcpy(pName, "Hello world");

printf("Size of memblock at pName is %d\n", NEEDED_SIZE);
printf("Len of string in memblock is %u\n",
(unsigned int) strlen(name));

free(pName);
failure = EXIT_SUCCESS;
}

return failure;
}

--
- Mark ->
--
 
Reply With Quote
 
Artie Gold
Guest
Posts: n/a
 
      12-17-2003
George wrote:
> Hello to everybody !!!
> Why am i getting always:
> size=4 (i understand this)
> length=3 (?????)


See below.

> when i'm executing the following programm?
> Should'nt i get always the number of bytes
> allocated by "malloc" ??? (in this example 16)


No. That's just not how it works. There is no portable way to know how
many bytes were allocated given a pointer to memory.

> Why is this happening?
>
>
> #include <stdio.h>
> #include <stdlib.h>
> #include <string.h>
> main()

int main(void)

> {
> char* name;
> name=(char*)malloc(16);


Lose the cast. It's unnecessary.

> if (!name)
> {
> printf("Mem Alloc Error.");
> exit (0);


You probably want:

exit EXIT_FAILURE;

It failed, didn't it?


> }
> printf("size=%d \n",sizeof(name));


The sizeof() operator returns the size of the object, which, in this
case is an object of type `pointer to char'. On your system that size is
evidently 4.

> printf("length=%d",strlen(name));


When you use malloc() to allocate memory, the contents of that memory is
indeterminate -- so looking at it produces undefined behavior. It just
so happens that in this particular case, the fourth `char' was 0 (or
'\0'). Since you invoked undefined behavior, the result could have been
*anything*, even things much too horrible to mention at this hour of the
morning.

> free(name);
> return 0;
> }
>
> Many thanks in advance,George


Fair enough.

HTH,
--ag

--
Artie Gold -- Austin, Texas
Oh, for the good old days of regular old SPAM.

 
Reply With Quote
 
Christopher Benson-Manica
Guest
Posts: n/a
 
      12-17-2003
Lew Pitcher <(E-Mail Removed)> spoke thus:

> You got 4 here because the C compiler you
> are using implements character pointers as 4-byte quantities.


Just FMI, is this a choice of the compiler or the implementation?

> The resulting value may have no correspondance to the
> size of the memory block allocated by your malloc() call.


No "may" about it - the values are independent, yes?

--
Christopher Benson-Manica | I *should* know what I'm talking about - if I
ataru(at)cyberspace.org | don't, I need to know. Flames welcome.
 
Reply With Quote
 
Lew Pitcher
Guest
Posts: n/a
 
      12-17-2003
Christopher Benson-Manica wrote:

> Lew Pitcher <(E-Mail Removed)> spoke thus:
>
>
>>You got 4 here because the C compiler you
>>are using implements character pointers as 4-byte quantities.

>
>
> Just FMI, is this a choice of the compiler or the implementation?
>
>
>>The resulting value may have no correspondance to the
>>size of the memory block allocated by your malloc() call.

>
>
> No "may" about it - the values are independent, yes?


Yes, mostly.

I thought of a caveat that I didn't want to write for fear of confusing the
issue, and not phrasing it correctly enough for the pedants in the group.

The caveat is that a programmer could write

strcpy(name,pointer_to_initialization_string);

(given proper definition and values for name and
pointer_to_initialization_string) and initialize the memory block.

Given that this results in /correct/ initialization, then strlen() would
result in a value less than the size of the allocated memory block.

However, assuming that this results in an /incorrect/ initialization (if,
for instance, pointer_to_initialization_string points to a string that is
larger than the target block of memory), then the results of strlen() will
be somewhat indeterminate (I'll let the language lawyers here decide whether
it would be an error condition, or "implementation defined" or "undefined").
/If/ strlen() returns a value in this case, it /may/ have some
correspondance to the size of the memory block allocated by the malloc() call.

And that's what I didn't want to expound on. <grin>




--
Lew Pitcher, IT Consultant, Application Architecture
Enterprise Technology Solutions, TD Bank Financial Group

(Opinions expressed here are my own, not my employer's)

 
Reply With Quote
 
Lew Pitcher
Guest
Posts: n/a
 
      12-17-2003
Christopher Benson-Manica wrote:

> Lew Pitcher <(E-Mail Removed)> spoke thus:
>
>
>>You got 4 here because the C compiler you
>>are using implements character pointers as 4-byte quantities.

>
>
> Just FMI, is this a choice of the compiler or the implementation?


Good question. I fear that I don't have a definitive answer for it though.

I would expect that the compiler has some restrictions wrt the target
platform, including restrictions on the size of pointers. Pointer sizes
/can/ vary at the hardware, either by type of data pointed to, or as a
result of execution environment limitations. The compiler may have to make
a choice as to /which/ pointer size to allocate a pointer to. If there's no
choice for the compiler to make, I'd expect that the pointer size is
dictated by the implementation.

--
Lew Pitcher, IT Consultant, Application Architecture
Enterprise Technology Solutions, TD Bank Financial Group

(Opinions expressed here are my own, not my employer's)

 
Reply With Quote
 
Kevin Goodsell
Guest
Posts: n/a
 
      12-17-2003
George wrote:

> Hello to everybody !!!
> Why am i getting always:
> size=4 (i understand this)
> length=3 (?????)
> when i'm executing the following programm?
> Should'nt i get always the number of bytes
> allocated by "malloc" ??? (in this example 16)
> Why is this happening?


Here's a few more details about things that were glossed over in some of
the replies.

>
>
> #include <stdio.h>
> #include <stdlib.h>
> #include <string.h>
>
> main()


int main(void)

"Implicit int" no longer exists in C. Under the latest standard you must
specify the return type for all functions. In the case of main(), the
return type must be 'int' (contrary to popular belief, 'void' has never
been an acceptable return type for main() in any version of C).

As for the voided parameter list, you should never use empty parameter
lists in C unless you really know what you are doing. In C (unlike C++)
an empty parameter list is very different from a void parameter list,
and empty parameter lists can be very dangerous.

> {
> char* name;
> name=(char*)malloc(16);


It's generally recommended to NOT cast the return from malloc(). At
least one very notable book on C incorrectly states that the cast is
required, but it is not.

The main reasons to not cast are: 1) It can suppress a useful
diagnostic, thus hiding an error in the code (the error in question is a
failure to provide a correct declaration for malloc() - the result of
forgetting to #include <stdlib.h>). 2) The cast is an extra maintenance
concern. If the type of 'name' were to change (say, to unsigned char, or
wchar_t), you'd need to locate and fix every cast expression involving
'name'.

The comp.lang.c-approved method of calling malloc() looks like this:

name = malloc(16 * sizeof(*name) );

(Alternatively, remove the parens on the sizeof operator - they aren't
necessary in this case.)

This form automatically adjusts to changes in the type of 'name', and is
generally more difficult to get wrong than other forms.

> if (!name)
> {
> printf("Mem Alloc Error.");


No one else mentioned this (that I saw), but a portable program needs to
terminate its output with a newline:

printf("Mem Alloc Error.\n");

It's not uncommon for the last line of output to mysteriously disappear,
or to appear with the system prompt tagged onto the end if it is not
correctly terminated.

Also, error output should usually go to the standard error stream:

fprintf(stderr, "Mem Alloc Error.\n");

> exit (0);
> }
> printf("size=%d \n",sizeof(name));
> printf("length=%d",strlen(name));


Both of these printfs are wrong. As before, you should end your lines
with a newline character, but more importantly you have used the wrong
format specifiers. This can be a very serious problem, and most
compilers won't warn you about it.

Both sizeof and strlen give a result of type size_t. size_t is an
unsigned type. The %d format specifier is for (signed) int ONLY. It's
possible that size_t could be an alias for unsigned int, but not signed
int. Therefore, %d can never be the correct format specifier for a size_t.

Keep in mind that printf is stupid. It cannot determine the actual types
of the objects you pass it. It relies completely on you telling it the
correct type. If you lie to it about the type, all bets are off. Stack
corruption leading to a program crash or worse is very likely. Even if
it "seems to work", bad things may be happening that aren't easily
observed - mysterious, very difficult to find bugs can pop up. The
behavior can appear random, and may be completely different on a
different system, or when using a different compiler.

In other words, it's very important to get your format strings right.
Always double-check them.

In this case, there probably isn't a format string you can use for
size_t. C99 introduced %zu for this purpose, but you probably aren't
using a C99 compiler. The safest way to print a size_t is to cast it to
a known type first:

printf("length=%lu\n", (unsigned long)strlen(name));

This is guaranteed safe in C versions prior to C99, since size_t can be
no wider than unsigned long. As of C99, size_t can be wider (it can even
be wider than the new 'long long' type, I think), so this is not
completely safe under C99 (it is safe in the sense that it cannot lead
to undefined behavior, but the results may be inaccurate).

-Kevin
--
My email address is valid, but changes periodically.
To contact me please use the address from a recent posting.
 
Reply With Quote
 
Chris Torek
Guest
Posts: n/a
 
      12-17-2003
In article <news:(E-Mail Removed). com>
George <(E-Mail Removed)> writes:
>Should'nt i get always the number of bytes
>allocated by "malloc" ??? (in this example 16)


In addition to the other responses so far, I might point out that
while the *call* says:

malloc(16)

there is no guarantee that you actually *got* 16 bytes, even if
the returned pointer is NULL. Suppose, for instance, that for some
reason your implementation has chosen never to hand out less than
some minimum number of bytes at a time via malloc(). The malloc()
on that system might include code like:

if (size < MIN_MALLOC_SIZE)
size = MIN_MALLOC_SIZE;

near the top, with MIN_MALLOC_SIZE greater than 16. Thus, you
might have gotten 20, 24, 32, or even more bytes. (Real malloc()s
often do contain this kind of code, so this is not a purely
theoretical issue.)

C has no "how much did I malloc() with this non-NULL pointer that
is suitable for use as an argument to free()" function. Such a
function might be useful, but if one were to be proposed for addition
to a future C standard (or any other "non-C" standard that acts as
a sort of add-on, such as the POSIX system-function bindings like
readdir() and such), we would have to decide: "Does this function
return the argument passed to malloc(), or does it return the actual
number of bytes malloc() handed out even if that was a larger
number?"

Also, this:

> char* name;

...
> printf("size=%d \n",sizeof(name));


printed 4. (Note that strlen() returns a size_t value, which is not
an int value; anything might have been printed, but for luck. Whether
this is "good luck" or "bad luck" depends on one's point of view...)
In a later followup he asked:

>... is this a choice of the compiler or the implementation?


The only correct answer to this is "yes", because it might be either
one. (I assume here "implementation" really means "hardware
for which the C compiler compiles machine-level code.") Computer
hardware often suggests (with varying degrees of strength) particular
implementations for C code, but C compilers are not required to
produce "sensible" code, merely "code that obeys the requirements
of the C standard". As such, a compiler for a machine with 32-bit
pointers could generate 16-bit-pointer code (that can only address
65536 bytes at a time) and "run" that code via an interpreter that
simulates some other machine that only has 16-bit pointers.

(This, too, is not purely theoretical -- it is how emulators work.
One might either use a cross-compiler that runs native and produces
code for the emulated hardware, or even run under the emulator an
old "native" C compiler that works on the emulated machine. In
the latter case one might reasonably claim that the "machine" really
does have 16-bit pointers; the cross-compiler case is more
interesting, particularly if it is the cross-compiler that emits
the emulator, and can optionally run some code "native" intermixed
with other code "emulated".)
--
In-Real-Life: Chris Torek, Wind River Systems
Salt Lake City, UT, USA (4039.22'N, 11150.29'W) +1 801 277 2603
email: forget about it http://web.torek.net/torek/index.html
Reading email is like searching for food in the garbage, thanks to spammers.
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
to malloc or not to malloc?? Johs32 C Programming 4 03-30-2006 10:03 AM
porting non-malloc code to malloc micromysore@gmail.com C Programming 3 02-19-2005 05:39 AM
Malloc/Free - freeing memory allocated by malloc Peter C Programming 34 10-22-2004 10:23 AM
free'ing malloc'd structure with malloc'd members John C Programming 13 08-02-2004 11:45 AM
Re: free'ing malloc'd structure with malloc'd members ravi C Programming 0 07-30-2004 12:42 PM



Advertisments