فهرست منبع

Fix segfault, due to not initializing the pointer when reserving extra capacity

ticki 9 سال پیش
والد
کامیت
6799cb9b37
1فایلهای تغییر یافته به همراه32 افزوده شده و 2 حذف شده
  1. 32 2
      src/bookkeeper.rs

+ 32 - 2
src/bookkeeper.rs

@@ -1,4 +1,4 @@
-//! The memory bookkeeping module.
+//! Memory bookkeeping primitives.
 //!
 //! Blocks are the main unit for the memory bookkeeping. A block is a simple construct with a
 //! `Unique` pointer and a size. Occupied (non-free) blocks are represented by a zero-sized block.
@@ -138,6 +138,32 @@ impl BlockList {
         }
     }
 
+    /// Initialize the block list.
+    ///
+    /// This will do some basic initial allocation, and a bunch of other things as well. It is
+    /// necessary to avoid meta-circular dependency.
+    // TODO can this be done in a more elegant way?
+    fn init(&mut self) {
+        /// The initial capacity.
+        const INITIAL_CAPACITY: usize = 16;
+
+        let reserve = INITIAL_CAPACITY * size_of::<Block>();
+        let brk = unsafe {
+            sys::inc_brk(reserve + align_of::<Block>()).unwrap_or_else(|x| x.handle())
+        };
+        let aligner = aligner(*brk as *const _, align_of::<Block>());
+
+        self.cap = reserve;
+        self.ptr = unsafe {
+            Unique::new((*brk as usize + aligner) as *mut _)
+        };
+
+        self.push(Block {
+            size: aligner,
+            ptr: brk,
+        });
+    }
+
     /// *[See `Bookkeeper`'s respective method.](./struct.Bookkeeper.html#method.alloc)*
     ///
     /// # Example
@@ -435,6 +461,10 @@ impl BlockList {
             self.check();
         }
         */
+
+        // Initialize if necessary.
+        if *self.ptr == EMPTY_HEAP as *mut _ { self.init() }
+
         if needed > self.cap {
             let block = Block {
                 ptr: unsafe { Unique::new(*self.ptr as *mut _) },
@@ -636,7 +666,7 @@ impl BlockList {
     /// This will check for the following conditions:
     ///
     /// 1. The list is sorted.
-    /// 2. No entries are not overlapping.
+    /// 2. No entries are overlapping.
     /// 3. The length does not exceed the capacity.
     #[cfg(debug_assertions)]
     fn check(&self) {