2015-05-15 3 views
4

Значение size_t значения виртуальной памяти, возвращаемое malloc(), имеет верхнюю границу?Имеет ли malloc() максимальное возвращаемое значение?

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

+1

У меня нет котировки, но я думаю, что это не указано. 'malloc' может вернуть все, что угодно. На практике это часто растет, и некоторые языки (OCaml) фактически делают то, что вы говорите безопасным способом. –

+0

что случилось с 'int64_t' или' uint64_t'? – pmg

+0

Это зависит от стратегии отображения памяти «OS» и потому, что стратегия - это детали реализации, она может меняться от одной версии «ОС» до следующей без предупреждения. Я не стал бы полагаться на такие хаки. – axiac

ответ

4

Как говорится в ответе @ datenwolf, вы не можете делать никаких предположений о том, как malloc предоставляет вам адрес памяти. MSB может содержать важные биты, которые вы могли бы перезаписать, если попытаетесь использовать их для хранения метаданных. Я работал над 32-разрядной системой, которая возвращала адреса с битами, установленными в MSB адресов (не от malloc, а других функций выделения памяти в системе).

Однако : гарантирует, что malloc вернет адрес, подходящий для вашей системы. Например, в 32-битной системе вы получите 4-байтовый выровненный указатель, а на 64-битном вы получите 8-байтовый выровненный указатель. Это означает, что вам гарантировано, что нижние 2 или 3 бита соответственно будет равным нулю. Вы можете увеличить количество гарантированных бит, используя вместо этого memalign. Это, по сути, тот же эффект, что и хранение метаданных в наиболее значимом бите. Чтобы получить/установить литерал, вы можете просто перевернуть его вниз в оставшиеся биты.

Однако я бы не предложил ни один из методов. Спасите себе некоторую душевную боль и выделите лишь немного больше памяти для хранения флага. Если у вас нет миллиардов, это действительно не стоит.

+0

Хорошо, что бы сделать трюк. Действительно, у меня их миллиарды, и я уже решил проблему, но мне было любопытно узнать больше о 'malloc()'. – ezorita

8

malloc возвращает void* не целое число. Выделение указателя на целое не дает вам адрес (виртуальной памяти), но некоторое значение, которое должно придерживаться семантики, как определено в стандарте языка C (0 для нулевого указателя и добавления и вычитания, связано с арифметикой указателя) , но это все.

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

0

Что касается size_t обеспокоен тем, что может содержать значение, заданное limits.h

#ifndef SIZE_MAX 
#ifdef _WIN64 
#define SIZE_MAX _UI64_MAX 
#else 
#define SIZE_MAX UINT_MAX 

Где _UI64_MAX и UINT_MAX определяются как followes.

#define UINT_MAX  0xffffffff /* maximum unsigned int value */ 
#define _UI64_MAX  0xffffffffffffffffui64 

И как для malloc() обеспокоен, на 32 битных Windows, он может возвращать любое значение (адрес) в пределах нуля до 2 Гб адресного пользовательского режима пространства, и на 64-битной Windows, он может возвращать любой (адрес) в пределах от 0 до 8 ТБ адресного пространства пользовательского режима.

Опять же, в 32-битной системе, начиная с WinNT 4, она представила опцию загрузки/3G. При этом malloc() может вернуть любое (адресное) значение в пределах от 0 до 3 ГБ адресного пространства пользовательского режима.

Подробнее см. Статью Марка Руссиновича here.

Смежные вопросы