Huge memory allocation

S

sam_cit

Hi Everyone,

I'm in a need to allocate huge memory block of size 50kb.
How can i use malloc() for this purpose, asuming sizeof(int) is two
bytes?

Thanks in advance!!!
 
R

Richard Tobin

I'm in a need to allocate huge memory block of size 50kb.

(I'm assuming kb means kbytes rather than kbits. kB is a better
abbreviation.)
How can i use malloc() for this purpose, asuming sizeof(int) is two
bytes?

sizeof(int) doesn't come into it. If you want 50kbytes, do

char *m = malloc(50*1024);

(assuming you mean the same thing by "bytes" as the compiler does,
which is almost certainly true).

But be sure you really mean what you say: why do you want 50kbytes?

-- Richard
 
E

Eric Sosman

Hi Everyone,

I'm in a need to allocate huge memory block of size 50kb.
How can i use malloc() for this purpose, asuming sizeof(int) is two
bytes?

sizeof(int) doesn't enter the picture.

#include <stdlib.h>
...
p = malloc(50000); /* or 51200, or whatever */
if (p != NULL) {
/* use it */
}

The reason that sizeof(int) is irrelevant is twofold. First,
the argument to malloc() is a size_t, not an int. Second, the
type of a numeric literal depends somewhat on its value: if it
is sufficiently small it will be an int, if it's too large for
an int it will be an unsigned int, or a long, or an unsigned
long, or perhaps something bigger still. The 50000 (or 51200)
might not be of type int, but will have the numerical value
fifty thousand (or so) no matter what type the compiler chooses.
Then that type will be converted to size_t in the malloc() call.
 
J

jacob navia

(e-mail address removed) a écrit :
Hi Everyone,

I'm in a need to allocate huge memory block of size 50kb.
How can i use malloc() for this purpose, asuming sizeof(int) is two
bytes?

Thanks in advance!!!

To get 50 K you do:


#include <stdlib.h>

....
char *result;

result = calloc(50,1024);


If you want to allocate NOT 50K but 50 000 *integers* you do

result = calloc(50000,sizeof(int));
 
C

Chris Dollin

I'm in a need to allocate huge memory block of size 50kb.

50Kbytes is "huge"?

I'm having a flashback to 1982.
How can i use malloc() for this purpose, asuming sizeof(int) is two
bytes?

Don't use an int to express the size you want to `malloc`.
 
E

Eric Sosman

Richard said:
(I'm assuming kb means kbytes rather than kbits. kB is a better
abbreviation.)


sizeof(int) doesn't come into it. If you want 50kbytes, do

char *m = malloc(50*1024);

Woops! In this formulation, sizeof(int) -- or, rather,
"rangeof(int)" -- *does* come into play. If INT_MAX is a
mere 32767 (it is allowed to be that small), the multiplication
written here produces undefined behavior.

On two's complement machines with silent overflow, the most
common variety these days, 50*1024 overflows to -14336, which is
then converted to size_t. For a 16-bit size_t, the converted result
will be 51200, as intended, but for a 32-bit size_t the request
is for 4294952960 bytes. malloc() may well fail to allocate nearly
four gig in circumstances where fifty K would be no problem -- but
at least, if it *does* succeed, the O.P. can be sure of having
enough memory for his purposes ...

(Please note that the calculations in the preceding paragraph
are *not* guaranteed by the C language itself, but based on the
particular characteristics of some C implementations. As far as
C is concerned, `50 * 1024' itself is the end of the story; after
that point, the Standard says nothing about what might happen.)
 
R

Richard Tobin

char *m = malloc(50*1024);
[/QUOTE]
Woops! In this formulation, sizeof(int) -- or, rather,
"rangeof(int)" -- *does* come into play.

Oops! I edited it from 50000 to 50*1024 at the last moment, without
considering the consequences.

-- Richard
 
J

jacob navia

Richard Tobin a écrit :
Woops! In this formulation, sizeof(int) -- or, rather,
"rangeof(int)" -- *does* come into play.


Oops! I edited it from 50000 to 50*1024 at the last moment, without
considering the consequences.

-- Richard[/QUOTE]
That's why I recommended
calloc(50,1024) in my other post

That should (if calloc has no bugs) do the trick
regardless of the sizeof(int)
 
M

Michael Brennan

Woops! In this formulation, sizeof(int) -- or, rather,
"rangeof(int)" -- *does* come into play.

Oops! I edited it from 50000 to 50*1024 at the last moment, without
considering the consequences.

-- Richard[/QUOTE]

So multiplying two integer constants will cause UB if their
product exceeds INT_MAX? What is the limit when writing the
product directly as 50000? Is it SIZE_MAX in this case since
it is passed as an argument to malloc()?

/Michael Brennan
 
E

Eric Sosman

Michael Brennan wrote On 05/09/07 12:05,:
So multiplying two integer constants will cause UB if their
product exceeds INT_MAX?

Yes: The behavior on overflow is undefined.
What is the limit when writing the
product directly as 50000? Is it SIZE_MAX in this case since
it is passed as an argument to malloc()?

Effectively, yes, but it's worth while to understand
the details. There are two things to think about: The
type of the integer constant, and the conversion to size_t.

The type of a decimal constant with no suffix is the
first of int, long, or long long that can express its value.
For even larger values the implementation can either give a
diagnostic or choose a still wider implementation-defined
type. The upshot is that you'll get either the value you
intended or you'll get an error message; you will not get a
value that is unexpectedly negative or unexpectedly reduced
modulo something-or-other. In the case at hand, 50000 will
be either `int' or `long'; there will be no need for anything
wider.

But then comes the step of passing the value to malloc().
The compiler knows (because <stdlib.h> was included) that
malloc() expects to receive a `size_t' argument, so it
converts the `int' or `long' to `size_t'. The conversion is
well-defined (by the rules of unsigned arithmetic), but is
not necessarily value-preserving: If the value is out of
range for `size_t' it is reduced modulo SIZE_MAX+1. That's
not going to be an issue in this case because SIZE_MAX is
at least 65535, so 50000 is in range and will not need
adjustment.
 
F

Flash Gordon

jacob navia wrote, On 09/05/07 16:10:
Richard Tobin a écrit :
That's why I recommended
calloc(50,1024) in my other post

That should (if calloc has no bugs) do the trick
regardless of the sizeof(int)

However, it potentially waists time setting all the bytes to 0. This can
happen even if the OS can provide pre-zeroed memory because it might be
allocated from memory previously used by the program and not returned to
the OS which will therefore be "dirty".

Personally what I would do depends on the situation. Normally I find
that when using malloc it is not a constant value, and if one of the
variables (or constants) used in the calculation is of size_t you will
get the correct result *if* the result fits in to a size_t. If not then
in my experience you should actually be limiting things rather earlier
in the process.
 
J

Jack Klein

sizeof(int) doesn't enter the picture.

#include <stdlib.h>
...
p = malloc(50000); /* or 51200, or whatever */
if (p != NULL) {
/* use it */
}

The reason that sizeof(int) is irrelevant is twofold. First,
the argument to malloc() is a size_t, not an int. Second, the
type of a numeric literal depends somewhat on its value: if it
is sufficiently small it will be an int, if it's too large for
an int it will be an unsigned int, or a long, or an unsigned
long, or perhaps something bigger still.

A unsuffixed decimal integer constant will never be treated as an
unsigned type, no matter what its value. Prior to C99, the result is
undefined if a decimal integer constant has a value larger than
LONG_MAX. Under C99, it the value of the constant is greater than
LLONG_MAX, it may be converted to an extended integer type if and only
if the implementation has a signed extended integer type large enough
to hold its value.

C99 6.4.4.1 P5.
The 50000 (or 51200)
might not be of type int, but will have the numerical value
fifty thousand (or so) no matter what type the compiler chooses.
Then that type will be converted to size_t in the malloc() call.

--
Jack Klein
Home: http://JK-Technology.Com
FAQs for
comp.lang.c http://c-faq.com/
comp.lang.c++ http://www.parashift.com/c++-faq-lite/
alt.comp.lang.learn.c-c++
http://www.club.cc.cmu.edu/~ajo/docs/FAQ-acllc.html
 
P

Peter Nilsson

Jack Klein said:
A unsuffixed decimal integer constant will never be treated
as an unsigned type, no matter what its value. Prior to C99,
the result is undefined if a decimal integer constant has a
value larger than LONG_MAX.

My C89 draft says...

"The type of an integer constant is the first of the
corresponding list in which its value can be represented.
Unsuffixed decimal: int, long int, unsigned long int..."

Indications are that this wasn't changed in C89 itself. [N629]

I also note that gcc still has a warning:

"this decimal constant is unsigned only in ISO C90"
 
K

Keith Thompson

Jack Klein said:
A unsuffixed decimal integer constant will never be treated as an
unsigned type, no matter what its value. Prior to C99, the result is
undefined if a decimal integer constant has a value larger than
LONG_MAX. Under C99, it the value of the constant is greater than
LLONG_MAX, it may be converted to an extended integer type if and only
if the implementation has a signed extended integer type large enough
to hold its value.

C99 6.4.4.1 P5.

The original question was how to allocate 50 kilobytes if int is only
16 bits (so INT_MAX==32767).

If you use a single integer constant such as 50000 or 51200, it's
guaranteed to be of some type able to hold its value, and, assuming
the prototype is visible, it will be implicitly converted to size_t in
malloc(51200).

But the significance of the number 51200 isn't entirely obvious at a
glance, so it's clearer to use an explicit multiplication:

malloc(50 * 1024)

But both of these constants are of type int, and if INT_MAX==32767 the
overflow will cause undefined behavior.

jacob suggested using calloc(), but that's wasteful if you don't need
zero-initialization. It avoids overflow only because calloc() just
happens to take two operands. In another example that jacob
presented, if you want to allocate 50*1024 ints rather than bytes, you
have *three* numbers to multiply, and the calloc() trick falls down.

In real life, you're not likely to be using a simple magic number for
this kind of thing. But if that's really what you need to do, this is
a rare case where a cast may be the right solution:

malloc((size_t)50 * 1024)

Note that it's important to cast only one operand; this:

malloc((size_t)(50 * 1024))

has the same problem as the version without the cast. If you prefer
symmetry:

malloc((size_t)50 * (size_t)1024)

The problem is that, though you can use a "U" suffix for unsigned, or
"UL" for unsigned long, there's no suffix for size_t.
 
I

Ian Collins

Keith said:
The original question was how to allocate 50 kilobytes if int is only
16 bits (so INT_MAX==32767).

If you use a single integer constant such as 50000 or 51200, it's
guaranteed to be of some type able to hold its value, and, assuming
the prototype is visible, it will be implicitly converted to size_t in
malloc(51200).

But the significance of the number 51200 isn't entirely obvious at a
glance, so it's clearer to use an explicit multiplication:

malloc(50 * 1024)

But both of these constants are of type int, and if INT_MAX==32767 the
overflow will cause undefined behavior.
How about malloc(50U * 1024U)?
 
K

Keith Thompson

Ian Collins said:
How about malloc(50U * 1024U)?

Sure, that will work in this particular case, since 51200 happens to
be representable as an unsigned int on any conforming implementation.
But if you change the 50 to 100, it breaks (if UINT_MAX==65535).
 
E

Eric Sosman

CBFalconer said:
Nobody has pointed out that C89 through C95 only guarantee
declaration of objects of less than 32768 bytes. I think C99 ups
that to 65535.

True[*], but the question isn't about declaring a large
object: It's about making a large (YMMV) malloc() request. The
request can be made, and may succeed or fail. There is no
guarantee that malloc(50000) will succeed, under any Cxx rules.
But then, there is no guarantee that malloc(1) will succeed, or
even malloc(0). That's why I showed a NULL test after the call.

[*] Almost. Given "less than," the value should be 65536.
 
E

Eric Sosman

Jack said:
[...]
type of a numeric literal depends somewhat on its value: if it
is sufficiently small it will be an int, if it's too large for
an int it will be an unsigned int, or a long, or an unsigned
long, or perhaps something bigger still.

A unsuffixed decimal integer constant will never be treated as an
unsigned type, no matter what its value. Prior to C99, the result is
undefined if a decimal integer constant has a value larger than
LONG_MAX. Under C99, it the value of the constant is greater than
LLONG_MAX, it may be converted to an extended integer type if and only
if the implementation has a signed extended integer type large enough
to hold its value.

C99 6.4.4.1 P5.

We're both wrong, but I'm wronger than you are. Nyaah!

Under C99 rules, an unsuffixed decimal constant never has
an unsigned type.

Under ANSI rules, an unsuffixed decimal constant greater
than LONG_MAX could have an unsigned type, and need not yield
undefined behavior. ANSI 3.1.3.2:

The type of an integer constant is the first of the
corresponding list in which its value can be represented.
Unsuffixed decimal: int, long int, unsigned long int; [...]

The reason I have bragging rights to being wronger than you
is that under *no* set of rules could an unsuffixed decimal
constant have `unsigned int' type. `unsigned long', yes, but
never `unsigned int', and I was wrong to say so.
 
K

Keith Thompson

Eric Sosman said:
Under C99 rules, an unsuffixed decimal constant never has
an unsigned type.

Under ANSI rules, an unsuffixed decimal constant greater
than LONG_MAX could have an unsigned type, and need not yield
undefined behavior. ANSI 3.1.3.2:
[snip]

Keep in mind that C99 is an ANSI standard (it was adopted by ANSI
after it was issued by ISO). To avoid ambiguity, it's best to refer
to C89 or C90 rather than "ANSI C".
 
A

Army1987

Hi Everyone,

I'm in a need to allocate huge memory block of size 50kb.
How can i use malloc() for this purpose, asuming sizeof(int) is two
bytes?

malloc(51200L);
"long" is required to hold numbers up to 2**31-1.
 

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

Forum statistics

Threads
473,768
Messages
2,569,574
Members
45,049
Latest member
Allen00Reed

Latest Threads

Top