diff options
| author | bors <bors@rust-lang.org> | 2014-01-19 04:31:53 -0800 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2014-01-19 04:31:53 -0800 |
| commit | 52f1d905b0c7a0f99f4e2a7c330acc86b9700cb0 (patch) | |
| tree | 331d42fcdd57363310a543e1ebad20b1e0554189 /src/libstd/rt | |
| parent | 53733c87b64855ac8f15ea3886e6a8ed6097545a (diff) | |
| parent | ae2a5ecbf600495a80ae4d99853a2ed2c8f6b5e9 (diff) | |
| download | rust-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.rs | 37 |
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. |
