about summary refs log tree commit diff
path: root/src/libstd/rt
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2014-01-19 04:31:53 -0800
committerbors <bors@rust-lang.org>2014-01-19 04:31:53 -0800
commit52f1d905b0c7a0f99f4e2a7c330acc86b9700cb0 (patch)
tree331d42fcdd57363310a543e1ebad20b1e0554189 /src/libstd/rt
parent53733c87b64855ac8f15ea3886e6a8ed6097545a (diff)
parentae2a5ecbf600495a80ae4d99853a2ed2c8f6b5e9 (diff)
downloadrust-52f1d905b0c7a0f99f4e2a7c330acc86b9700cb0.tar.gz
rust-52f1d905b0c7a0f99f4e2a7c330acc86b9700cb0.zip
auto merge of #11635 : thestinger/rust/zero-size-alloc, r=alexcrichton
The `malloc` family of functions may return a null pointer for a
zero-size allocation, which should not be interpreted as an
out-of-memory error.

If the implementation does not return a null pointer, then handling
this will result in memory savings for zero-size types.

This also switches some code to `malloc_raw` in order to maintain a
centralized point for handling out-of-memory in `rt::global_heap`.

Closes #11634
Diffstat (limited to 'src/libstd/rt')
-rw-r--r--src/libstd/rt/global_heap.rs37
1 files changed, 25 insertions, 12 deletions
diff --git a/src/libstd/rt/global_heap.rs b/src/libstd/rt/global_heap.rs
index ce4072fb1ab..00195f726cb 100644
--- a/src/libstd/rt/global_heap.rs
+++ b/src/libstd/rt/global_heap.rs
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 use libc::{c_void, c_char, size_t, uintptr_t, free, malloc, realloc};
-use ptr::RawPtr;
+use ptr::{RawPtr, mut_null};
 use unstable::intrinsics::{TyDesc, abort};
 use unstable::raw;
 use mem::size_of;
@@ -31,24 +31,37 @@ fn align_to(size: uint, align: uint) -> uint {
 
 /// A wrapper around libc::malloc, aborting on out-of-memory
 #[inline]
-pub unsafe fn malloc_raw(size: uint) -> *c_void {
-    let p = malloc(size as size_t);
-    if p.is_null() {
-        // we need a non-allocating way to print an error here
-        abort();
+pub unsafe fn malloc_raw(size: uint) -> *mut c_void {
+    // `malloc(0)` may allocate, but it may also return a null pointer
+    // http://pubs.opengroup.org/onlinepubs/9699919799/functions/malloc.html
+    if size == 0 {
+        mut_null()
+    } else {
+        let p = malloc(size as size_t);
+        if p.is_null() {
+            // we need a non-allocating way to print an error here
+            abort();
+        }
+        p
     }
-    p
 }
 
 /// A wrapper around libc::realloc, aborting on out-of-memory
 #[inline]
 pub unsafe fn realloc_raw(ptr: *mut c_void, size: uint) -> *mut c_void {
-    let p = realloc(ptr, size as size_t);
-    if p.is_null() {
-        // we need a non-allocating way to print an error here
-        abort();
+    // `realloc(ptr, 0)` may allocate, but it may also return a null pointer
+    // http://pubs.opengroup.org/onlinepubs/9699919799/functions/realloc.html
+    if size == 0 {
+        free(ptr as *c_void);
+        mut_null()
+    } else {
+        let p = realloc(ptr, size as size_t);
+        if p.is_null() {
+            // we need a non-allocating way to print an error here
+            abort();
+        }
+        p
     }
-    p
 }
 
 /// The allocator for unique pointers without contained managed pointers.