Задать вопрос
  • При добавление элементов в вектор, при превышении capacity, это приведет к перераспределению Vec?

    fenrir1121
    @fenrir1121
    Начни с документации
    При превышении capacity адрес может измениться.
    Довольно банальная оптимизация - если впереди необходимая память свободна, расширение происходит на месте, без переноса.

    Проверить можно так
    fn main() {
        let mut vec = Vec::with_capacity(2);
        let initial_ptr = vec.as_ptr();
    
        let (new_ptr, new_capacity) = std::iter::repeat(())
            .enumerate()
            .find_map(|(i, _)| {
                vec.push(i as i32 + 3);
                (vec.as_ptr() != initial_ptr).then(|| (vec.as_ptr(), vec.capacity()))
            })
            .unwrap();
        println!("Initial ptr: {:?}", initial_ptr);
        println!("New ptr: {:?}", new_ptr);
        println!("New capacity: {}", new_capacity);
    }
    Ответ написан
    Комментировать
  • Покажите на ассемблере как выглядит защита от переполнения буфера?

    Ternick
    @Ternick
    Есть такая штука Stack Canary. Она отвечает за защиту от переполнения буфера, вполне возможно, что это не единственный механизм, но один из основных, которые отвечают за это.

    Есть аргументы компилятора, которые убирают защиту от переполнения и соответственно добавив их можно посмотреть и сравнить бинарники с защитой и без.

    В принципе вопрос особо ничего не стоит и гуглиться по первым ссылкам буквально, но допустим.

    От себя порекомендую видео S0ER на эту тему
    Ответ написан
    1 комментарий
  • Кракозябры, когда запускаю 4BSD в эмуляторе SIMH в консоли?

    VoidVolker
    @VoidVolker Куратор тега Windows
    Dark side eye. А у нас печеньки! А у вас?
    Ловите инструкцию:
    670d4c201254a086434124.png
    Ответ написан
    Комментировать
  • Какой тип данных у переменной a?

    bingo347
    @bingo347
    Crazy on performance...
    У переменной a указан тип встроенный массив [T; n]. Но у такого типа нет метода get_unchecked_mut(). Он есть у среза на массив [T]
    Тут нужно понять как в Rust работает оператор точка.

    Во-первых, мало кто пишет, но операторов точка на самом деле в Rust целых 2:
    - Доступ к полю структуры/кортежа/юниона
    - Вызов метода
    Rust различает их по наличию круглых скобок:
    struct S {
        a: i32,
        f: fn(),
    }
    
    impl S {
        fn a(&self) {}
    }
    
    let s = S { a: 0, f: || {} };
    s.a; // Доступ к полю
    s.a(); // Вызов метода
    (s.f)(); // Вызов функции по указателю, который лежит в поле f

    С доступом к полю все просто, компилятор преобразует его в смещение в памяти где это поле лежит относительно самой структуры.
    А вот с вызовом метода все интереснее, Rust пытается рассахарить его в одну из следующих конструкций в следующем порядке:
    S::a(s);
    S::a(&s);
    S::a(&mut s);
    <S as Deref>::Target::a(S::deref(&s));
    <S as DerefMut>::Target::a(S::deref_mut(&mut s));
    <<S as Deref>::Target as Deref>::Target::a(<S as Deref>::Target::deref(S::deref(&s)));
    <<S as DerefMut>::Target as DerefMut>::Target::a(<S as DerefMut>::Target::deref_mut(S::deref_mut(&mut s)));
    // ...
    и так пока либо не найдет вариант, который компилируется, либо пока не обнаружит что для очередного типа не реализован трейт Deref.
    Подробнее можно почитать тут: https://doc.rust-lang.org/stable/nomicon/dot-opera...

    У всех массивов есть Deref к слайсу, в core библиотеке прописано что-то вроде:
    impl<T, const N: usize> Deref for [T; N] {
        type Target = [T];
        fn deref(&self) -> &[T] {
            // ...
        }
    }
    За счет этого все массивы (а так же векторы, у которых тоже Deref к слайсу) получают методы слайса. И по тому же принципу String получает методы str.

    Ну и кстати, неявный вызов deref может еще происходить при взятии ссылки.

    Ну и из комментов к вопросу:
    Что тут делает unsafe код как раз понятно
    Однозначно понятно, он здесь делает UB так как обращается к памяти владелец которой неизвестен.
    Ответ написан
    1 комментарий
  • Хватит ли мне блока питания?

    @hiddenSt
    Т.е меняете видеокарту 108 Вт на видеокарту 120 Вт и сомневаетесь, что не потянет? Блок питания 450 Вт загружен наполовину. Потянет конечно.
    Ответ написан
    Комментировать
  • В unix все действия в gui интерфейсе фактически вызывают какую-то команду консоли?

    saboteur_kiev
    @saboteur_kiev Куратор тега Linux
    software engineer
    В линуксе, гуишные программы могут в принципе использовать exec консольных команд вместо "API", поскольку удобных консольных команд, которые работают достаточно стабильно из версии в версию, по сравнению с Win много.

    Но обычно все-таки используют просто вызов системных функций напрямую - так и быстрее и надежнее.
    Ответ написан
    Комментировать
  • В unix все действия в gui интерфейсе фактически вызывают какую-то команду консоли?

    jamakasi666
    @jamakasi666 Куратор тега Linux
    Просто IT'шник.
    Вы немного перепутали понятия. mel в майке это самый настоящий интерпретируемый ЯП, аналогично lua\js\python и еще тьмы языков.
    Касательно линуксов то и тут все просто. Сама программа может иметь разные "слои", если утрировать:
    1) сама программа может быть на любом языке, возьмем к примеру ifconfig.
    2) вокруг программы могут быть скриптовые обвертки на других языках или таких же. К примеру скрипт /etc/sysconfig/network-scripts/ifcfg-Auto_eth1 который грубо говоря запускает ifconfig с заданными параметрами.
    3) оболочка также может быть написана на чем угодно и ,к примеру, может тупо генерировать /etc/sysconfig/network-scripts/ifcfg-Auto_eth1 или напрямую запускать ifconfig с нужными параметрами. Но никто не запрещает реализовать аналогичный функционал как в ifconfig и быть полностью самостоятельной.

    Выше сказанное просто пример причем несовсем корректный и написан просто для примера как это может быть.

    В windows программах ситуация полностью аналогичная только там с\вместо прослойки со скриптами может использоваться реестр\конфиги\wmi и т.д.
    Поэтому дать однозначный ответ да\нет дать нельзя, все зависит от функционала программы и то как его реализовали.
    Ответ написан
    4 комментария
  • Когда вызывается malloc() или new, то на самом деле вызывается какая-то win api функция?

    @abcd0x00
    Первый раз вызывается какая-то функция операционной системы (в зависимости от системы, есть же не только Windows) и запрашивается очень большой блок (даже если запрашиваешь мало). Потом из него выделяется то, что ты запросил, и в нём же запоминается информация об этом (метаданные). При последующих вызовах этот первый блок продолжает нарезаться, пока в нём хватает памяти (может на всё время хватить). Во время освобождения памяти этот блок остаётся занятым, просто в нём какие-то места помечаются свободными для повторного использования.
    Ответ написан
    Комментировать
  • Когда вызывается malloc() или new, то на самом деле вызывается какая-то win api функция?

    Nipheris
    @Nipheris Куратор тега C++
    Когда вызывается malloc() или new, то на самом деле вызывается какая-то win api функция?

    Нет, не всегда. В большинстве случаев не вызывается. Системный вызов осуществляется только если текущий блок, управляемый сишной кучей (т.е. сишным рантаймом) исчерпывается. Если б каждый раз делался системный вызов, вы б не дождались результатов работы вашей программы.

    И при удалении тоже?

    См. выше.

    И вот интересно, а как сделать маленькую кучу, чтобы память выделялась в пределах этой маленькой кучи только?

    Выделяете блок памяти любым из известных вам способов, декларируете функции а-ля myalloc и myfree, и реализуете один из алгоритмов управления свободным пространством в куче (например, двоичного разбиения).

    В C++ можно переопределить операторы new и delete.
    Ответ написан
    8 комментариев