22

7.22.3.4 The malloc function The malloc function allocates space for an object whose size is specified by size and whose value is indeterminate.

Prototype: void *malloc(size_t size);

I tried passing a negative value as a parameter: malloc(negative) returns NULL.

Is it because the [size_t] negative converted to unsigned [some big value] and cannot allot required space or is the function checking parameter and returns NULL?

If its getting converted to big positive, then when calling malloc(INT_MIN+2) it still returns NULL, but malloc(0) alloted to pointer and *p = somevalue works. What about this?

Is it implementation defined?

Read this link:malloc(0)

Community
  • 1
  • 1
Dineshkumar
  • 4,165
  • 5
  • 29
  • 43

2 Answers2

29

A size_t value is always positive even if you pass a negative value to malloc. The negative value is converted to an unsigned value of type size_t which leads to a huge positive value.

Example:

char *p = malloc(-2);

is equivalent to:

char *p = malloc(SIZE_MAX - 1);  // SIZE_MAX is the maximum
                                 // size_t value 
ouah
  • 142,963
  • 15
  • 272
  • 331
  • how size determined? even if i've possible memory size? lets say 8 gb ram? [or memory limited to programs] – Dineshkumar Jul 29 '13 at 13:49
  • @Dineshkumar how the size is converted to unsigned integer is implementation-dependent, IIRC. However most architectures use two's complement nowadays and corresponding conversion. Make a test by writing a function with the same argument type as malloc and print it inside. On Linux, with memory overcommit enabled, malloc basically never fails, no matter what you pass to it (maybe only when the address space is exhausted). However, attempts to write to more (virtual) memory than is available will result in SIGSEGV. I'm not sure about Windows, but it's likely similar. – spbnick Jul 29 '13 at 13:54
  • @spbnick this is actually not implementation-defined and ruled by *(c99, 6.3.1.3p2) "Otherwise, if the new type is unsigned, the value is converted by repeatedly adding or subtracting one more than the maximum value that can be represented in the new type until the value is in the range of the new type"* – ouah Jul 29 '13 at 13:57
  • when i pass malloc(INT_MIN+offset) it should result in a small positive value right, still it results in NULL? – Dineshkumar Jul 29 '13 at 14:12
  • @ouah Thanks, I should really spend time on reading the standard. However, isn't this basically the same as masking out the higher bits? And wouldn't this basically mean simply interpreting signed representation as unsigned, and that representation is implementation-defined? – spbnick Jul 29 '13 at 14:14
  • @Dineshkumar if `offset` is a small positive value, then `INT_MIN + offset` is still a negative value. – ouah Jul 29 '13 at 14:15
  • In fact, it is literally impossible to pass a negative value to `malloc()`. Any negative argument value is implicitly converted to `size_t`, which is an unsigned type and therefore cannot represent negative values. – Keith Thompson Jul 29 '13 at 14:39
  • 2
    @Dineshkumar: Let's assume both `int` and `size_t` are 32 bits. If `INT_MIN == -2147483648` and `offset == 100`, then `INT_MIN + offset == -2147483548`, which when converted to a 32-bit `size_t` yields `+2147483748`. – Keith Thompson Jul 29 '13 at 14:43
  • @spbnick on two's complement system, yes it is basically truncating higher bits. But the way this integer conversion is defined in the standard (in 6.3.1.3p2) is deliberately independent of the signed representation. – ouah Jul 29 '13 at 14:45
  • @ouah Thank you. Yes, 6.3.1.3p2 is independent, but isn't what exactly happens, i.e. what value we get in the end still implementation-defined? I.e. depends on how signed integers are stored? – spbnick Jul 29 '13 at 15:09
  • @spbnick `(size_t) -2` is `SIZE_MAX - 1` whatever the signed representation is. – ouah Jul 29 '13 at 15:16
  • @ouah Thanks, I'll meditate on this and will read the spec :) – spbnick Jul 29 '13 at 17:17
8

Since the argument to malloc is of type size_t which is unsigned but you are passing an integer which is signed, the integer value will be converted to size_t the rules for this are covered in the draft C99 standard section 6.3.1.3 Signed and unsigned integers which comes under Conversions and it says:

Otherwise, if the new type is unsigned, the value is converted by repeatedly adding or subtracting one more than the maximum value that can be represented in the new type until the value is in the range of the new type.49)

Let's look at an example of what this means, if you pass in -1 then max size_t value + 1 will be added:

-1 + MAX_SIZE_T + 1

which results in:

 MAX_SIZE_T

For -5 you would end up with:

MAX_SIZE_T - 4

This means for small negative values the resulting size_t value will be a very large positive number.

So why do you receive NULL back for malloc in these cases? If we go back to the the draft standard section 7.20.3 Memory management functions it says:

If the space cannot be allocated, a null pointer is returned

You are making a request that is too large and the space can not be allocated.

Shafik Yaghmour
  • 154,301
  • 39
  • 440
  • 740