Приложение поршня падает через несколько минут с ошибкой выделения памяти - PullRequest
0 голосов
/ 02 января 2019

Я разработал игру-лабиринт с использованием Piston в Rust, чтобы научить себя программированию графики / пользовательского интерфейса.Игра в основном работает нормально, но когда я запускаю ее с большим лабиринтом (например, 120 x 72 прямоугольника), игра вылетает с ошибкой выделения памяти через пару минут.

Ниже приведен сокращенный пример:

extern crate graphics;
extern crate opengl_graphics;
extern crate piston;
extern crate piston_window;

use opengl_graphics::OpenGL;
use piston::event_loop::*;
use piston::input::*;
use piston_window::{PistonWindow, WindowSettings};

const BLACK: [f32; 4] = [0.0, 0.0, 0.0, 1.0];
const WHITE: [f32; 4] = [1.0, 1.0, 1.0, 1.0];

fn main() {
    let opengl = OpenGL::V3_2;

    let mut window: PistonWindow = WindowSettings::new("maze", [800, 600])
        .opengl(opengl)
        .exit_on_esc(true)
        .build()
        .unwrap();

    let mut events = Events::new(EventSettings::new());

    while let Some(event) = events.next(&mut window) {
        if let Some(_args) = event.render_args() {
            window.draw_2d(&event, |c, gl| {
                graphics::clear(BLACK, gl);

                for _row in 0..72 {
                    for _col in 0..120 {
                        let color = WHITE;
                        let box_rect =
                            graphics::rectangle::rectangle_by_corners(0.0, 0.0, 10.0, 10.0);
                        graphics::rectangle(color, box_rect, c.transform, gl);
                    }
                }
            });
        }
    }
}

Когда я запускаю это, я получаю ошибку выделения памяти, за которой следует прерывание процесса:

$ time cargo run --release
   Compiling maze v0.1.0 (/home/isaac/prog/rust/test-maze)
    Finished release [optimized] target(s) in 5.28s
     Running `target/release/maze`
memory allocation of 7927496704 bytes failedAborted (core dumped)

real    2m24.317s
user    1m29.515s
sys     0m3.644s

Запустив его в отладчике, я получаю следующую обратную трассировку:

(gdb) backtrace
#0  __GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:51
#1  0x00007ffff71e1801 in __GI_abort () at abort.c:79
#2  0x0000555555708fc7 in std::sys::unix::abort_internal () at src/libstd/sys/unix/mod.rs:157
#3  0x000055555570419d in rust_oom () at src/libstd/alloc.rs:211
#4  0x0000555555717f37 in alloc::alloc::handle_alloc_error () at src/liballoc/alloc.rs:224
#5  0x00005555556eaf7d in <alloc::vec::Vec<T> as alloc::vec::SpecExtend<T, I>>::spec_extend ()
#6  0x00005555556e64aa in <gfx_core::handle::Manager<R>>::extend ()
#7  0x00005555556da204 in <gfx_device_gl::Device as gfx_core::Device>::pin_submitted_resources ()
#8  0x000055555559d654 in <gfx::encoder::Encoder<R, C>>::flush ()
#9  0x000055555558f8af in maze::main ()
#10 0x000055555558bb73 in std::rt::lang_start::{{closure}} ()
#11 0x0000555555704913 in std::rt::lang_start_internal::{{closure}} () at src/libstd/rt.rs:49
#12 std::panicking::try::do_call () at src/libstd/panicking.rs:297
#13 0x000055555570927a in __rust_maybe_catch_panic () at src/libpanic_unwind/lib.rs:92
#14 0x0000555555705466 in std::panicking::try () at src/libstd/panicking.rs:276
#15 std::panic::catch_unwind () at src/libstd/panic.rs:388
#16 std::rt::lang_start_internal () at src/libstd/rt.rs:48
#17 0x000055555558fae2 in main ()

Я использую Ubuntu Linux 18.04.

Должна ли моя программа быть написана иначе, чтобы предотвратить эту проблему?Что-то не так с поршнем?

Ответы [ 2 ]

0 голосов
/ 02 января 2019

Проблема находится здесь:

let mut events = Events::new(EventSettings::new());

while let Some(event) = events.next(&mut window) {

Вместо этого следует использовать это:

while let Some(event) = window.next() {

Оказывается, window.next() выполняет некоторые этапы очистки, которые events.next(&mut window) пропускает, и эти этапы очистки освобождают соответствующую память. Насколько я могу судить, документация не упоминает об этом, и в примерах используются оба шаблона без указания различий.

Эта очистка упоминается в комментариях здесь , на что указал Тириозавр на reddit .

0 голосов
/ 02 января 2019

Это примерно 8 ГБ распределения;слишком большой, чтобы быть разумным.8 ГБ, вероятно, связано с вашей системной RAM.Половина, равная или двойная, в зависимости от настроек вашей системы.

Проблема должна быть в цикле, и она должна быть небольшой.Цикл не очень большой, не так ли?Что приятно в небольших примерах.Похоже, это был код события.Я понятия не имею, почему.

Вот версия, которая не имеет утечки памяти:

extern crate graphics;
extern crate opengl_graphics;
extern crate piston;
extern crate piston_window;

use opengl_graphics::OpenGL;
use piston::event_loop::*;
use piston::input::*;
use piston_window::{PistonWindow, WindowSettings};

const BLACK: [f32; 4] = [0.0, 0.0, 0.0, 1.0];
const WHITE: [f32; 4] = [1.0, 1.0, 1.0, 1.0];

fn main() {
    let opengl = OpenGL::V3_2;

    let mut window: PistonWindow = WindowSettings::new("maze", [800, 600])
        .opengl(opengl)
        .exit_on_esc(true)
        .build()
        .unwrap();

    while let Some(event) = window.next() {
        window.draw_2d(&event, |c, gl| {
            graphics::clear(BLACK, gl);

            for _row in 0..72 {
                for _col in 0..120 {
                    let color = WHITE;
                    let box_rect =
                        graphics::rectangle::rectangle_by_corners(0.0, 0.0, 10.0, 10.0);
                    graphics::rectangle(color, box_rect, c.transform, gl);
                }
            }
        });
    }
}
...