У меня есть этот фрагмент кода
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
int main(){
void *a, *b;
a = malloc(16);
b = malloc(16);
printf("\n block size (for a): %p-%p : %li", b, a, b-a);
a = malloc(1024);
b = malloc(1024);
printf("\n block size (for a): %p-%p : %li", b, a, b-a);
}
Разве это не должно печатать последний выделенный размер блока (16 или 1024)? Вместо этого он печатает 24 и 1032, поэтому объем выделенной памяти, кажется, имеет 8 дополнительных байтов.
Моя проблема в том, что (до создания этого тестового примера) я выполняю malloc() в функции (1024 байта) и возвращаю выделенный результат. При проверке размера блока при возврате функции я получаю 516 блоков ... и я не понимаю почему. Я предполагаю, что это может быть причиной повреждения памяти, которое происходит после некоторой обработки выделенных буферов :)
Редактировать: Я видел Как я могу получить размер массива из указателя в C? и, кажется, спрашивает то же самое, извините за репост.
Я переделал свой пример в свой более конкретный код:
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
short int * mallocStuff(long int number, short int base){
short int *array;
int size=1024;
array=(short int*)calloc(1,size);
//array=(short int*)malloc(size);
return array;
}
int main(){
short int **translatedArray;
translatedArray=malloc(4*sizeof(short int));
int i;
for(i=0;i<4;i++){
translatedArray[i]=mallocStuff(0,0);
if (i>0)
printf("\n block size (for a): %p-%p : %i",
translatedArray[i], translatedArray[i-1], translatedArray[i]-translatedArray[i-1]);
}
return 0;
}
И на выходе
block size (for a): 0x804a420-0x804a018 : 516
block size (for a): 0x804a828-0x804a420 : 516
block size (for a): 0x804ac30-0x804a828 : 516
Согласно вышеупомянутому сообщению, это больше 1024. Я ошибаюсь?





Перед указателем стоит размер следующего массива, который представляет собой 32- или 64-битное целое число (не знаю, со знаком или без знака)
Функция malloc всегда выделяет немного больше, чем вы запрашиваете, для хранения некоторой бухгалтерской информации. В конце концов, когда вы вызываете free(), он должен знать, насколько велик блок.
Кроме того, обычно реализации malloc округляют запрошенный размер до следующего кратного 8 или 16 или некоторого другого числа округления.
Обновлять: Настоящий ответ на ваш вопрос заключается в использовании вами типа short int. При выполнении арифметики указателя (вычитания) между типизированными указателями C и C++ возвращают разницу в номер вещей, на которые указывает. Поскольку вы указываете на short int, размер которого составляет два байта, возвращаемое значение составляет половину ожидаемого.
С другой стороны, malloc всегда выделяет заданное количество байты, независимо от того, к какому результату вы приведете результат позже. Попробуй это:
array=(short int*)malloc(sizeof(short int) * size);
malloc() будет иметь собственные накладные расходы.
Не говоря уже о том, что нет никакой гарантии, что 2 последовательных выделения с самого начала будут рядом друг с другом.
Во-первых, Malloc не дает никаких гарантий, что два последовательных вызова malloc вернут последовательные указатели.
Во-вторых, в зависимости от вашей конкретной архитектуры применяются разные правила выравнивания; иногда вы можете запросить один байт, но архитектура предпочитает распределение с 8- или 4-байтовыми интервалами.
В-третьих, malloc требует дополнительных затрат, чтобы запомнить размер выделенного блока и т. д.
Не делайте предположений о том, что делает malloc, помимо того, что написано в документации!
Если malloc возвращает что-либо, кроме нуля, тогда память, выделенная для него для вашей программы, имеет размер, который вы передали в malloc. Принятие разницы указателей между возвращаемыми значениями двух разностных вызовов malloc может иметь любое значение и не имеет ничего общего (ну очень мало) с размером блока первого выделенного блока.
Нет никаких гарантий, что два вызова malloc вернут блоки, точно упакованные вместе - на самом деле нет никаких гарантий относительно результата, за исключением того, что если он не NULL, он будет указывать на блок размером не менее запрошенного.
Внутри большинство маллоков содержат рабочие данные, которые помогают им управлять кучей. Например, эти 8 байтов могут содержать два указателя - один указывает на следующий блок, а другой указывает на предыдущий блок. Я не знаю, что это за 8 байтов, потому что вы не упомянули, на какой ОС вы работаете, но для malloc совершенно нормально использовать некоторую память для себя за кулисами.
Некоторые распределители (например, в Windows) предоставляют библиотечную функцию для определения размера блока по указателю, однако некоторые этого не делают, поскольку это довольно эзотерическая функция.
Выравнивание тоже в какой-то степени гарантировано, если я правильно помню.
И вы гарантированно получите по меньшей мере столько, сколько вы просите, если вызов завершится успешно.
Скорее всего, это будет размер и указатель на следующий или предыдущий блок.
То, что возвращает malloc, зависит от реализации malloc и архитектуры. Как уже говорили другие, вы гарантированно получите как минимум запрошенный объем памяти или NULL. Вот почему иногда вы можете записать за конец массива и не получить ошибку сегментации. Это потому, что у вас действительно есть действительный доступ к этой памяти, вы просто не знали об этом.
malloc () обычно реализуется путем разделения доступной кучи на куски различного размера. В вашем случае malloc () возвращает 2 последовательных блока по 1024 (или 16) байтов. Указанное вами 8-байтовое пространство используется malloc () для бухгалтерской информации.
См. Примечания Дуга Ли malloc () impl здесь, чтобы понять, что происходит за кулисами: http://g.oswego.edu/dl/html/malloc.html
У вас ошибка. Вместо:
translatedArray=malloc(4*sizeof(short int));
У вас должно быть
translatedArray=malloc(4*sizeof(short int*));
Обратите внимание на отсутствующий указатель в вашем коде. Я подозреваю, что отсюда и проистекает ваше наблюдаемое поведение.
Также обратите внимание, что 0x804a420 - 0x804a018 = 1032, а не 516. Формула translatedArray[i] - translatedArray[i - 1] дает вам количество элементы (короткие целые числа или, проще говоря, коротких замыканий) между двумя адресами, а не количество байты.
нет, у меня такие же размеры блоков ... но я думаю, что вы правы насчет отсутствующего символа '*'
Я нашел это ... и проверьте ссылку ниже для получения дополнительной информации.
Блок выделяется из свободного пула путем преобразования запрошенных байтов в индекс в массиве корзины, используя следующее уравнение:
необходимо = запрошено + 8
При необходимости <= 16, тогда ведро = 0
При необходимости> 16, тогда bucket = (log (необходимо) / log (2) с округлением до ближайшего целого числа) - 3
Размер каждого блока в списке, привязанном к сегменту, равен размеру блока = 2 сегмента + 4. Если список в сегменте равен нулю, память выделяется с помощью подпрограммы sbrk для добавления блоков в список. Если размер блока меньше страницы, то страница выделяется с помощью подпрограммы sbrk, и количество блоков, полученных путем деления размера блока на размер страницы, добавляется в список. Если размер блока равен или больше страницы, необходимая память выделяется с помощью подпрограммы sbrk, и один блок добавляется в список свободных для корзины. Если список свободных номеров не пуст, вызывающему абоненту возвращается блок во главе списка. Следующий блок в списке становится новым главой.
Обратите внимание, что ссылка предназначена для AIX, который может использовать совершенно другой malloc, чем glibc в Linux. Фактически, klibc, ulibc и любые другие библиотеки могут использовать разные методы. Большинство libc также позволяют программному обеспечению переопределять malloc по умолчанию.
так что объем выделенной памяти, кажется, имеет 8 дополнительных байтов? Реализация malloc() в вашей системе, кажется, выделяет дополнительные байты для поддержки информации метаданных, например, размер раздела кучи, начальный адрес и т. д. Информацию.
Хотя это зависит от разных платформ.
В моих системах X86 malloc() выделяет минимум 17 байтов, даже если я запрашиваю malloc(0).
int main(void) {
int *p = malloc(0);
if (p == NULL) {
/* error handling */
}
printf("%d\n",p[-1]);/ *it prints 17 bytes */
/* some code */
return 0;
}
malloc () может выделять непрерывную память, но когда вы вызываете malloc () 2 раза и не можете ожидать, что выделенная память будет смежной, вычитая два указателя variabls ...
Однако выделенная память - это виртуальная память, которая является частью реализации ядра, а точнее управления памятью (VFS). Это не может повлиять на работу приложения.
предположения рано или поздно доставят вам неприятности