Здравствуйте, df, Вы писали:
df>Добрый день!
df>Подскажите пожалуйста, существуют-ли способы узнать размер блока памяти выделяемой оператором new? df>Т.е. например
df>
df>int *p = new int[5];
df>
df>можно-ли узнать, что теперь скрывается за p? Если я передаю в функцию этот указатель, то могу-ли я узнать размер блока памяти на который указывает p?
нет нельзя.
Вместе с указателем надо передавать размер
Здравствуйте, korzhik, Вы писали:
df>>можно-ли узнать, что теперь скрывается за p? Если я передаю в функцию этот указатель, то могу-ли я узнать размер блока памяти на который указывает p?
K>нет нельзя. K>Вместе с указателем надо передавать размер
А еще лучше обернуть классом или исползовать чей нибудь готовый
Здравствуйте, df, Вы писали:
df>можно-ли узнать, что теперь скрывается за p? Если я передаю в функцию этот указатель, то могу-ли я узнать размер блока памяти на который указывает p?
Ну как бы это... Теоретически — да (имхо). Библиотеке CRT надо знать, сколько памяти она выделила, чтобы потом все корректно освободить. Соответственно, эту служебную информацию надо где-то хранить. Есть два подхода. Первый — это где-то во внутренних служебных структурах CRT, а второй — перед выделенным блоком по адресу (примерно так):
(char *)p - sizeof(size_t)
HgLab: Mercurial Server and Repository Management for Windows
df>>Подскажите пожалуйста, существуют-ли способы узнать размер блока памяти выделяемой оператором new? df>>Т.е. например
df>>
df>>int *p = new int[5];
df>>
df>>можно-ли узнать, что теперь скрывается за p? Если я передаю в функцию этот указатель, то могу-ли я узнать размер блока памяти на который указывает p?
K>нет нельзя.
Категорически?
А как delete[] p; работает? Он-то как-то узнает размер блока, или для программиста это криминал?
K>Вместе с указателем надо передавать размер
Эт да.
Здравствуйте, df, Вы писали:
df>>>можно-ли узнать, что теперь скрывается за p? Если я передаю в функцию этот указатель, то могу-ли я узнать размер блока памяти на который указывает p?
K>>нет нельзя.
df>Категорически?
df>А как delete[] p; работает? Он-то как-то узнает размер блока, или для программиста это криминал?
Криминал. Зато не является криминалом использование std::vector
Здравствуйте, Нахлобуч, Вы писали:
Н>Здравствуйте, df, Вы писали:
df>>можно-ли узнать, что теперь скрывается за p? Если я передаю в функцию этот указатель, то могу-ли я узнать размер блока памяти на который указывает p?
Н>Ну как бы это... Теоретически — да (имхо). Библиотеке CRT надо знать, сколько памяти она выделила, чтобы потом все корректно освободить.
Однозначно, надо знать. Вопрос в том возможно-ли это использовать (как delete[]) или это порочный путь.
Вопрос между тем, не совсем праздный. Ковыряюсь в старом проекте, который писался много лет, многими людьми, там такое понаворочено, что не хочется переделывать функции (в плане передачи параметров) ибо это за собой много чего тянет
Здравствуйте, Нахлобуч, Вы писали:
Н>Ну как бы это... Теоретически — да (имхо). Библиотеке CRT надо знать, сколько памяти она выделила, чтобы потом все корректно освободить. Соответственно, эту служебную информацию надо где-то хранить. Есть два подхода. Первый — это где-то во внутренних служебных структурах CRT, а второй — перед выделенным блоком по адресу (примерно так): Н>
Н>(char *)p - sizeof(size_t)
Н>
Не забывайте, что у кучи есть гранулярность. То есть, попросил 4 байта, а она тебе вручила 16.
Впрочем, чтобы не зависеть от дефолтной кучи — можно написать свой менеджер памяти (перегрузить operator new, operator delete и похимичить с макросами).
Но инструкции new[]/delete[] (не операторы, а именно statement'ы) вдобавок к памяти, нужной для массива, подвёрстывают свою информацию о количестве элементов. Причём не всегда, а только если у типа есть нетривиальный деструктор.
Поэтому заниматься хаком и добывать размер массива обиняками — занятие бестолковое.
Лучше пользоваться обёртками массивов — тем же std::vector, например.
Здравствуйте, Вадим Никулин, Вы писали:
ВН>Здравствуйте, df, Вы писали:
df>>>>можно-ли узнать, что теперь скрывается за p? Если я передаю в функцию этот указатель, то могу-ли я узнать размер блока памяти на который указывает p?
df>>А как delete[] p; работает? Он-то как-то узнает размер блока, или для программиста это криминал? ВН>Криминал. Зато не является криминалом использование std::vector ;)
Предполагал я такие ответы, хотя грустно... как я уже отвечал человеку
"в старом проекте, который писался много лет, многими людьми, там такое понаворочено, что не хочется переделывать функции (в плане передачи параметров) ибо это за собой много чего тянет..."
Здравствуйте, Кодт, Вы писали:
К>Но инструкции new[]/delete[] (не операторы, а именно statement'ы) вдобавок к памяти, нужной для массива, подвёрстывают свою информацию о количестве элементов. Причём не всегда, а только если у типа есть нетривиальный деструктор.
А можно определение "{не}тривиального деструктора"? Чтобы на будущее, так сказать...
HgLab: Mercurial Server and Repository Management for Windows
К>Не забывайте, что у кучи есть гранулярность. То есть, попросил 4 байта, а она тебе вручила 16. К>Впрочем, чтобы не зависеть от дефолтной кучи — можно написать свой менеджер памяти (перегрузить operator new, operator delete и похимичить с макросами). К>Но инструкции new[]/delete[] (не операторы, а именно statement'ы) вдобавок к памяти, нужной для массива, подвёрстывают свою информацию о количестве элементов. Причём не всегда, а только если у типа есть нетривиальный деструктор. К>Поэтому заниматься хаком и добывать размер массива обиняками — занятие бестолковое.
Все.... похоронили....
Ok, а если простые типы: char, int? все равно никак?
К>Лучше пользоваться обёртками массивов — тем же std::vector, например.
Лучше, но все уже написано до меня. Мне нужно только кое-чего изменить, отсюда соблазн минимизировать....
Здравствуйте, Нахлобуч, Вы писали:
Н>А можно определение "{не}тривиального деструктора"? Чтобы на будущее, так сказать...
Стандарт (12.4.3)
Деструктор тривиальный, если
— он неявный (т.е. нет объявления); в частности, у всех POD-типов деструкторы тривиальные
— и у всех членов и баз тривиальные деструкторы
Т.е., если в деструкторе проводится какая-то работа (пусть даже {}) — он нетривиальный.
Здравствуйте, Нахлобуч, Вы писали:
Н>А можно определение "{не}тривиального деструктора"? Чтобы на будущее, так сказать...
Да пожалуйста:
12.4
...
3 If a class has no user declared
destructor, a destructor is declared implicitly. An implicitly declared
destructor is an inline public member of its class. A destructor is
trivial if it is an implicitlydeclared destructor and if:
— all of the direct base classes of its class have trivial destructors and
— for all of the nonstatic data members of its class that are of class type
(or array thereof), each such class has a trivial destructor.
4 Otherwise, the destructor is nontrivial.
...
Здравствуйте, df, Вы писали:
df>ПС: а почему это криминал?
Потом operator delete или new перегрузишь (лет через 10 кодинга или твой коллега), знаешь сколько ошибок словить можно будет? Да дурно это, какая-то не здоровая весчь.
К>Но инструкции new[]/delete[] (не операторы, а именно statement'ы) вдобавок к памяти, нужной для массива, подвёрстывают свою информацию о количестве элементов. Причём не всегда, а только если у типа есть нетривиальный деструктор.
Кстати. Может узнать количество элементов будет вполне достаточно, тип известен, реально?
Здравствуйте, df, Вы писали:
К>>Лучше пользоваться обёртками массивов — тем же std::vector, например.
df>Лучше, но все уже написано до меня. Мне нужно только кое-чего изменить, отсюда соблазн минимизировать....
Мышиная возня с голыми типами (в частности, с указателями) — обычно к добру не приводит.
В лучшем случае оттягиваешь рефакторинг... особенно, если проект большой.
Можно выполнить "кровавый рефакторинг", заменив голый указатель умным. Компилятор быстро покажет, где фигурируют твои типы — один день потеряешь, зато потом за час долетишь.
Здравствуйте, Кодт, Вы писали:
К>Здравствуйте, df, Вы писали:
К>>>Лучше пользоваться обёртками массивов — тем же std::vector, например.
df>>Лучше, но все уже написано до меня. Мне нужно только кое-чего изменить, отсюда соблазн минимизировать....
К>Мышиная возня с голыми типами (в частности, с указателями) — обычно к добру не приводит. К>В лучшем случае оттягиваешь рефакторинг... особенно, если проект большой.
К>Можно выполнить "кровавый рефакторинг", заменив голый указатель умным. Компилятор быстро покажет, где фигурируют твои типы — один день потеряешь, зато потом за час долетишь.
Как в воду глядишь Похоже все к этому и идет. А сейчас все на дирижаблей (концерт Роберта Планта в Питере через час)
Здравствуйте, df, Вы писали:
df>Вопрос между тем, не совсем праздный. Ковыряюсь в старом проекте, который писался много лет, многими людьми, там такое понаворочено, что не хочется переделывать функции (в плане передачи параметров) ибо это за собой много чего тянет
Показывай код, рассказывай в чём проблема, может чего придумаем коллективным разумом.
Здравствуйте, Кодт, Вы писали:
К>Здравствуйте, Нахлобуч, Вы писали:
Н>>Ну как бы это... Теоретически — да (имхо). Библиотеке CRT надо знать, сколько памяти она выделила, чтобы потом все корректно освободить. Соответственно, эту служебную информацию надо где-то хранить. Есть два подхода. Первый — это где-то во внутренних служебных структурах CRT, а второй — перед выделенным блоком по адресу (примерно так): Н>>
Н>>(char *)p - sizeof(size_t)
Н>>
К>Не забывайте, что у кучи есть гранулярность. То есть, попросил 4 байта, а она тебе вручила 16. К>Впрочем, чтобы не зависеть от дефолтной кучи — можно написать свой менеджер памяти (перегрузить operator new, operator delete и похимичить с макросами). К>Но инструкции new[]/delete[] (не операторы, а именно statement'ы) вдобавок к памяти, нужной для массива, подвёрстывают свою информацию о количестве элементов. Причём не всегда, а только если у типа есть нетривиальный деструктор. К>Поэтому заниматься хаком и добывать размер массива обиняками — занятие бестолковое.
К>Лучше пользоваться обёртками массивов — тем же std::vector, например.
Про библиотеку CRT можно говорить только применительно к конкретной реализации конкретным производителем для конкретной платформы.
Знание библиотеки не дает даже надежды, что при портировании кода даже не другую операционку, а под другую версию компилятора, Вы не наступите на грабли.
Также язык С++ не обесчает, что оператор new выделит память на куче. Что если этой самой кучи вообще нет? И уж о гранулярности тем более вопрос настолько не корректный, что упоминания про 16 байт не имеет право на жизнь.
Из примера
int *p = new int[5];
можно сказать, что ты получишь не меньше 5 элементов типа int, если p не нулевой.
Здравствуйте, korzhik, Вы писали:
K>Здравствуйте, df, Вы писали:
df>>Вопрос между тем, не совсем праздный. Ковыряюсь в старом проекте, который писался много лет, многими людьми, там такое понаворочено, что не хочется переделывать функции (в плане передачи параметров) ибо это за собой много чего тянет
K>Показывай код, рассказывай в чём проблема, может чего придумаем коллективным разумом.
Ну хорошо. Может в самом деле чего придумаем. Весь код показывать не имеет смысла, решит кто-нибудь, что это я такое понаписал, во век потом не отмоюсь. Стыдно и страшно там :(.
В качестве подтверждения:
int FDescr=_open(LocalFileName.operator LPCTSTR(), _O_BINARY|_O_RDONLY);
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
как вам такое, а? Вот то-то... :( Есть и другая жуть...
Ладно это все лирика... Далее если коротко так:
p = new char[lFileLength];
далее этот р передается в функцию (пусть будет FNet()) в которой работает NetAgent. Он принимает этот указатель вкачестве параметра и отправляет данные, скажем, на сервер. Так же для работы Нетагенту нужна lFileLength. FNet() исполняется в потоке, поэтому сделано так, что она принимает this в качестве параметра.
В проекте близнеце lFileLength передается через член класса, что, мне кажется, не хорошо, поскольку он, этот член класса, служит только как средство подобной передачи параметра и ничего более.
Какое может быть решение? Я не очень понимаю как можно использовать вектор в этом случае...
Не выпендриваться, оставить все как есть?