Здравствуйте, 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 передается через член класса, что, мне кажется, не хорошо, поскольку он, этот член класса, служит только как средство подобной передачи параметра и ничего более.
Какое может быть решение? Я не очень понимаю как можно использовать вектор в этом случае...
Не выпендриваться, оставить все как есть?
Здравствуйте, Ellin, Вы писали:
E>Здравствуйте, df, Вы писали:
df>>ПС: а почему это криминал?
E>Потом operator delete или new перегрузишь (лет через 10 кодинга или твой коллега), знаешь сколько ошибок словить можно будет? Да дурно это, какая-то не здоровая весчь.
Все еще хуже. Насколько я понимаю, размер выделенной памяти может храниться по-разному для разных компиляторов.
Здравствуйте, Murom, Вы писали:
К>>Не забывайте, что у кучи есть гранулярность. То есть, попросил 4 байта, а она тебе вручила 16. К>>Впрочем, чтобы не зависеть от дефолтной кучи — можно написать свой менеджер памяти (перегрузить operator new, operator delete и похимичить с макросами). К>>Но инструкции new[]/delete[] (не операторы, а именно statement'ы) вдобавок к памяти, нужной для массива, подвёрстывают свою информацию о количестве элементов. Причём не всегда, а только если у типа есть нетривиальный деструктор. К>>Поэтому заниматься хаком и добывать размер массива обиняками — занятие бестолковое.
К>>Лучше пользоваться обёртками массивов — тем же std::vector, например.
M>Про библиотеку CRT можно говорить только применительно к конкретной реализации конкретным производителем для конкретной платформы. M>Знание библиотеки не дает даже надежды, что при портировании кода даже не другую операционку, а под другую версию компилятора, Вы не наступите на грабли.
Если не заниматься хаками, то надежда будет оправдана.
M>Также язык С++ не обесчает, что оператор new выделит память на куче. Что если этой самой кучи вообще нет? И уж о гранулярности тем более вопрос настолько не корректный, что упоминания про 16 байт не имеет право на жизнь.
Упоминание — это к тому, чтобы не пользоваться CRT'шными функциями типа _msize() (MS-specific) и т.п.
M>Из примера
int *p = new int[5];
можно сказать, что ты получишь не меньше 5 элементов типа int, если p не нулевой.
Получишь ровно 5 плюс вагон или маленькую тележку мусора.
Здравствуйте, Кодт, Вы писали:
К>Здравствуйте, Murom, Вы писали:
К>>>Лучше пользоваться обёртками массивов — тем же std::vector, например.
К>Упоминание — это к тому, чтобы не пользоваться CRT'шными функциями типа _msize() (MS-specific) и т.п.
Честно говоря, сначало было желание воспользоваться _msize... но вы так настойчиво отговариваете...
Николай, а какой контейнер вы посоветуете в связи со следующим:
Пусть:
p = new char[lFileLength];
далее этот р передается в функцию (пусть будет FNet()) в которой работает NetAgent. Он принимает этот указатель вкачестве параметра и отправляет данные, скажем, на сервер. Так же для работы Нетагенту нужна lFileLength. FNet() исполняется в потоке, поэтому сделано так, что она принимает this в качестве параметра.
В проекте близнеце lFileLength передается через член класса, что, мне кажется, не хорошо, поскольку он, этот член класса, служит только как средство подобной передачи параметра и ничего более.
Какое может быть решение? Я не очень понимаю как можно использовать вектор в этом случае...
Я не очень хорошо знаю STL сейчас буду читать MSDN про <new> и <memory>
Здравствуйте, df, Вы писали:
K>>Показывай код, рассказывай в чём проблема, может чего придумаем коллективным разумом.
df>Ну хорошо. Может в самом деле чего придумаем. Весь код показывать не имеет смысла, решит кто-нибудь, что это я такое понаписал, во век потом не отмоюсь. Стыдно и страшно там . df>В качестве подтверждения:
df>
df>как вам такое, а? Вот то-то... Есть и другая жуть... df>Ладно это все лирика... Далее если коротко так:
df>
df>p = new char[lFileLength];
df>
df>далее этот р передается в функцию (пусть будет FNet()) в которой работает NetAgent. Он принимает этот указатель вкачестве параметра и отправляет данные, скажем, на сервер. Так же для работы Нетагенту нужна lFileLength. FNet() исполняется в потоке, поэтому сделано так, что она принимает this в качестве параметра. df> В проекте близнеце lFileLength передается через член класса, что, мне кажется, не хорошо, поскольку он, этот член класса, служит только как средство подобной передачи параметра и ничего более. df> Какое может быть решение? Я не очень понимаю как можно использовать вектор в этом случае... df> Не выпендриваться, оставить все как есть?
Как мрачно... А просто использовать строки (std::string, MFC CString) нельзя?
df>>далее этот р передается в функцию (пусть будет FNet()) в которой работает NetAgent. Он принимает этот указатель вкачестве параметра и отправляет данные, скажем, на сервер. Так же для работы Нетагенту нужна lFileLength. FNet() исполняется в потоке, поэтому сделано так, что она принимает this в качестве параметра. df>> В проекте близнеце lFileLength передается через член класса, что, мне кажется, не хорошо, поскольку он, этот член класса, служит только как средство подобной передачи параметра и ничего более.
df>> Какое может быть решение? Я не очень понимаю как можно использовать вектор в этом случае... df>> Не выпендриваться, оставить все как есть?
К>Как мрачно... А просто использовать строки (std::string, MFC CString) нельзя?
Здравствуйте, df, Вы писали:
К>>Как мрачно... А просто использовать строки (std::string, MFC CString) нельзя?
df>Да можно, наверное... но там ведь как:
df>
df>а далее см. выше, примерную существующую логику я описал...
df>может все-таки calloc и _msize?
_msize возвращает не размер массива, а размер блока памяти, выданного под массив.
_msize(malloc(10)) > 10.
df>или контейнер <memory>... сейчас пытаюсь с ним разобраться... df>или какой другой...
vector<char> ?
И передавай его по ссылке, чтобы копированием не заниматься без нужды.
Здравствуйте, BacCM, Вы писали:
BCM>Здравствуйте, korzhik, Вы писали:
df>>>можно-ли узнать, что теперь скрывается за p? Если я передаю в функцию этот указатель, то могу-ли я узнать размер блока памяти на который указывает p?
K>>нет нельзя. K>>Вместе с указателем надо передавать размер
BCM>А еще лучше обернуть классом или исползовать чей нибудь готовый
Наприме ртут моожно сделать одно маленькое упрощение. так как тебе размер заране известен — сколько выделить, то можно написать так
FDescr=_open(LocalFileName, _O_BINARY|_O_RDONLY);
...
FLength=_filelength(FDescr);
...
std::vector<char> FileBuff(FLength);
FileBuff.resize( FLength ); //застолбили память
_read(FDescr, &FileBuff[0], FLength); //так как элементы вектора расположены неприрывно, то можно получить адрес начала блока памяти
...
Ну а дальше уже вместо указателя на массив можно например передавать ссылку на этот вектор — конечно код, который эти указатели пользовал раньше придется малось подправить
G>FDescr=_open(LocalFileName, _O_BINARY|_O_RDONLY);
G>...
G>FLength=_filelength(FDescr);
G>...
G>std::vector<char> FileBuff(FLength);
G>FileBuff.resize( FLength ); //застолбили память
G>_read(FDescr, &FileBuff[0], FLength); //так как элементы вектора расположены неприрывно, то можно получить адрес начала блока памяти
G>...
G> — конечно код, который эти указатели пользовал раньше придется малось подправить :)
G>_read(FDescr, &FileBuff[0], FLength); //_если это сработает - будет гуд!_
std::vector<char> FileBuff(FLength);
А после _такого_ создания вектор обязательно ресайзить нужно? Разве память не выделяется сразу? Зачем тогда размер указываем?
В msdn об этом ничего не нашел :shuffle:
Здравствуйте, ansi, Вы писали:
BCM>>А еще лучше обернуть классом или исползовать чей нибудь готовый A>Начинается... Почему лучше?
Потому что так в программе разделяются уровни функционирования. Все задачи, скажем, по управлению блоком памяти — сосредоточены в классе my_block_of_memory, а задачи использования этой памяти — в клиентском коде.
Иначе есть огромное искушение проинлайнить этот низкоуровневый код руками. А через дельта-тэ мы имеем не программу, а спагетти.
Эволюция работы с динамическими объектами выглядит примерно так:
1) В пределах одного объекта или одной функции: создали, поковыряли, удалили
2) Создали; передали в функцию {там поковыряли}; удалили
3) Создали; поковыряли; отдали в функцию [запомнили: она владеет] {там ещё попередавали и удалили}
4) Изобрели велосипед по контролю владения; создали, инициализировали владение; передали в функцию; чего-то забыли, владение расщепилось; дважды удалили, UB.
5) Исправили, всюду по коду расставили проверки — через месяц смотришь: а что это здесь понаписано?
6) Решили чуток переделать управление объектом; еле-еле нашли все вхождения, творчески переработали, накосячили, упало.
7) Исправили косяки, всё работает, ан нет — в дальнем углу ещё с п.5 чего-то осталось, а то и с п.3.
Здравствуйте, Кодт, Вы писали:
BCM>>>А еще лучше обернуть классом или исползовать чей нибудь готовый A>>Начинается... Почему лучше?
К>Потому что так в программе разделяются уровни функционирования. Все задачи, скажем, по управлению блоком памяти — сосредоточены в классе my_block_of_memory, а задачи использования этой памяти — в клиентском коде. К>Иначе есть огромное искушение проинлайнить этот низкоуровневый код руками. А через дельта-тэ мы имеем не программу, а спагетти.
К>Эволюция работы с динамическими объектами выглядит примерно так:
К>1) В пределах одного объекта или одной функции: создали, поковыряли, удалили К>2) Создали; передали в функцию {там поковыряли}; удалили К>3) Создали; поковыряли; отдали в функцию [запомнили: она владеет] {там ещё попередавали и удалили} К>4) Изобрели велосипед по контролю владения; создали, инициализировали владение; передали в функцию; чего-то забыли, владение расщепилось; дважды удалили, UB. К>5) Исправили, всюду по коду расставили проверки — через месяц смотришь: а что это здесь понаписано? К>6) Решили чуток переделать управление объектом; еле-еле нашли все вхождения, творчески переработали, накосячили, упало. К>7) Исправили косяки, всё работает, ан нет — в дальнем углу ещё с п.5 чего-то осталось, а то и с п.3.
Эволюция забавная конечно, но реально это дело должно учитываться еще при проектиронии. У нас вот 300 Мб исходников и все на Си... Проблем с управлением памятью, ну не то, чтобы не было, но я видел только один баг, связанный с утечкой. Вобщем все четко регламентировано, кто, что и куда передает и кто, где и когда освобождает.
Я в принципе не говорю, что обертками не надо пользоваться, просто не стоит, на мой взгляд, в крайности бросаться и совать их, где им не самое место. В принципе, работа с памятью очевидна, а реализация обертки...кто его знает.
new RSDN@Home(1.1.4, 303) << new Message(); std::head::ear << "Celtic Angels — Angels Sea";
df>Ладно это все лирика... Далее если коротко так:
df>
df>p = new char[lFileLength];
df>
df>далее этот р передается в функцию (пусть будет FNet()) в которой работает NetAgent. Он принимает этот указатель вкачестве параметра и отправляет данные, скажем, на сервер. Так же для работы Нетагенту нужна lFileLength. FNet() исполняется в потоке, поэтому сделано так, что она принимает this в качестве параметра. df> В проекте близнеце lFileLength передается через член класса, что, мне кажется, не хорошо, поскольку он, этот член класса, служит только как средство подобной передачи параметра и ничего более. df> Какое может быть решение? Я не очень понимаю как можно использовать вектор в этом случае... df> Не выпендриваться, оставить все как есть?
Если код совсем мрачный и трогать его совсем не хочется, то можно предложить решение а-ля BSTR. Т.е. типа такого:
size_t lFileLength = ...;
p = new char[lFileLength + sizeof(size_t)];
*(reinterpret_cast< size_t* >(p)) = lFileLength;
Foo(p);
А в Foo() написать типа этого:
void Foo(char* _p) {
size_t Size = *(reinterpret_cast< size_t* >(p));
char* p = _p + sizeof(size_t);
// Далее пользуем p как и раньше без изменений
}
Решение не очень хорошее, но иногда самое простое.
_msize
Returns the size of a memory block allocated in the heap.
size_t _msize( void *memblock );
Parameter
— memblock
Pointer to memory block Libraries
All versions of the C run-time libraries.
Return Value
_msize returns the size (in bytes) as an unsigned integer.
Remarks
The _msize function returns the size, in bytes, of the memory block allocated by a call to malloc, or realloc.
When the application is linked with a debug version of the C run-time libraries, _msize resolves to _msize_dbg. For more information about how the heap is managed during the debugging process, see Using C Run-Time Library Debugging Support.
Здравствуйте, Chez, Вы писали:
C>Remarks C>The _msize function returns the size, in bytes, of the memory block allocated by a call to malloc, or realloc.
Обрати внимание: size of the block allocated by a call. Но не сказано, что размер этого блока равен заказанному размеру.
Об этом же говорится в справке по malloc
Allocates memory blocks.
void *malloc(
size_t size
);
Parameter size
Bytes to allocate.
Return Value
malloc returns a void pointer to the allocated space, or NULL if there is insufficient memory available. To return a pointer to a type other than void, use a type cast on the return value. The storage space pointed to by the return value is guaranteed to be suitably aligned for storage of any type of object. If size is 0, malloc allocates a zero-length item in the heap and returns a valid pointer to that item. Always check the return from malloc, even if the amount of memory requested is small.
Remarks
The malloc function allocates a memory block of at leastsize bytes. The block may be larger than size bytes because of space required for alignment and maintenance information.