gpt4 book ai didi

memory-leaks - Rc 依赖循环的最小示例是什么?

转载 作者:行者123 更新时间:2023-11-29 08:01:06 25 4
gpt4 key购买 nike

我正在尝试编写一个会泄漏内存的 Rust 程序 due to cycles with reference counts .下面的示例看起来应该会导致内存泄漏,但根据 Valgrind 的说法,它并没有泄漏内存。给了什么?

测试.rs:

use std::cell::RefCell;
use std::rc::Rc;

struct Foo {
f: Rc<Bar>,
}

struct Bar {
b: RefCell<Option<Rc<Foo>>>,
}

fn main() {
let bar = Rc::new(Bar {
b: RefCell::new(None),
});
let foo = Rc::new(Foo { f: bar.clone() });
*bar.b.borrow_mut() = Some(foo.clone());
}

Valgrind 输出:

$ rustc --version
rustc 1.4.0 (8ab8581f6 2015-10-27)
$ rustc -o test test.rs
$ valgrind test
==23331== Memcheck, a memory error detector
==23331== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==23331== Using Valgrind-3.10.1 and LibVEX; rerun with -h for copyright info
==23331== Command: test
==23331==
==23331==
==23331== HEAP SUMMARY:
==23331== in use at exit: 0 bytes in 0 blocks
==23331== total heap usage: 37 allocs, 37 frees, 9,078 bytes allocated
==23331==
==23331== All heap blocks were freed -- no leaks are possible
==23331==
==23331== For counts of detected and suppressed errors, rerun with: -v
==23331== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)

最佳答案

对于您使用的 Rust 版本,很可能您使用的是 jemalloc,它与 Valgrind 的配合并不总是很好(有关更多信息,请参阅链接的问题)。对于现代版本的 Rust,默认使用系统分配器,您发布的代码确实报告内存泄漏:

$ valgrind --leak-check=full ./test
==761== Memcheck, a memory error detector
==761== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==761== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
==761== Command: ./test
==761==
==761==
==761== HEAP SUMMARY:
==761== in use at exit: 56 bytes in 2 blocks
==761== total heap usage: 13 allocs, 11 frees, 2,233 bytes allocated
==761==
==761== 56 (32 direct, 24 indirect) bytes in 1 blocks are definitely lost in loss record 2 of 2
==761== at 0x4C2FB0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==761== by 0x10BDAB: alloc::alloc::alloc (in /tmp/test)
==761== by 0x10BD17: alloc::alloc::exchange_malloc (in /tmp/test)
==761== by 0x10C3F6: <alloc::rc::Rc<T>>::new (in /tmp/test)
==761== by 0x10BF6F: test::main (in /tmp/test)
==761== by 0x10DAF2: std::rt::lang_start::{{closure}} (in /tmp/test)
==761== by 0x115CC2: {{closure}} (rt.rs:49)
==761== by 0x115CC2: std::panicking::try::do_call (panicking.rs:297)
==761== by 0x117BA9: __rust_maybe_catch_panic (lib.rs:87)
==761== by 0x11677C: try<i32,closure> (panicking.rs:276)
==761== by 0x11677C: catch_unwind<closure,i32> (panic.rs:388)
==761== by 0x11677C: std::rt::lang_start_internal (rt.rs:48)
==761== by 0x10DAD4: std::rt::lang_start (in /tmp/test)
==761== by 0x10C19A: main (in /tmp/test)
==761==
==761== LEAK SUMMARY:
==761== definitely lost: 32 bytes in 1 blocks
==761== indirectly lost: 24 bytes in 1 blocks
==761== possibly lost: 0 bytes in 0 blocks
==761== still reachable: 0 bytes in 0 blocks
==761== suppressed: 0 bytes in 0 blocks
==761==
==761== For counts of detected and suppressed errors, rerun with: -v
==761== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)

我在 Ubuntu 上使用 Valgrind 3.13.0 和 Rust 1.34.1,但我认为这不会改变结果。

您还可以向结构中添加虚拟值,以便更轻松地在输出中找到它们。我用了 Box<[u8; 10240]>非常突出。

至于最小,我会建模一个链表:

use std::cell::RefCell;
use std::rc::Rc;

struct Node {
next: RefCell<Option<Rc<Node>>>,
}

fn main() {
let foo1 = Rc::new(Node {
next: RefCell::new(None),
});
let foo2 = Rc::new(Node {
next: RefCell::new(Some(foo1.clone())),
});
*foo1.next.borrow_mut() = Some(foo2.clone());
}

该程序还报告泄漏。

另见:

关于memory-leaks - Rc 依赖循环的最小示例是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34469585/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com