Russian Qt Forum

Разное => Говорилка => Тема начата: AzazelloAV от Март 09, 2015, 00:27



Название: Плюсолюбителям
Отправлено: AzazelloAV от Март 09, 2015, 00:27
Qt ни причём, однако.
Являюсь "пользователем" библиотеки, поэтому напишу.

Объясните гуру плюсов (и просто С) вещь, которая меня уже давно "мучает".
Зачем, зачем при передаче массива (к примеру char*, не строки) в API (любой) передаётся его размер?

Я точно уверен, что объяснения этому есть, но грамотный запрос в поисковики так и не смог составить, чтобы получить ответ.

Приведу пример условного кода.

char * c = new 100;
void somFunct(c,100)
delete []с;

Этот когд всегда мне мозг выносит.




Название: Re: Плюсолюбителям
Отправлено: gil9red от Март 09, 2015, 00:35
Потому-что, массив не знает свой размер, это простой тип, а не класс, по сути массив -- указатель на первый элемент, и количество своих элементов он не знает, потому что они находятся последовательно в памяти, после первого элемента (и включая первый элемент).
Массивы символов могут "знать" свой размер благодаря завершающему символу '\0' в конце, и то он не обязателен :)

Используйте в плюсах класс vector -- тот же массив, но более продвинутый :)


Название: Re: Плюсолюбителям
Отправлено: AzazelloAV от Март 09, 2015, 00:48
Потому-что, массив не знает свой размер, это простой тип, а не класс, по сути массив -- указатель на первый элемент, и количество своих элементов он не знает, потому что они находятся последовательно в памяти, после первого элемента (и включая первый элемент).
Массивы символов могут "знать" свой размер благодаря завершающему символу '\0' в конце, и то он не обязателен :)

Используйте в плюсах класс vector -- тот же массив, но более продвинутый :)

Вы меня не поняли. Qt  здесь вообще далеко.
Я привел пседокод, процитирую его:

char * c = new 100;
void somFunct(c,100)
delete []с;

Cмущает, что нет delete[100]c

Другими словами delete знает, сколько ему данных удалять, а в других случаях: "Извените, размер массива не известен"


Название: Re: Плюсолюбителям
Отправлено: gil9red от Март 09, 2015, 01:13
Потому-что, массив не знает свой размер, это простой тип, а не класс, по сути массив -- указатель на первый элемент, и количество своих элементов он не знает, потому что они находятся последовательно в памяти, после первого элемента (и включая первый элемент).
Массивы символов могут "знать" свой размер благодаря завершающему символу '\0' в конце, и то он не обязателен :)

Используйте в плюсах класс vector -- тот же массив, но более продвинутый :)

Вы меня не поняли. Qt  здесь вообще далеко.

это вы меня не поняли )
я говорил про vector, или std::vector, а не про QVector :)
vector это стандартный класс плюсов

А вот откуда delete знает сколько ему удалять я не знаю, подождем ответа более опытных форумчан ;)


Название: Re: Плюсолюбителям
Отправлено: Bepec от Март 09, 2015, 01:13
Выделить можно 100, а использовать 20. Оставшиеся 80 будут забиты мусором.
Передаем мы собственно контейнер и размер используемого пространства.

[Псевдокод]
Допустим мы инициализируем массив из 30 элементов.
Код:
char *c = new 30;
c = "poiuyhjuyhjuytghytrfgtredgbhyj"
 и добавляем в него слово Привет.
Код:
strcpy(c,"Привет");
c = "Привет\0uyhjuytghytrfgtredgbhyj"
И нам надо вывести слово на экран.
Код:
PrintStr(c, 6);
На экране - "Привет"

Если просто передать массив с его размером, то получим следующее
Код:
PrintStr(c, 30);
На экране - "Привет\0uyhjuytghytrfgtredgbhyj"



Название: Re: Плюсолюбителям
Отправлено: Swa от Март 09, 2015, 01:30
Другими словами delete знает, сколько ему данных удалять, а в других случаях: "Извените, размер массива не известен"
Да, именно так.
Вот тут (http://isocpp.org/wiki/faq/freestore-mgmt#num-elems-in-new-array) немного написано.


Название: Re: Плюсолюбителям
Отправлено: AzazelloAV от Март 09, 2015, 01:44
Выделить можно 100, а использовать 20. Оставшиеся 80 будут забиты мусором.
Передаем мы собственно контейнер и размер используемого пространства.

Допустим мы инициализируем массив из 30 элементов.


Не не не не.
С твоей стороны используется софизм, который в тупик заведёт.
Во первых, нужно забыть про строки (они же с 0), а во вторых, определить правила.

1. Как есть, так есть. Цель просто понять, почему по историческим причинам так.
2. Размер передается для избежания переполнения, безопасности и т.д.
3. delete  знает размер данных и спокойно их удаляет. Если пункт 2 не подходит (нужно хитрый размер по другим причинам) - я не видел таких функций. Тогда все остальные должны быть с одним параметром.

Даже если есть такие функции, в которых размер передается для "хитрых" вещей -  я их не встречал, по крайней мере в ВинАПИ (с линухом АЙПИ напрямую не работал)

Если нужен максимальный размер, вы видели такие функции, которые не передавали бы размер?


Название: Re: Плюсолюбителям
Отправлено: AzazelloAV от Март 09, 2015, 01:46
Другими словами delete знает, сколько ему данных удалять, а в других случаях: "Извените, размер массива не известен"
Да, именно так.
Вот тут (http://isocpp.org/wiki/faq/freestore-mgmt#num-elems-in-new-array) немного написано.

Та там тоска читать, мы же не компиляторы пишем, объясните в двух словах, с какого.

Ага, ну это не ответ на вопрос. Страуструп внятно в своих книгах описывает даже где хранятся эти самые байты (размер массива).

Вопрос же почему там так, а там - мы не знаем.


Название: Re: Плюсолюбителям
Отправлено: Bepec от Март 09, 2015, 01:47
Собственно передача размера даёт вам гибкость и возможность реализовать функцию как угодно, не меняя её входных аргументов.
Функция на 1 символ и миллион будет иметь один прототип. Простор для вашей фантазии.


Название: Re: Плюсолюбителям
Отправлено: AzazelloAV от Март 09, 2015, 01:53
Собственно передача размера даёт вам гибкость и возможность реализовать функцию как угодно, не меняя её входных аргументов.
Функция на 1 символ и миллион будет иметь один прототип. Простор для вашей фантазии.


Повторюсь - это не так. Передается "не для фантазии", а для "размера". Какая гибкость может быть в вызове функции "получить полный путь к файлу"?  Если я не ошибаюсь, в примерах МСДН был полный путь [1024] (буфер), какую гибкость можно получить уменьшая или увеличивая этот размер?


Название: Re: Плюсолюбителям
Отправлено: Igors от Март 09, 2015, 09:55
Собственно передача размера даёт вам гибкость и возможность реализовать функцию как угодно, не меняя её входных аргументов.
Как ни странно, это "правельный ответ"

Другими словами delete знает, сколько ему данных удалять, а в других случаях: "Извените, размер массива не известен"
delete знает размер выделенного блока, который совсем не 100. Однако
Код
C++ (Qt)
void SomeFunc(  char * c )
{
...
}
SomeFunc ничего не знает о размере строки. "c" может быть чем угодно, напр подстрокой в др строке. глобальной переменной, буфером др класса и.т.д. Если размер не передан явно, то SomeFunc остается полагать что строка заканчивается нулем.

Др. словами не надо обобщать частный случай "строка в куче" - даже в этом случае точное число символов неизвестно


Название: Re: Плюсолюбителям
Отправлено: RSATom от Март 09, 2015, 10:02
Например потому что выделенную память можно использовать вот так:

Код
C++ (Qt)
char* c = new char[100];
somFunc(c, 10);
somFunc(c+10, 10);
somFunc(c+20, 80);
delete [] с;
 

а указывать в delete [] размер выделенной памяти не нужно просто потому что CRT знает сколько памяти было выделено.


Название: Re: Плюсолюбителям
Отправлено: sergek от Март 09, 2015, 11:37
Cмущает, что нет delete[100]c
Другими словами delete знает, сколько ему данных удалять, а в других случаях: "Извените, размер массива не известен"
operator delete() и operator delete[]() - это разные операторы и предназначены для освобождения памяти, выделенной с помощью разных операторов operator new() и operator new[]() соответственно. Собственно, это все объясняет - требования языка.
Если бы вы посмотрели материал, который вам предложил Swa, вы бы поняли, что использование delete для массива может привести не только к неполному освобождению памяти, но и к краху программы. И связано это с тем, что в разных реализациях компиляторов new и new[] по-разному выделяют память и хранят ее размер.


Название: Re: Плюсолюбителям
Отправлено: AzazelloAV от Март 09, 2015, 15:35
Например потому что выделенную память можно использовать вот так:

Код
C++ (Qt)
char* c = new char[100];
somFunc(c, 10);
somFunc(c+10, 10);
somFunc(c+20, 80);
delete [] с;
 

а указывать в delete [] размер выделенной памяти не нужно просто потому что CRT знает сколько памяти было выделено.

Это хороший пример, и действительно....
Но мы его разобъём об скалы уязвимости, которыми пестрят книги....

Код
C++ (Qt)
somFunc(c+20, 100);
 

Я всего лишь говорю, что везде классика предлагает: "нужно передавать размер, потому как его никто не знает".
Нигде я не встречал оправданий, что размер передаётся для  вашего варианта передачи.


Название: Re: Плюсолюбителям
Отправлено: AzazelloAV от Март 09, 2015, 15:44
Цитировать
operator delete() и operator delete[]() - это разные операторы и предназначены для освобождения памяти, выделенной с помощью разных операторов operator new() и operator new[]() соответственно. Собственно, это все объясняет - требования языка.
Если бы вы посмотрели материал, который вам предложил Swa, вы бы поняли, что использование delete для массива может привести не только к неполному освобождению памяти, но и к краху программы. И связано это с тем, что в разных реализациях компиляторов new и new[] по-разному выделяют память и хранят ее размер.
То, что delete может хранится по разному для разных компиляторах ничего не значит. Также может разными компиляторами реализовывать VMT. Но т.к. это происходит в одном "пространстве компилятора", это не важно, он же знает где хранится.
Хотя в общем случае это не так, все хранят одинаково, иначе были бы сложности в вызове функций delete для разных библиотек.
Ведь есть функции, которые возращают новый объект, выделеный, вы им передаете только указатель, освобождение ложится на вас. Если, то, что вы говорите было правдой, мы бы не смогли пользоваться такой библиотекой с другим компилятором.


Название: Re: Плюсолюбителям
Отправлено: Bepec от Март 09, 2015, 16:12
AzazelloAV - в вашем примере ошибся программист, а не программа.
И вопрос об уязвимости человеческого фактора, а не функции.

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

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


Название: Re: Плюсолюбителям
Отправлено: AzazelloAV от Март 09, 2015, 16:32
AzazelloAV - в вашем примере ошибся программист, а не программа.
И вопрос об уязвимости человеческого фактора, а не функции.

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

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

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

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

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

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


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


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

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

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

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

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

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


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


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


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

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


Название: Re: Плюсолюбителям
Отправлено: Old от Март 09, 2015, 17:26
Проверяют, если этого хочет разработчик, и передача этого размера в качестве парамеира, как раз позволяет это сделать.


Название: Re: Плюсолюбителям
Отправлено: Alex Custov от Март 09, 2015, 17:27
Я тогда сформулирую свой вопрос очень конкретно, без всяких стрельб в ноги - почему функции хотя бы не проверяют выход за рамер буфера?

Смотря какого буфера и смотря какие функции. Например?


Название: Re: Плюсолюбителям
Отправлено: AzazelloAV от Март 09, 2015, 17:31
Нет. Я как раз не про строки, а про объекты классов.
Функция func( SuperClass *ptr ) никак не может узнать количество элементов в массиве, она даже не может определить ptr указатель на одиночный объект или массив объектов.

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


Название: Re: Плюсолюбителям
Отправлено: PinkPanther от Март 09, 2015, 17:36
Цитировать
Операторы new[] и delete[] получают размер необходимого буфера в байтах, а не количество элементов. Даже сохранив этот размер он не поможет определить число элементов.

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

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

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

Кстати, прибавляя к адресу, вы получите адреса следующих элементов. Но попробуйте отнять. Вы не получите физический адрес. Вы выскочите за пределы выделенной памяти с обратной стороны, в пустую область или в область другого блока, процессор это заметит, приложение поймает свисток судьи и прекратит работу.


Название: Re: Плюсолюбителям
Отправлено: Old от Март 09, 2015, 17:44
Я же спрашиваю зачем, если размер массива можно вычислить (как делает delete) да ещё умножить на 4 (для 32-х разрядной системы).
delete ничего не вычисляет, new получает неободимый размер буфера в байтах, она ничего не знает сколько элементов в него поместиться. delete освобождает этот блок.
По размеру буфера в байтах нельзя получить количество элементов в нем.


Название: Re: Плюсолюбителям
Отправлено: Old от Март 09, 2015, 17:51
2PinkPanther Мы хоть и в защищенном режиме, но в flat mode, поэтому указатель это именно адрес в виртуальном адресном пространстве, и дискрипторы здесь не причем.


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


Название: Re: Плюсолюбителям
Отправлено: PinkPanther от Март 09, 2015, 18:03
2PinkPanther Мы хоть и в защищенном режиме, но в flat mode, поэтому указатель это именно адрес в виртуальном адресном пространстве, и дискрипторы здесь не причем.

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


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

О, извеняюсь что сложно высказываюсь, но вы меня правильно поняли.
То, что память выделяется блоками нас нисколечки не должно волновать. Мало того, что с выравниванием, так ещё и по бланкам 4Кб (если находятся на границе). Но это нас не касается, как и то, что размер файла тоже выравнивается по размеру кластера на винте. Мы же оперируем размером файла, которые нам предоставила ОС.

Но вот вы сказали самострел. Зачем же функция не проверяет этот самострел, когда delete известен этот размер. Не может delete оперировать физическими размерами реальной памяти (как вы знаете, у 32-х разрядных систем 48 разрядная адресcация (46, если быть справедливым)). Но он оперирует виртуальным адресным пространством, а выравнивание на границы 32 происходит на этапе new, а не delete


Название: Re: Плюсолюбителям
Отправлено: Old от Март 09, 2015, 18:14
Нет никакой архитектуры языка. Все зависит от реализации менеджера памяти в стандартной библиотеке. В языке нет стандартных средств определить размер выделенного блока, да это и не нужно.


Название: Re: Плюсолюбителям
Отправлено: AzazelloAV от Март 09, 2015, 18:23
Нет никакой архитектуры языка. Все зависит от реализации менеджера памяти в стандартной библиотеке. В языке нет стандартных средств определить размер выделенного блока, да это и не нужно.

Так я и про тоже. delete видите ли знает, но никому не говорит. Он что, (этот delete), на марсе живёт, и никто не знает как он устроен? Мы туда (на Марс) запросы шлём. Он оперирует конретными значениями, и говорит конкретные вещи ОС, что данная память свободна. Везде это работает. Какие магические числа передает delete менеджеру памяти, этому черному ящику, что он, только менеджер памяти это знает, но скрывает от нас. Так ли это?


Название: Re: Плюсолюбителям
Отправлено: Old от Март 09, 2015, 18:32
Так я и про тоже. delete видите ли знает, но никому не говорит. Он что, (этот delete), на марсе живёт, и никто не знает как он устроен? Мы туда (на Марс) запросы шлём. Он оперирует конретными значениями, и говорит конкретные вещи ОС, что данная память свободна. Везде это работает. Какие магические числа передает delete менеджеру памяти, этому черному ящику, что он, только менеджер памяти это знает, но скрывает от нас. Так ли это?
Не нужно смешивать менеджер памяти ядра ОС с менеджером памяти кучи, которым и пользуется рантайм C++ для выделения памяти. Это совершенно разные вещи.
delete может не знать размер блока, это нигде не стандартизованно.
И еще раз, если delete и знает размер, то это размер блока в байтах, а из этого размера нельзя вычислить, сколько объектов находятся в этом блоке.


Название: Re: Плюсолюбителям
Отправлено: AzazelloAV от Март 09, 2015, 18:43
Цитировать
Не нужно смешивать менеджер памяти ядра ОС с менеджером памяти кучи, которым и пользуется рантайм C++ для выделения памяти. Это совершенно разные вещи.
delete может не знать размер блока, это нигде не стандартизованно.
И еще раз, если delete и знает размер, то это размер блока в байтах, а из этого размера нельзя вычислить, сколько объектов находятся в этом блоке.

Я с трудом представляю что такое менеджер памяти кучи, и мне кажется, что его попросту нет.
Также с трудом представляю, что такое менеджер памяти ядра linux, которое, грузится напрямую, без всякого менеджера памяти.
Но то такое, может там и существую какие то дикие "менеджеры", как для винта планировщики, но тогда что они делаю - мне неизвестно.

При чем здесь кол-во блоков. Где передается кол-во блоков, всегда передаётся только размер.


Название: Re: Плюсолюбителям
Отправлено: Bepec от Март 09, 2015, 18:44
Это у вас отсутствует теоритическая база :) Бессмысленно разговаривать :D


Название: Re: Плюсолюбителям
Отправлено: Old от Март 09, 2015, 18:48
При чем здесь кол-во блоков. Где передается кол-во блоков, всегда передаётся только размер.
Ну так в функции вместе с указателем на начало массива, обычно передают количество элементов в массиве, а не размер занимаемой им памяти в байтах.


Название: Re: Плюсолюбителям
Отправлено: PinkPanther от Март 09, 2015, 18:51
Нет никакой архитектуры языка. Все зависит от реализации менеджера памяти в стандартной библиотеке. В языке нет стандартных средств определить размер выделенного блока, да это и не нужно.

Я об этом и говорю. Абстрактный delete[] не знает, сколько памяти освобождается. Стандартная библиотека - надстройка, ей можно не пользоваться, пользоваться чем-то еще, а выделять память при помощи new[] и освобождать при помощи delete[], которые являются частью языка, можно в любой программе на С++. Количество элементов для обработки потом придется указать явно, так как средствами С++, если не ошибаюсь, нет возможности выяснить ни размер выделенного блока в байтах, ни количество элементов в массиве.

Пример с дескрипторами - демонстрация, когда указатель хранит не адрес ячейки памяти, а что-то еще. Строго говоря, на абстрактной платформе, под которую может быть написан компилятор С++, указатель может иметь абсолютно любой формат, и может не предоставлять никакой информации о размере массива, на который он (явно или опосредованно) указывает. И delete[] - команда или последовательность команд ASSM - также не будет знать ничего о размере блока, которую выделяли на старте. И, действительно, delete[] это знать не обязательно.


Название: Re: Плюсолюбителям
Отправлено: AzazelloAV от Март 09, 2015, 19:04
Это у вас отсутствует теоритическая база :) Бессмысленно разговаривать :D

Послушайте. Здесь собрались не ремесленики, а профессионалы и вы в том числе. (Я давно на форуме, пароль забыл, аккаунт новый, хотя часто просто читал). Большинство из делфы перепрыгнуло на Qt, чтобы дальше кодить красиво (так испортить язык низким порогом вхождения). Так что здесь случайных людей нет (не буквально). Большинство из старожил (как и вы) здесь пишут не потому как им нужно что-то, а просто помочь да и вообще..... Таким как вы не нужна помощь, уже давным давно, кто здесь сидит лезут в ответы в исходники, а не на форум и в инет. Вы всё это прекрасно знаете, и все здесь это прекрасно знают. Поделится идеей, найти правильный путь - вот что сейчас есть форум. Не помощь в чём либо, нет (ну кроме заблудьших).

К чему это я? К бессмысленно разговаривать! Если бы я хотел занятся темой "с какого перепугу" delete что-то там, я бы сюда не обращался. Как минимум сам исследовал и с готовыми какими то наработками или понятиями. Но мне по сути это не итересно, так есть, потому что так есть. А вы со своим "Бессмысленно разговаривать" обломили весь кайф. Может вы подумали что я побегу создавать версиию плюсов ISO 15?

К чему вы это сказали?


Название: Re: Плюсолюбителям
Отправлено: Bepec от Март 09, 2015, 19:14
К тому, что с вами бессмысленно разговаривать :) Засим умолкаю :D


Название: Re: Плюсолюбителям
Отправлено: AzazelloAV от Март 09, 2015, 19:17
К тому, что с вами бессмысленно разговаривать :) Засим умолкаю :D


Я с вами не соревнуюсь. Но поверьте, это сообщение было лишнее. Так оно противоречит самому себе.


Название: Re: Плюсолюбителям
Отправлено: Igors от Март 10, 2015, 07:10
Я тогда сформулирую свой вопрос очень конкретно, без всяких стрельб в ноги - почему функции хотя бы не проверяют выход за рамер буфера?
Потому что язык С разрабатывался как альтернатива ассемблеру. Плюсы вносят свое, но этой базовой позиции не меняют.  Пример
Код
C++ (Qt)
std::vector <char> test(5);
test[10] = 0;
 
Здесь можно добиться исключения по выходу за границы - но ценой использования контейнера. Это "приемлемо", но далеко не бесплатно. В С/C++ программист сам решает идти на эти расходы или нет. Если Вы хотите чтобы это делали за Вас всегда и везде - используйте др язык.

И еще: не очень хорошее название темы. Как-то это звучит вызывающе, да и "любителей" здесь немного. Во всяком случае идеологию и принципы языка все понимают.


Название: Re: Плюсолюбителям
Отправлено: qate от Март 10, 2015, 13:29
полагаю, что на delete [] нет стандарта "реализации", а также можно сделать свой delete []
есть наверно еще ответ: " не предусматривалось" )


Название: Re: Плюсолюбителям
Отправлено: Lagovas от Март 10, 2015, 13:52
https://isocpp.org/wiki/faq/freestore-mgmt#num-elems-in-new-array


Название: Re: Плюсолюбителям
Отправлено: ViTech от Март 10, 2015, 14:52
Я с трудом представляю что такое менеджер памяти кучи, и мне кажется, что его попросту нет.
Также с трудом представляю, что такое менеджер памяти ядра linux, которое, грузится напрямую, без всякого менеджера памяти.
Но то такое, может там и существую какие то дикие "менеджеры", как для винта планировщики, но тогда что они делаю - мне неизвестно.
Может тогда стоит разобраться? Раз уж такой интерес к работе с памятью возник :). Ещё есть исходники компиляторов, где можно посмотреть, как работают все эти new и delete.


Название: Re: Плюсолюбителям
Отправлено: Hrundel от Март 10, 2015, 18:11
А вот откуда delete знает сколько ему удалять я не знаю, подождем ответа более опытных форумчан ;)

Этим ОСь занимается, она должна следить за удалением из кучи.


Название: Re: Плюсолюбителям
Отправлено: Old от Март 10, 2015, 18:14
Этим ОСь занимается, она должна следить за удалением из кучи.
ОС понятия не имеет о куче, кучи может вообще не быть. ;)
Куча это уровень рантайма стандартной библиотеки.


Название: Re: Плюсолюбителям
Отправлено: Hrundel от Март 10, 2015, 18:16
Все-равно, ось не дает программам написанным на С++ на прямую обращаться к памяти. 


Название: Re: Плюсолюбителям
Отправлено: Old от Март 10, 2015, 18:21
Все-равно, ось не дает программам написанным на С++ на прямую обращаться к памяти. 
Используется механизм виртуальной памяти, когда ОС подставляет страницы физической памяти в адресное пространство процесса.
А дальше процесс уже работает с подставленной физической памятью. Процесс не знает, в какую физическую страницу он пишет/читает, ну ему это и не надо.


Название: Re: Плюсолюбителям
Отправлено: AzazelloAV от Март 14, 2015, 16:00
Для себя ничего не уяснил, видно много действительно разных условий.
Если брать DOS, контроллеры, загрузчики - всё, что грузится на голое железо не может не знать о размере выделяемой памяти, не может запрашивать ОС о памяти, т.к. самой оси нету. Менеджеры памяти приложения, о которых говорили - ну это сама программа приложения, глупо говорить что auto_ptr (в данном контексте), является менеджером памяти приложения. Учитывая, что new появился в плюсах задолго до всяких хитрых ОС, значит это было осознанно.

Данную историческую причину я для себя так и не уяснил. Совершенно ясен факт - new выделяет память и спокойно может знать сколько памяти выделено. Эту информацию ему может вернуть сама ОС (дико звучит, что ОС лучше знает, сколько памяти нужно выделить данной операции, ну пусть так, прогнусь под общественное мнение) или компилятор (если на голом железе). Эту информацию можно "зашить" в выделенный указатель для массивов. Все равно эта информация где-то хранится. Да и вообще! Если уж так, с какого перепугу две версии delete существует, просто и delete[].

Опять же, главный вопрос - почему так не сделали.


Название: Re: Плюсолюбителям
Отправлено: Old от Март 14, 2015, 16:10
Если посмотреть ваш первый и последний пост в этой теме, то становиться очевидно, что вы путаете размер и количество элементов массива. Часто они не совпадают.


Название: Re: Плюсолюбителям
Отправлено: AzazelloAV от Март 14, 2015, 16:17
Если посмотреть ваш первый и последний пост в этой теме, то становиться очевидно, что вы путаете размер и количество элементов массива. Часто они не совпадают.

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

char * = new[100]
size = 100;
someFunct(char+50,size)


Название: Re: Плюсолюбителям
Отправлено: Old от Март 14, 2015, 16:18
Я не знаю кто и для чего так делает.  :)


Название: Re: Плюсолюбителям
Отправлено: AzazelloAV от Март 14, 2015, 16:21
Я не знаю кто и для чего так делает.  :)

Да не важно, кто и для чего так делает, важно то, что функция это проглотит и не проверит, что памяти меньше, чем нужно


Название: Re: Плюсолюбителям
Отправлено: gil9red от Март 14, 2015, 16:25
Я не знаю кто и для чего так делает.  :)

Да не важно, кто и для чего так делает, важно то, что функция это проглотит и не проверит, что памяти меньше, чем нужно

Поймите, это с++, и его компилятор считает, что у программиста руки прямые и растут из правильного места, и не будет делать такие проверки.
Не пойму, чего рассусоливать эту тему? :)


Название: Re: Плюсолюбителям
Отправлено: Old от Март 14, 2015, 16:26
Да не важно, кто и для чего так делает, важно то, что функция это проглотит и не проверит, что памяти меньше, чем нужно
Правильно, проверка входных параметров лежит на программисте и это замечательно. Я сам могу решать, в какой функции стоит проверять параметры, а в какой это избыточно.


Название: Re: Плюсолюбителям
Отправлено: AzazelloAV от Март 14, 2015, 16:33
Цитировать
Поймите, это с++, и его компилятор считает, что у программиста руки прямые и растут из правильного места, и не будет делать такие проверки.
Не пойму, чего рассусоливать эту тему? :)

Я рад, что тему в курилку перенесли.
При программирование на плюсах, я не заметил ни одной вещи, которая бы противоречила бы "логике" плюсов. Да, можно выстрелить в ногу, но всему есть объяснений. И чем больше ты их знаешь, тем проще тебе на них писАть. Нету у них мелочей, абсолютно. Все продумано давным давно, всё стройно и красиво. Даже если что-то не так, ты понимаешь, почему это не так и опять всё становится стройно и красиво.

Тут пару лет назад предлагали внести в плюсы property, так народ обосрался, как это мы без get/set будем (хотя само Qt пренебригает префиксом get). А что всего лишь property - аля inline - повышение области видимости.

Ну а почему рассусоливать - ну просто, рассусоливаем, без причины.


Название: Re: Плюсолюбителям
Отправлено: AzazelloAV от Март 14, 2015, 16:36
Да не важно, кто и для чего так делает, важно то, что функция это проглотит и не проверит, что памяти меньше, чем нужно
Правильно, проверка входных параметров лежит на программисте и это замечательно. Я сам могу решать, в какой функции стоит проверять параметры, а в какой это избыточно.

Подойду от обратного.
Совершенно с вами согласен! Но как же программисту получить объём выделенной памяти? Где ТО САМОЕ сравнение перед вызовом функции, которая проверит что памяти не хватит. Опять переменные вводить и синхронизировать их....

Другими словами:
Код:
char * = new[100]
size = 100;
someFunct(char+50,size-50)

Вместо
Код:
char * = new[100]
someFunct(char+50) //функция может проверить, сколько памяти доступно


Название: Re: Плюсолюбителям
Отправлено: Old от Март 14, 2015, 16:54
Если вам нужен размер, то нужно использовать коллекции, которые его сохраняют.


Название: Re: Плюсолюбителям
Отправлено: AzazelloAV от Март 14, 2015, 17:02
Если вам нужен размер, то нужно использовать коллекции, которые его сохраняют.

Мои рассуждения не имеют практической плоскости. Меня интересует "историческая". Так есть, потому что оно так есть, все уже привыкли и считают как должное. Это как предварительная оптимизация, все пишут "++i" и тут понятно, почему так, любой захудалый учебник пишет об этом и все пользуются этим на уровене подсознания. А нету не захудалого учебника, описывающий такое поведение new/delete


Название: Re: Плюсолюбителям
Отправлено: Old от Март 14, 2015, 17:08
Потому, что это избыточно.
Вы выделяете память сами, вы знаете ее размер, вы знаете начало блока, вы можете вычислить конец блока.
Если вам нужно иметь возможность по указателю, получить размер блока, вы всегда это можете реализовать сами.


Название: Re: Плюсолюбителям
Отправлено: AzazelloAV от Март 15, 2015, 01:46
Потому, что это избыточно.
Вы выделяете память сами, вы знаете ее размер, вы знаете начало блока, вы можете вычислить конец блока.
Если вам нужно иметь возможность по указателю, получить размер блока, вы всегда это можете реализовать сами.

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

Давайте если уж так, сравним на более примитивном уровне.
Возьмём "нелюбимый" всеми pascal с его хранением длины строки в первом байте и Си, с заканчивающим нулём (я про то далёкое).

Паскалевская строка самодостаточна (опустим возражения, что классический паскаль только 255 размер), сишная тупа, нужно искать 0. На данном этапе рожки да ножки остались от сишных строк, все пользуются "паскалевским" типом строк (к примеру   QString т.е. все заранее знают, каков размер.)

Если вы поняли, я провожу аналогию - все знают, что строки с #0 плохо, но все понимают, почему так.  

У меня нет объяснений про new/delete.

P.S. Только не надо говорить про класс QString, что это не паскаль строка и рядом не стояла. Мы с другой позиции смотрим.


Название: Re: Плюсолюбителям
Отправлено: Igors от Март 15, 2015, 10:38
Паскалевская строка самодостаточна (опустим возражения, что классический паскаль только 255 размер), сишная тупа, нужно искать 0. На данном этапе рожки да ножки остались от сишных строк, все пользуются "паскалевским" типом строк (к примеру   QString т.е. все заранее знают, каков размер.)
Всегда есть конфликт между эффективностью и удобством пользования, это нормально.
Код
C++ (Qt)
s2 = s1 + ".txt";
Да, с сишной строкой это отольется в порядочный геморрой. Но ведь за удобство и заплачено немало. Сначала надо привести ".txt" к строковому классу, выделить память и скопировать. А с QString еще и в юникод перевести. Потом опять выделить память и склеить строки. Потом еще раз скопировать в s2. И наконец избавиться от временных переменных.

Популярное мнение "да зачем мне знать что там делается за кадром? Я вот написал 1 строку - и все! Что я, должен с strcpy мудохаться?". Нет конечно, к этому никто не призывает. Но понимать что чего стоит необходимо. Иначе бездумный подход само-воспроизводится, "невникающий" начинает ляпать контейнерами - а это уже совсем не мелочи со строками. Вот не так уж давно человек накатал статью(!) где предлагает такой способ создания 2-мерного массива
Код
C++ (Qt)
std::vector <std::vector <int> > MyArray
Это взамен "устаревшего" С-массива. Ну а чего? Где говнокод? Удобно писать MyArray[ i ][ j ]? Удобно! Ну и все!

Короче: не нравится ассеиблер - переходите на жабу, будете всем в нос тыкать "сборщиком мусора" и.т.п.  :)


Название: Re: Плюсолюбителям
Отправлено: Old от Март 15, 2015, 11:00
У меня нет объяснений про new/delete.
А какие претензии к new/delete? Они выделяют/освобождают необходимый блок памяти. Все.
Вы же хотите, что бы указатель знал размер блока, внутрь которого он указывает. Вот это и есть избыточность, которая никому не нужна.
Мне нужно, что бы указатель был просто адресом в пространстве процесса. Если мне понадобятся какие-то дополнительные параметры, я их обеспечу сам. А если все указатели будут хранить какие-то размеры, то мы получим огромный оверхед как по памяти, так и по производительности. Понадобится эти размеры вычислять и заполнять, для всех указателей.


Название: Re: Плюсолюбителям
Отправлено: AzazelloAV от Март 15, 2015, 13:33
У меня нет объяснений про new/delete.
А какие претензии к new/delete? Они выделяют/освобождают необходимый блок памяти. Все.
Вы же хотите, что бы указатель знал размер блока, внутрь которого он указывает. Вот это и есть избыточность, которая никому не нужна.
Мне нужно, что бы указатель был просто адресом в пространстве процесса. Если мне понадобятся какие-то дополнительные параметры, я их обеспечу сам. А если все указатели будут хранить какие-то размеры, то мы получим огромный оверхед как по памяти, так и по производительности. Понадобится эти размеры вычислять и заполнять, для всех указателей.


Да какой же оверхед. Это что, колодец какой то бездонный (черный ящик) ,  ну знает же кто-то сколько памяти нужно освободить при делете, это где то хранится, в любом случае это где то есть, ну что у нас делете  - это какое то запредельное что-то, которое живет в секретном потоке на секретном процессоре? Он что то вызывает и это что-то уж точно знает что оно делает и сколько нужно удалить.  Значит данные уже гдето "живут". А у нас получается, что создать/удалить объект (объект ООП) мы запросто можем, а узнать сколько он памяти ест - тут целые програмные комплексы нужны.


Название: Re: Плюсолюбителям
Отправлено: Old от Март 15, 2015, 14:09
ну знает же кто-то сколько памяти нужно освободить при делете
Знает и что? Как этот размер должен быть связан с любым указателем, который вы можете передать в функцию?


Название: Re: Плюсолюбителям
Отправлено: Igors от Март 15, 2015, 14:13
Да какой же оверхед. Это что, колодец какой то бездонный (черный ящик) ,  ну знает же кто-то сколько памяти нужно освободить при делете, это где то хранится, в любом случае это где то есть, ну что у нас делете  - это какое то запредельное что-то, которое живет в секретном потоке на секретном процессоре? Он что то вызывает и это что-то уж точно знает что оно делает и сколько нужно удалить.  Значит данные уже гдето "живут". А у нас получается, что создать/удалить объект (объект ООП) мы запросто можем, а узнать сколько он памяти ест - тут целые програмные комплексы нужны.
Вы как-то уперлись в это "delete ЗНАЕТ размер". Ну знает, так что, давайте чтобы каждый указатель знал свой размер? Ну это, мягко говоря, неразумно. Уже не раз сказали что указатель может указывать на что угодно, а не только на блок в куче. Что Вы хотите? А то уже пошла толчея воды в ступе


Название: Re: Плюсолюбителям
Отправлено: Авварон от Март 16, 2015, 00:30
Что-то старожилы совсем опозорились в данном топике. Хоть топикстартер и пишет фигню по большей части, но здесь он затронул больную тему с/с++. Правильный ответ на его вопрос - "потому что си - говно".
Во-первых. delete[] КОНЕЧНО ЖЕ ЗНАЕТ количество элементов. Иначе как он вызовет нужное количество деструкторов?
Во-вторых. Все почему-то зазубрили что массив и указатель - это одно и то же. Но это не так. char * и char [] - это разные типы (в char[] нельзя записать char * но наоборот - можно). К сожалению, в сях работа с массивами не доведена до хоть какого-то ума (к примеру то, что просит топикстартер - передать T[] в ф-ию как пару T* + size)


Название: Re: Плюсолюбителям
Отправлено: Igors от Март 16, 2015, 13:07
..совсем опозорились ... пишет фигню ... "потому что си - говно"...в сях работа с массивами не доведена до хоть какого-то ума..
Подобная тональность говорит совсем не о понимании языка, а показывает "чрезмерную начитанность" приведшую к некоторой переоценке своих сил :)

Если Вы говорите "указатель", то тем самым уже признаете что никаких гарантий никто не дает. Это просто "адрес" - и все. Интимные подробности delete [] ровным счетом ничего не меняют. Единственное принципиальное решение - избавиться от указателя вообще, а заодно и от new/delete, Именно так и сделано в жабе. Если Вам по душе такой подход - переходите туда. А здесь было и будет так, и по мне это хорошо и правильно: не надо обо мне (навязчиво) заботиться, я сам о себе позабочусь


Название: Re: Плюсолюбителям
Отправлено: Авварон от Март 16, 2015, 13:49
Подобная тональность говорит совсем не о понимании языка, а показывает "чрезмерную начитанность" приведшую к некоторой переоценке своих сил :)

Если Вы говорите "указатель", то тем самым уже признаете что никаких гарантий никто не дает. Это просто "адрес" - и все. Интимные подробности delete [] ровным счетом ничего не меняют. Единственное принципиальное решение - избавиться от указателя вообще, а заодно и от new/delete, Именно так и сделано в жабе. Если Вам по душе такой подход - переходите туда. А здесь было и будет так, и по мне это хорошо и правильно: не надо обо мне (навязчиво) заботиться, я сам о себе позабочусь

Фигню какую-то написали.


Название: Re: Плюсолюбителям
Отправлено: ViTech от Март 16, 2015, 13:59
Данную историческую причину я для себя так и не уяснил. Совершенно ясен факт - new выделяет память и спокойно может знать сколько памяти выделено. Эту информацию ему может вернуть сама ОС (дико звучит, что ОС лучше знает, сколько памяти нужно выделить данной операции, ну пусть так, прогнусь под общественное мнение) или компилятор (если на голом железе). Эту информацию можно "зашить" в выделенный указатель для массивов. Все равно эта информация где-то хранится. Да и вообще! Если уж так, с какого перепугу две версии delete существует, просто и delete[].

Опять же, главный вопрос - почему так не сделали.

Мне кажется, правильные ответы тут звучали, но как-то размазаны по теме :).

delete, конечно же, знает размер выделенной памяти, на которую указывает указатель, возвращаемый new. Ключевое слово "указатель", а не объект какого-то класса/структуры, где можно узнать размер. Почему тогда наравне с этими операторами нет функции, которая бы возвращала размер выделенной памяти для заданного указателя?

Допустим, такая функция есть, пусть её зовут memory_size(), и возвращает она размер памяти по указателю в байтах (хоть в элементах, неважно). Вы можете гарантировать, что в качестве параметра для этой функции будут передаваться только указатели, возвращённые оператором new? А не любой произвольный указатель. И что делать этой функции, если туда передали "левый" указатель? И что ожидать и как обрабатывать ситуации с неверными указателями пользователям этой функции? Ловить исключения? А оно нам надо? :)

Например:
Код
C++ (Qt)
void someSortFunc(float *array)
{
   int array_size = memory_size(array);
   ...
}
 
main()
{
   float *a = new float[100];
   float *b = a + 50;
 
   someSortFunc(a);
   someSortFunc(b);
 
   delete[] a;
}
Что произойдёт во время вызова someSortFunc(b)? Какой результат должна вернуть memory_size(b)? Арифметические операции над указателями, надеюсь, никто не отменял.

Таким образом, memory_size() могла бы возвращать размер выделенной памяти, только для указателей, созданных с помощью new. Без всяких сдвигов и т.п. Но таких гарантий никто не может дать. Нужна ли тогда она вообще?

В общем, ответ на вопрос: "Почему нет функции, которая возвращает размер памяти, выделенный new?", Вы получите, когда придумаете реализацию функции memory_size() для произвольного указателя :).


Название: Re: Плюсолюбителям
Отправлено: Авварон от Март 16, 2015, 15:23
Мне кажется, правильные ответы тут звучали, но как-то размазаны по теме :).

delete, конечно же, знает размер выделенной памяти, на которую указывает указатель, возвращаемый new. Ключевое слово "указатель", а не объект какого-то класса/структуры, где можно узнать размер. Почему тогда наравне с этими операторами нет функции, которая бы возвращала размер выделенной памяти для заданного указателя?

Допустим, такая функция есть, пусть её зовут memory_size(), и возвращает она размер памяти по указателю в байтах (хоть в элементах, неважно). Вы можете гарантировать, что в качестве параметра для этой функции будут передаваться только указатели, возвращённые оператором new? А не любой произвольный указатель. И что делать этой функции, если туда передали "левый" указатель? И что ожидать и как обрабатывать ситуации с неверными указателями пользователям этой функции? Ловить исключения? А оно нам надо? :)

Например:
Код
C++ (Qt)
void someSortFunc(float *array)
{
   int array_size = memory_size(array);
   ...
}
 
main()
{
   float *a = new float[100];
   float *b = a + 50;
 
   someSortFunc(a);
   someSortFunc(b);
 
   delete[] a;
}
Что произойдёт во время вызова someSortFunc(b)? Какой результат должна вернуть memory_size(b)? Арифметические операции над указателями, надеюсь, никто не отменял.

Таким образом, memory_size() могла бы возвращать размер выделенной памяти, только для указателей, созданных с помощью new. Без всяких сдвигов и т.п. Но таких гарантий никто не может дать. Нужна ли тогда она вообще?

В общем, ответ на вопрос: "Почему нет функции, которая возвращает размер памяти, выделенный new?", Вы получите, когда придумаете реализацию функции memory_size() для произвольного указателя :).
Для сей написанное верно. Понятно, что для УКАЗАТЕЛЯ размер получить нельзя. Но, строго говоря, массив - это НЕ УКАЗАТЕЛЬ. То, что разрабы сей упростили себе жизнь, не отменяет факта, что так сделать нельзя.
В идеальном мире должно было бы так:
Код
C++ (Qt)
void someSortFunc(float array[])
{
   int array_size = memory_size(array);
   ...
}
 
Другое дело, что надо переделывать new (к примеру, возвращать не указатель, а ссылку на T[]) и куча других проблем возникает.


Название: Re: Плюсолюбителям
Отправлено: Igors от Март 16, 2015, 15:46
В общем, ответ на вопрос: "Почему нет функции, которая возвращает размер памяти, выделенный new?", Вы получите, когда придумаете реализацию функции memory_size() для произвольного указателя :).
Мне не раз приходилось от такой ф-ции избавляться переделывая старый код
Код
C++ (Qt)
void * AllocPtr( size_t size )
{
if (!size) return NULL;
char * ptr = (char *) malloc(size + 16);
if (!ptr) return NULL:
*(size_t *) ptr = size;
return ptr + 16;
}
 
voild FreePtr( void * ptr )
{
if (ptr) free((char *) ptr - 16);
}
 
size_t GetPtrSize( void * ptr)
{
return *(size_t *) ((char *) ptr - 16);
}
 
:)


Название: Re: Плюсолюбителям
Отправлено: PinkPanther от Март 16, 2015, 18:05
Перед тем, как требовать ответ на вопрос, следует разобраться, нужен ли ответ. Размер блока вообще знать не обязательно. Если программисту нужен размер блока, который он же выделяет, речь идет о слабом программисте, ущербном алгоритме и бесполезном приложении, потому что память выделяют под конкретные данные, а не "с запасом". Думаю, со временем функция выделения физической памяти останется у процессора, и доступ к таблице блоков будет ограничен. Выход за границы блока простых данных приведет к ошибке, и в 100% случаев это ошибка алгоритма (программиста).


Название: Re: Плюсолюбителям
Отправлено: AzazelloAV от Март 16, 2015, 20:13
Перед тем, как требовать ответ на вопрос, следует разобраться, нужен ли ответ. Размер блока вообще знать не обязательно. Если программисту нужен размер блока, который он же выделяет, речь идет о слабом программисте, ущербном алгоритме и бесполезном приложении, потому что память выделяют под конкретные данные, а не "с запасом". Думаю, со временем функция выделения физической памяти останется у процессора, и доступ к таблице блоков будет ограничен. Выход за границы блока простых данных приведет к ошибке, и в 100% случаев это ошибка алгоритма (программиста).

Ну уж. Как известно, операция выделения памяти затратная. А вас не интересовало никогда, с практической точки зрения, сколько памяти занимает объект? Например QObject (это всего лишь пример!).  Анализируя с помощью valgrind код, интересные вещи узнаёшь, о которых никогда бы не подумал, что там узкое место. А выделение сотни объектов (тривиальная задача, встречающаяся очень часто) не подлежит анализу на предмет выделения памяти лишь потому, что new/delete  от нас попрятались.

Да и память не плохо выделять с запасом иногда, блоками, что в этом плохого.  Что плохого, что QVector будет выделять память с запасом по 16К (подсознание выплюнуло), чем сотни вызовов выделения памяти.  На низком уровне ОС так и происходит (хотя, данное замечание здесь некорректно).


Название: Re: Плюсолюбителям
Отправлено: PinkPanther от Март 17, 2015, 01:46
Выделение "про запас" плохо не столько с технической точки зрения, сколько алогично: в коде, где память живет независимо от данных, легко запутаться, необходимо помнить о времени-месте возврата, и, к тому же, необходимо вводить счетчик, отделяющий полезную память буфера от бесполезной. На вопрос, почему буфер - 100 элементов, а не 7394, тоже может возникнуть, а значит, придется отвечать, если нет желания запоминать число 100. Такое решение говорит о недостаточно хорошо продуманном алгоритме (ошибке в подходе к данным, их размещению и обработке). Код должен оперировать только полезной информацией, а выделенная под нее память должна освобождаться сразу же, как только исчезает необходимость в обработке данных. Все остальное создает неоднозначности и коллизии. Если нас интересует размер объекта в байтах, этот интерес тоже должен иметь логическое продолжение, быть частью алгоритма.

Цитировать
А вас не интересовало никогда, с практической точки зрения, сколько памяти занимает объект? Например QObject (это всего лишь пример!).  Анализируя с помощью valgrind код, интересные вещи узнаёшь, о которых никогда бы не подумал, что там узкое место.

Нет. При высоких затратах я выигрываю в скорости разработки сносно работающей программы. Умственная лень и бабло победили добро, развратила дешевая RAM и гигагерцы. :) Qt - черный ящик, лезть внутрь нет желания. Но хочется потрогать кнопочки, чтобы представлять пределы фантазии создателей. Если мои проекты на Qt будут развиваться, и окажется, что программы с QObject жрут слишком много и не работают на нужных машинах, поинтересуюсь, сколько захватывают QObject, QVariant,... ужаснусь, напишу что-нибудь свое, на базе простых типов. Есть расчетные задачи, где нужно считать такты CPU, но построение GUI к ним не относятся. GUI сложен и строится один раз, а Qt - это, в первую очередь, GUI.

Учитывая потребность рынка софта за последние 25 лет, выгоднее создать системы программирования для фермеров, чем рассчитывать на узкую прослойку "программистов от бога", умеющих создавать безошибочные, логически стройные программы малыми средствами. Спрос на "правильный" софт остался, но он нишевой. Программы, написанные реднеками при помощи разных адских фреймворков дешевы, разнообразны, и удивляют необычными результатами. :D То, что каждую вторую программулину приходится удалять сразу после инсталляции, пользователей обычно не напрягает.

Этих проблем можно избежать, если пользоваться базовыми типами данных, либо типами данных, которые имеют четкие спецификации. В противном случае вы - заложник библиотеки, объекты которой могут не только занимать много места при создании, но и раздуваться, плодя буферы неизвестного размера... Сегодня считается, что риск оправдан (если вам нужно 100% рабочее приложение - не оправдан). Qt - любительская библиотека, хотя сегодня ее продают за деньги. Это преступление? Юридически - нет, логически - да. 8)


Название: Re: Плюсолюбителям
Отправлено: AzazelloAV от Март 17, 2015, 06:45
Нет. При высоких затратах я выигрываю в скорости разработки сносно работающей программы. Умственная лень и бабло победили добро, развратила дешевая RAM и гигагерцы. :)

Дешёвую RAM и мегагерцы засунули в одно место обычные батарейки. Абсолютно верное высказывание, но лет 6-7 назад.  Достаточно сравнить  Java и Objective-C.  Но это лирика. Существую задачи, где производительность GUI критична, в моем случае это векторная графика. И важность скорости разработки сильно преувеличина. Прям волны какие-то изменения трендов разработки. Вспомните, почему умер Delphi -  именно из за высокой скорости разработки. Так все научились формошлёпить (кому не лень), что среда приобрела статус "ненадёжной" абсолютно по субъективным причинам (а делфистов вообще за людей не считали)



Название: Re: Плюсолюбителям
Отправлено: Igors от Март 17, 2015, 11:22
А вас не интересовало никогда, с практической точки зрения, сколько памяти занимает объект? Например QObject (это всего лишь пример!).
Ну почему же никогда? Подсчитывали и на этом форуме (захотите найдете). Но в этом нет необходимости. Если QObject имеет мощный ф-ционал, значит он "жирный", это нормально, все чего-то стоит. Нормальный программист интуитивно/рефлекторно решает нужен ли такой мощный объект или нет.

Да и память не плохо выделять с запасом иногда, блоками, что в этом плохого.  Что плохого, что QVector будет выделять память с запасом по 16К (подсознание выплюнуло), чем сотни вызовов выделения памяти. 
А так все практически все контейнеры и делают (и QVector тоже), никто не выделяет на каждый чих


Название: Re: Плюсолюбителям
Отправлено: AzazelloAV от Март 18, 2015, 00:42
Что-то старожилы совсем опозорились в данном топике. Хоть топикстартер и пишет фигню по большей части, но здесь .....

Чисто интерес, про какую фигню вы говорите. Если нет желания, лучше не отвечайте, иначе про фигню более конкретно.


Название: Re: Плюсолюбителям
Отправлено: Авварон от Март 22, 2015, 01:03
Чисто интерес, про какую фигню вы говорите.
Соседний топик, где вы ноете про закрытость.


Название: Re: Плюсолюбителям
Отправлено: AzazelloAV от Март 25, 2015, 15:39
Чисто интерес, про какую фигню вы говорите.
Соседний топик, где вы ноете про закрытость.

Ну а чего не могу поныть то? Чем запрещается нытьё в нытной теме (говорилке). Тем более в соседней ветке. Вот вы поймите, я всегда не понимал людей (без обид), которые влазят в другие нытные темы, чтобы сказать, что они ноют. Т.е становятся участниками нытья. Ладно там в общественном месте каком, где эти разговоры доступны всем (всилу распростастронения звуковых волн), но тут что вас заставило? Мало того что зайти, так ещё и ответить. Прям присоединение к бабушкам на скамеечке. Но вы же на такой?

P.S. Нивкоем случае не хочу вас обидеть, также (на самом деле) считаю что на "бабушкиных скамеечках" можно выражать своё Я, но только осторожно, чтобы не обидеть других. А то "карга старая" каждый может бросить. :)


Название: Re: Плюсолюбителям
Отправлено: Авварон от Март 25, 2015, 16:23
Ну а чего не могу поныть то? Чем запрещается нытьё в нытной теме (говорилке). Тем более в соседней ветке. Вот вы поймите, я всегда не понимал людей (без обид), которые влазят в другие нытные темы, чтобы сказать, что они ноют. Т.е становятся участниками нытья. Ладно там в общественном месте каком, где эти разговоры доступны всем (всилу распростастронения звуковых волн), но тут что вас заставило? Мало того что зайти, так ещё и ответить. Прям присоединение к бабушкам на скамеечке. Но вы же на такой?

P.S. Нивкоем случае не хочу вас обидеть, также (на самом деле) считаю что на "бабушкиных скамеечках" можно выражать своё Я, но только осторожно, чтобы не обидеть других. А то "карга старая" каждый может бросить. :)

Ну вы же не по делу ноете:)


Название: Re: Плюсолюбителям
Отправлено: AzazelloAV от Март 26, 2015, 02:18
Ну вы же не по делу ноете:)

Не хотел отвечать, но не выдержал. Вы такой же нытик..... По какому делу вы сейчас проныли?