Skip to content

Instantly share code, notes, and snippets.

@pzread pzread/
Last active Jun 6, 2017

What would you like to do?
use std::collections::HashMap;
use std::mem;
struct Link {
pub value: String,
next: *const Link,
impl Link {
fn new(value: String, next: *const Self) -> Self {
Self { value, next }
struct Table {
inner: HashMap<i32, Box<Link>>,
head: *const Link,
/// Implemented a Table which can insert and search by key. And show all elements in reversed order of insertion.
/// The reason why it uses a single linked list to maintain and record the insertion order is because in my real case,
/// it also needs to support element removing operation.
/// The design of linked list is trying to keep the elements pointed by `next` pointers alive as long as the Table itself.
/// So the ownerships of all elements are held by internal `HashMap` and are dropped only(?) when the Table itself is dropped.
impl Table {
fn new() -> Self {
Self { inner: HashMap::new(), head: std::ptr::null() }
fn insert(&mut self, key: i32, value: &str) {
if !self.inner.contains_key(&key) {
let link = Box::new(Link::new(value.to_owned(), self.head));
self.head = &*link;
self.inner.insert(key, link);
fn get_mut(&mut self, key: i32) -> &mut Box<Link> {
fn show(&self) {
let mut current = self.head;
while !current.is_null() {
unsafe {
let reference = current.as_ref().unwrap();
println!("{}", reference.value);
current =;
fn main() {
let mut t = Table::new();
// No suprise.
t.insert(1, "Hello");
t.insert(10, "Word");
t.insert(20, "!");
t.get_mut(10).value = "World".to_string();;
// The bug is triggered by following code.
let mut mutref = t.get_mut(10);
let otherlink = Link::new("New World".to_string(), std::ptr::null());
let oldlink = mem::replace(mutref, Box::new(otherlink));
println!("{}", t.get_mut(10).value);
let dirtything = Box::new(vec![1u8; mem::size_of::<Link>()]);;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.