Russian Qt Forum
Май 04, 2024, 16:46 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: 1 [2] 3 4 ... 6   Вниз
  Печать  
Автор Тема: Плюсолюбителям  (Прочитано 40055 раз)
Bepec
Гость
« Ответ #15 : Март 09, 2015, 16:12 »

AzazelloAV - в вашем примере ошибся программист, а не программа.
И вопрос об уязвимости человеческого фактора, а не функции.

PS какую то уязвимость придумали. Походу нормального диалога с вами не получается Веселый

PPS С++ тем и известен, что в нём можно делать всё, в том числе и стрелять себе в ногу.
Записан
AzazelloAV
Гость
« Ответ #16 : Март 09, 2015, 16:32 »

AzazelloAV - в вашем примере ошибся программист, а не программа.
И вопрос об уязвимости человеческого фактора, а не функции.

PS какую то уязвимость придумали. Походу нормального диалога с вами не получается Веселый

PPS С++ тем и известен, что в нём можно делать всё, в том числе и стрелять себе в ногу.

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

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

Если при вызове такой функции, где мы задали не правильный размер, происходит крах, почему его не проверяют, если размер известен. Почему не сделать проверку за выход "диапазона". Тут любой код смотришь, и такое впечатление, что 50% производительности съедается одними глупыми проверками, а тут "зажали" пару тактов. Что не так? Почему так?

Про уязвимость не понял. Как это я её придумал? Зохавать соседние данные путем такой передачи - это классика.
Записан
Old
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4349



Просмотр профиля
« Ответ #17 : Март 09, 2015, 16:39 »

Я всего лишь говорю, что везде классика предлагает: "нужно передавать размер, потому как его никто не знает".
Именно, этот размер никто не знает.
Операторы new[] и delete[] получают размер необходимого буфера в байтах, а не количество элементов. Даже сохранив этот размер он не поможет определить число элементов.
Записан
AzazelloAV
Гость
« Ответ #18 : Март 09, 2015, 17:01 »

Я всего лишь говорю, что везде классика предлагает: "нужно передавать размер, потому как его никто не знает".
Именно, этот размер никто не знает.
Операторы new[] и delete[] получают размер необходимого буфера в байтах, а не количество элементов. Даже сохранив этот размер он не поможет определить число элементов.

Количество элементов. Ну куда, ну куда.....
Во первых, вы опять про строки.
Во вторых, нету функций, которые не "знают" размер элемента.
У вас будут функции
getAnsi
getUTF16
getUTF32
Все они прекрасно знают размер элемента (читать размер буфера).
Как может функция не знать данные, с которыми она работает.

Единственное разумное объяснение, которое я здесь получил, что это может быть "беспрерывный" набор данных, и нам нужно с некоторой точки (смещения) записывать туда данные. Это специфичная задача на самом деле (соотношение тех и тех функций). Например - соединение по сети, где мы получаем данные скопом, а потом их расшифровываем.

Но тут опять несостыковка - мы же передаем размер максимально проглатываемых данных (которые обработаем), а не максимальный размер буфера. Или что мы передаём? Что мы передаем в таком случае?

Есть разные подходы. Вот в Qt, в силу исторических причин (которые они называют бинарной совместимостью) два класса. Один рабочий (выполняет все действия), второй обёртка (торчит внаружу). Обертка проверяет всякие пакости, в рабочем классе небезопастный код, который вызывается напрямую. Code less, create more это хорошо, но ведь не все идеальны, так что и там проверки есть. Где то похожий код в винде (ну если очень с высока смотреть) - безопасные функции.

Я тогда сформулирую свой вопрос очень конкретно, без всяких стрельб в ноги - почему функции хотя бы не проверяют выход за рамер буфера?
« Последнее редактирование: Март 09, 2015, 17:20 от AzazelloAV » Записан
Old
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4349



Просмотр профиля
« Ответ #19 : Март 09, 2015, 17:07 »

Нет. Я как раз не про строки, а про объекты классов.
Функция func( SuperClass *ptr ) никак не может узнать количество элементов в массиве, она даже не может определить ptr указатель на одиночный объект или массив объектов.
« Последнее редактирование: Март 09, 2015, 17:12 от Old » Записан
sergek
Гипер активный житель
*****
Offline Offline

Сообщений: 870


Мы должны приносить пользу людям.


Просмотр профиля
« Ответ #20 : Март 09, 2015, 17:14 »

То, что delete может хранится по разному для разных компиляторах ничего не значит. Также может разными компиляторами реализовывать VMT. Но т.к. это происходит в одном "пространстве компилятора", это не важно, он же знает где хранится.
Коллега, вы не слышите. Речь о выделении памяти и ее высвобождении- если использовали new[], то нужно использовать delete[]. Это медицинский факт.
А если хотите стрелять себе в ногу (да хоть в голову), то пожалуйста - язык позволяет, защиты от дурака в нем нет. За это его и ругают и хвалят.
Записан

Qt 5.13.0 Qt Creator 5.0.1
Win10, Ubuntu 20.04
AzazelloAV
Гость
« Ответ #21 : Март 09, 2015, 17:22 »

То, что delete может хранится по разному для разных компиляторах ничего не значит. Также может разными компиляторами реализовывать VMT. Но т.к. это происходит в одном "пространстве компилятора", это не важно, он же знает где хранится.
Коллега, вы не слышите. Речь о выделении памяти и ее высвобождении- если использовали new[], то нужно использовать delete[]. Это медицинский факт.
А если хотите стрелять себе в ногу (да хоть в голову), то пожалуйста - язык позволяет, защиты от дурака в нем нет. За это его и ругают и хвалят.

Извеняюсь, продублирую
Я тогда сформулирую свой вопрос очень конкретно, без всяких стрельб в ноги - почему функции хотя бы не проверяют выход за рамер буфера?
Записан
Old
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4349



Просмотр профиля
« Ответ #22 : Март 09, 2015, 17:26 »

Проверяют, если этого хочет разработчик, и передача этого размера в качестве парамеира, как раз позволяет это сделать.
Записан
Alex Custov
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2063


Просмотр профиля
« Ответ #23 : Март 09, 2015, 17:27 »

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

Смотря какого буфера и смотря какие функции. Например?
Записан
AzazelloAV
Гость
« Ответ #24 : Март 09, 2015, 17:31 »

Нет. Я как раз не про строки, а про объекты классов.
Функция func( SuperClass *ptr ) никак не может узнать количество элементов в массиве, она даже не может определить ptr указатель на одиночный объект или массив объектов.

Данная функция бессмыслена, т.к. она не может определить размер ptr и что с ним делать. Либо ей плевать на элементы что там (ну допустим нужно обрезать 8 бит, аля по старой почте отправлять будем), либо ей нужно знать, с чем работать, отсюда и размер. Хотя, ваш пример перечеркивает всё подряд, мы говорили про поток данных, вы же уже объект засовываете, что теряет смысл - это же указатели, размер которых определен в ОС. Вы хотите туда передать размер (кол-во) объектов. Я же спрашиваю зачем, если размер массива можно вычислить (как делает delete) да ещё умножить на 4 (для 32-х разрядной системы). Тут люд говорит - не важно, может у нас массив больше, да и не с той позиции хотим. Чтож, согласен. Возможен и такой вариант. Но пока не сказал (тот же люд), почему нет проверки на выход за пределы буфера и передаваемым размером.
Записан
PinkPanther
Самовар
**
Offline Offline

Сообщений: 169



Просмотр профиля
« Ответ #25 : Март 09, 2015, 17:36 »

Цитировать
Операторы new[] и delete[] получают размер необходимого буфера в байтах, а не количество элементов. Даже сохранив этот размер он не поможет определить число элементов.

Мне кажется, что delete тоже не знает размер, а точнее, delete просто не нужно знать размер. Делаю это утверждение по памяти, могу ошибаться.

Если брать PC, в защищенном режиме указатель хранит не адрес в памяти, а номер дескриптора (4 байта) в специальной таблице, которую использует процессор для адресации физической памяти. По нему освобождается сегмент данных (фактически, "черный ящик"). Физический адрес процессор сам берет из таблицы, поэтому на уровне C/C++ выход за границы массива никак не отслеживается, так как после выделения памяти для массивов простых типов при помощи new информация о количестве элементов не сохраняется. Зато процессор отслеживает границы, и, если начнете писать за пределы сегмента, программа прекратит работу по системному прерыванию.

Увеличение адреса указателя определяет другой адрес - смещение от физического адреса сегмента (который хранит таблица). Когда вызывается delete, процессор находит нужный дескриптор по номеру и вычищает из таблицы. Данные о размере куска и правах доступа к нему содержатся в таблице, и к ним, как я понимаю, на уровне кода C/C++ никто не обращается (к тому же, процессоров много и все работают по-разному, попытка это делать сделает код непереносимым на другие платформы).

Кстати, прибавляя к адресу, вы получите адреса следующих элементов. Но попробуйте отнять. Вы не получите физический адрес. Вы выскочите за пределы выделенной памяти с обратной стороны, в пустую область или в область другого блока, процессор это заметит, приложение поймает свисток судьи и прекратит работу.
« Последнее редактирование: Март 09, 2015, 17:44 от PinkPanther » Записан

Эвтаназия - наше хобби!
Old
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4349



Просмотр профиля
« Ответ #26 : Март 09, 2015, 17:44 »

Я же спрашиваю зачем, если размер массива можно вычислить (как делает delete) да ещё умножить на 4 (для 32-х разрядной системы).
delete ничего не вычисляет, new получает неободимый размер буфера в байтах, она ничего не знает сколько элементов в него поместиться. delete освобождает этот блок.
По размеру буфера в байтах нельзя получить количество элементов в нем.
Записан
Old
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4349



Просмотр профиля
« Ответ #27 : Март 09, 2015, 17:51 »

2PinkPanther Мы хоть и в защищенном режиме, но в flat mode, поэтому указатель это именно адрес в виртуальном адресном пространстве, и дискрипторы здесь не причем.
Записан
sergek
Гипер активный житель
*****
Offline Offline

Сообщений: 870


Мы должны приносить пользу людям.


Просмотр профиля
« Ответ #28 : Март 09, 2015, 17:52 »

Я же спрашиваю зачем, если размер массива можно вычислить (как делает delete) да ещё умножить на 4 (для 32-х разрядной системы). Тут люд говорит - не важно, может у нас массив больше, да и не с той позиции хотим. Чтож, согласен. Возможен и такой вариант. Но пока не сказал (тот же люд), почему нет проверки на выход за пределы буфера и передаваемым размером.
Трудно вас понимать. Может, вы хотите сказать, что распределяя память по адресу ptr, размер распределенной памяти хранится в системе. И при передаче ptr в функцию, эту информацию можно взять из системы?
Но, во-первых, функция не знает, каким оператором (new или new[]) выделена память, а, во-вторых, память выделяется не байтами, а блоками, с выравниванием. А это уже зависит от платформы и компилятора.
Поэтому somFunc(c+20, 100) - это самострел.
Записан

Qt 5.13.0 Qt Creator 5.0.1
Win10, Ubuntu 20.04
PinkPanther
Самовар
**
Offline Offline

Сообщений: 169



Просмотр профиля
« Ответ #29 : Март 09, 2015, 18:03 »

2PinkPanther Мы хоть и в защищенном режиме, но в flat mode, поэтому указатель это именно адрес в виртуальном адресном пространстве, и дискрипторы здесь не причем.

В каком режиме идет работа - это уровень конкретной архитектуры машины. Здесь же идет речь об архитектуре языка, о причинах, почему функции требуют дополнительные данные. Ответ - архитектура может быть разной, в некоторых размер блока может стать физически неизвестным после его выделения. Хотя надстройки (siztof() и так далее), конкретные реализации библиотек С++ и предоставляют возможность это выяснить - в рамках любезности разработчиков.
Записан

Эвтаназия - наше хобби!
Страниц: 1 [2] 3 4 ... 6   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.087 секунд. Запросов: 22.