Упаковка Данных или Выравнивание Памяти

แชร์
ฝัง
  • เผยแพร่เมื่อ 30 ต.ค. 2024

ความคิดเห็น • 55

  • @rollangrant8347
    @rollangrant8347 5 ปีที่แล้ว +5

    спасибо Володя!!! смотрел ролик как завороженный))

  • @AndersonSilva-dg4mg
    @AndersonSilva-dg4mg 5 ปีที่แล้ว +7

    Спасибо Володя

  • @cyxoqppykt4699
    @cyxoqppykt4699 3 ปีที่แล้ว

    Спасибо большое за видео. Готовлюсь к собеседованию, эта тема как раз является одной из ключевых, теперь чувствую себя уверенее!)

  • @zzerocks
    @zzerocks 5 ปีที่แล้ว +2

    Использую упаковку структур на микроконтроллерах, когда необходимо эти структуры пересылать, например, между устройствами. Здесь очень важным становится длина посылки. Для этих целей использую typedef struct { ... } __attribute((packed)) mystruct_t; - даже при использовании указателей информация об упаковке данных не теряетя.
    Также часто важна непрерывность данных, тогда можно например uint8_t* кастить к своей структуре.

  • @x3n0n3
    @x3n0n3 5 ปีที่แล้ว +1

    Отличный урок, премного благодарен.

  • @МаксимШишиморов
    @МаксимШишиморов 5 ปีที่แล้ว +13

    Что то не понятно как через не инициализированный указатель "tp" получается доступ к "t" ?

    • @АлмазНазипов-ы4ф
      @АлмазНазипов-ы4ф 2 ปีที่แล้ว

      "не знаешь язык - других в заблуждение не вводи", зачем Вам это, автор?

    • @МаксимШишиморов
      @МаксимШишиморов 2 ปีที่แล้ว

      @@АлмазНазипов-ы4ф вводить в заблуждение можно каким бы то ни было утверждением. Единственное утверждение выше это то что указатель не инициализирован (не задано никакое значение, а значит по стандарту это "Undefined Behaviour". Вероятней всего там какие то мусорные значения, не ноль не NULL, а что угодно). И вполне может быть адрес на соседнюю структуру в памяти. И вот я вижу что у автора это работает и не понимаю по какой причине, для этого и задавал вопрос. А вопрос это не утверждение и стало быть фраза "не знаешь язык - других в заблуждение не вводи" вообще не к месту. Если чего то не знаешь то наилучший способ разрешить это это задать вопрос. Если ты велик и могуч и ко всему прочему понимаешь почему указатель без инициализации можно использовать, то неплохо было бы объяснить именно для этого и был задан вопрос :D Что думаешь Алмаз ?

  • @dripfeeder666
    @dripfeeder666 5 ปีที่แล้ว +4

    Спасибо!

  • @ОлегДусь-ч6ь
    @ОлегДусь-ч6ь 4 ปีที่แล้ว

    Спасибо, просто, понятно и полезно

  • @olehvolynets9910
    @olehvolynets9910 4 ปีที่แล้ว

    Отличное видео, но как указал Максим Шишиморов проблема в том, что указатель не инициализиван и содержит мусор, что и вызывает Segmentation Fault, при верной инициализации все работает

  • @МаксимХвостов-м1й
    @МаксимХвостов-м1й 4 ปีที่แล้ว

    Ого, спасибо, очень наглядно.

  • @yunir844
    @yunir844 5 ปีที่แล้ว

    Спасибо, про упаковку было полезно узнать) В высокоуровневых языках(java, python) теряется связь с пониманием как это всё интерпретируется в машинный код (будто смотрим на черный ящик), что не прививает привычку стараться понимать как это всё работает..

  • @trismegistus9602
    @trismegistus9602 5 ปีที่แล้ว +5

    Все комменты по типу "Зачем? Мы в 2019!!! Ацтой". Объясняю один раз: то о чем говорится в видео должен знать человек, работающий с высоконагруженными системами, такими как написание ПО для спутника или программирование микроконтроллера где обьем памяти минимален. Для обычных программистов как вы это может быть бесполезно, но это не делает контент не актульным

    • @VladimirMozhenkov
      @VladimirMozhenkov  5 ปีที่แล้ว +1

      Ещё это немного позволяет вникнуть в суть того, как именно работает компилятор и (что тоже немало важно) сам процессор.

    • @yunir844
      @yunir844 5 ปีที่แล้ว

      Real Time OS

    • @АмэйзингЧенал
      @АмэйзингЧенал 2 ปีที่แล้ว

      у спутника миним обьем памяти ? дану нах уй , ты че несешь🤦

  • @nameundef8076
    @nameundef8076 4 ปีที่แล้ว

    Вот, если кому нужно - простенький js скрипт с функцией выравнивания байт и демонстрацией разницы между отсортированным и неотсортированными порядками байт:
    function GetAlignedStruct(structure)
    {
    var alignedStructure = [];
    var curAddr = 0;
    structure.forEach(element => {
    var remind = (curAddr += element) % element;
    if (remind)
    alignedStructure.push(element - remind);
    alignedStructure.push(element);
    });
    return alignedStructure;
    }
    var struct = [1, 4, 2, 1];
    console.log(GetAlignedStruct(struct));
    struct.sort((a, b) => b - a);
    console.log(GetAlignedStruct(struct));

  • @thelast1869
    @thelast1869 5 ปีที่แล้ว +2

    Очень приятный преподаватель

  • @yunir844
    @yunir844 5 ปีที่แล้ว

    Володя, откуда знаешь про процессоры arc? :)

  • @МанекенИбрагим
    @МанекенИбрагим 5 ปีที่แล้ว +2

    Есть хоть одна причина использовать int вместо int32_t?

    • @VladimirMozhenkov
      @VladimirMozhenkov  5 ปีที่แล้ว

      Не на всех платформах int32_t будет typedef для int. Так что это зависит от того, что вы хотите. Если вам важно получить 32 бита, используйте int32_t, а если вам важно только то, чтобы переменная была не меньше short и не больше long, и в будущих платформах может увеличиваться, то используйте int.

    • @VladimirMozhenkov
      @VladimirMozhenkov  5 ปีที่แล้ว

      Если у вас 16-битный процессор, то int32_t был-бы бесполезным.

    • @МанекенИбрагим
      @МанекенИбрагим 5 ปีที่แล้ว +1

      Я не могу представить сценария, когда программист использует переменную, и ему не важно какого она будет размера. int не является кроссплатформенным вариантом, т.к. неконтролируемое изменение свойств типа данных приводит к неизбежным багам и недочётам программы.

    • @keydon5661
      @keydon5661 5 ปีที่แล้ว

      Volodya Mozhenkov это может быть обертка над 2мя 16разрядными числами с целью переносимости для случаев когда она важнее производительности

  • @Rayvenor
    @Rayvenor 5 ปีที่แล้ว

    Не понятно зачем сейчас это всё нужно. При таких доступных объёмах ОЗУ, даже если ОС позволяет адресовать не более 2 ГБ, всё равно непрерывных данных будет гораздо больше, чем пропусков. Как пример, имеем два больших одинаковых по размеру массива. Описываем их как массив1 из int, затем что-то мелкое char, затем массив2 из int. Как будет это располагаться в памяти? Поправьте, но между массивами не будет дырки размером с массив2. Дырка будет размером с Int, что гораздо меньше всей структуры.
    Могу себе представить такую возню при программировании микроконтроллеров, но на ПК и даже на ARM это выглядит как экономия на спичках.

    • @iamstillanon3048
      @iamstillanon3048 5 ปีที่แล้ว

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

    • @Rayvenor
      @Rayvenor 5 ปีที่แล้ว +1

      @@iamstillanon3048 спасибо.

    • @keydon5661
      @keydon5661 5 ปีที่แล้ว +1

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

  • @Ivan-qb7kc
    @Ivan-qb7kc 5 ปีที่แล้ว +3

    Не верится, что сейчас, в 2019 все так ужасно. Программист вообще не должен думать о подобном. Неужели даже последние версии gcc не умеют автоматически упаковывать данные и заботиться о том, чтобы в коде ничего из-за этого не сломалось?

    • @VladimirMozhenkov
      @VladimirMozhenkov  5 ปีที่แล้ว +3

      Я в видео даже обсуждал почему компилятор не может просто поменять местами переменные за вас. Это связано с тем, как переменные конструируются. Кроме этого подумайте, что произойдёт, если у вас ваша структура внутри union, при изменении порядка переменных вы можете сломать то, зачем вы делали union.

    • @Ivan-qb7kc
      @Ivan-qb7kc 5 ปีที่แล้ว

      @@DabaevSS, программисты, для которых возня с компиляторами, архитектурами - их работа, а не для тех, кто хочет, чтобы его либа просто работала эффективнее. Это как решить проблему один раз, а не возиться с ней на каждом проекте каждому программисту

    • @Ivan-qb7kc
      @Ivan-qb7kc 5 ปีที่แล้ว

      @@VladimirMozhenkov, подобные способ обращения с памятью - совсем другой разговор. В таком случае, программист оборачивает против себя весь тот ужас, с которым приходится работать разработчикам компиляторов. Хорошо, когда подобная грань между хорошим (безопасным) обращением с памятью и плохим (небезопасным) проведена на уровне языка, как это сделано в Rust. Ну этим я, собственно, и ответил на свой вопрос - семантика языка не позволяет подобные вольности компилятору

    • @Ivan-qb7kc
      @Ivan-qb7kc 5 ปีที่แล้ว

      @Станислав Вешняков, возможно, что в таком случае операции прямого обращения к памяти, такие как *(int*)(ptr + 1), помечены как операции, вызывающие UB

    • @keydon5661
      @keydon5661 5 ปีที่แล้ว

      Rah 837 вот как раз программист либы и может этим заняться, потому что для него это частный случай, он знает какие переменные используются, в какую память выделяются и знает где можно для скорости упаковать, а где данные уедут в сеть на другую машину с другой архитектурой. Требовать того же от разработчиков компилятора странно, у них нет этой информации.

  • @serhii-dzhus
    @serhii-dzhus 5 ปีที่แล้ว

    Думаю все-таки сыграло роль то что вы не знаете С.
    Тут есть одна фатальная ошибка из-за которой приложение "падает", и это совсем не выравнивание памяти.
    struct Test* tp; // здесь вы не инициализировали переменную
    int* pp = &tp->i; // здесь вы обращаетесь к неинит. переменной, тут тоже может падать
    int* pp_correct __attribute__((aligned(1))) = &tp->i; // здесь этот аттрибут никак не поможет, компилятор и сам знает как нужно выравнивать
    printf("pp is %d
    ", *pp); // тут вы разименовываете указатель на память которую не выделили
    printf("pp_correct is %d
    ", *pp_correct); // тут тоже самое
    чтобы решить эту проблему нужно заменить строчку "struct Test* tp;" на:
    struct Test* tp = malloc(sizeof(struct Test));
    memset(tp, sizeof(struct Test), 0);

    • @astmix1337
      @astmix1337 5 ปีที่แล้ว

      Да ладно, указатель указывает на валидную память на стеке (struct Test t) так что утверждение о невыделенной памяти некорректно. Более того, в коде он даже ее инициализировал (t.i = 5), так что тут нет UB с точки зрения чтения неинициализированной памяти. Отсюда следует, что это как раз UB связанное с выравниванием

    • @serhii-dzhus
      @serhii-dzhus 5 ปีที่แล้ว +3

      @@astmix1337 посмотри ниже, сверху он создал struct Test t;
      Но ниже создал struct Test* tp;
      И не инициализировал ее и использовал и t и tp,
      t - на стеке
      tp - указатель, но не инициализирован
      Там где работа с "t" - все ок,
      Все плохо там где работа с "tp" именно изза того что память для нее не выделенная

    • @astmix1337
      @astmix1337 5 ปีที่แล้ว

      @@serhii-dzhus да, согласен) с первого раза не сразу заметил) так что извиняюсь), показалось, что там была строка tp = &t, но похожие названия других переменных сбили с толку)

  • @x3n0n3
    @x3n0n3 5 ปีที่แล้ว

    Что-то донэйт по вебмани не проходит: "Пользователь с таким идентификатором не найден.
    "

    • @VladimirMozhenkov
      @VladimirMozhenkov  5 ปีที่แล้ว

      Ааа, они там отменили кошельки с тамими номерами. Увы много видео уже отредактировано и я не буду только ради этого переделывать. Но всё в конечном счёте исправлю.

    • @x3n0n3
      @x3n0n3 5 ปีที่แล้ว

      @@VladimirMozhenkov, редактировать все видео не надо, просто обновите кошельки в описании к каналу.

  • @CraBiKun
    @CraBiKun 5 ปีที่แล้ว

    Кое-что-таки узнал.

  • @victorzedwings
    @victorzedwings 5 ปีที่แล้ว

    *последлнее видео было просто какаойто стёб над писателями книг.*
    *40 минут текста ни о чём. но строго научно.*
    посмотрим каким это будет.

  • @victorzedwings
    @victorzedwings 5 ปีที่แล้ว

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

    • @serhii-dzhus
      @serhii-dzhus 5 ปีที่แล้ว +1

      ну это всегда экономит память, но ваш процессор от этого совсем не в восторге)

    • @victorzedwings
      @victorzedwings 5 ปีที่แล้ว +1

      @@serhii-dzhus , очень даже в восторге. меньше циклов для загрузки в кэш.
      экономней расход памяти и кэша соответственно

    • @serhii-dzhus
      @serhii-dzhus 5 ปีที่แล้ว

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

    • @victorzedwings
      @victorzedwings 5 ปีที่แล้ว

      @@serhii-dzhus ,чем это он более медленный?
      Если куски по 14 байт, то да, возможно.
      А если вся структура умещается в 128 байт а память 2х канальная то наоборот быстрее.
      Сильно зависит от контроллера памяти.
      Например nVidia выполняет спекулятивную загрузку.
      Да и серверные контроллеры тоже знают как правильно читать...

    • @serhii-dzhus
      @serhii-dzhus 5 ปีที่แล้ว

      @@victorzedwings процессорам "удобнее" читать данные выровненные по 4 или 8 байт, а если они не выровненные то процессор делает дополнительные манипуляции чтобы считать данные по невыровненому адресу

  • @dendrit17
    @dendrit17 5 ปีที่แล้ว

    2019 год - а компиляторы дерьмо, языки программирования - дерьмо.