Память (sbrk) 16-байтовый выровненный сдвиг при доступе к указателю

Я написал достаточно простой распределитель памяти, используя sbrk. Я прошу кусок памяти, скажем, 65 КБ, и разделяю его по мере необходимости для переменных, запрашивающих динамическую память. Я освобождаю память, добавляя ее обратно в блок 65k. Блок размером 65 КБ получается из объединения sizeof(16 байт). Затем я выравниваю блок по ровной 16-байтовой границе. Но я получаю необычное поведение.

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

Например, реальный адрес этого конкретного члена: 0x100313d50, но при выполнении определенной функции (ничего особенного) адрес члена представляется как 0x100313d70. Внутри отладчика я могу запросить реальный адрес, и он кажется правильным, когда он находится внутри функции, в которой это проявляется. Это не первый доступ к члену, это третий, поэтому два предыдущих доступа к памяти в порядке, но во время третьего доступа я вижу это необычное смещение.

Возможно ли, что я обращаюсь к этой памяти через смещенный блок? Это возможно, но я ожидаю, что возникнет исключение SIGBUS (микросхема SPARC). Я компилирую с использованием -memalign=16s, поэтому он должен использовать SIGBUS, а не перехватывать и исправлять смещение.

Все мои структуры дополнены кратным 16 байтам: sizeof(structure)%16 = 0. Кто-нибудь сталкивался с таким поведением? Вообще говоря, какие вещи/вещи/и т.д. может привести к тому, что указатель исказит адрес памяти?

Здоровья, Трейси.

Solaris 10, SunStudio-12, язык C на современном процессоре SPARC (если это поможет).


person tracy.brown    schedule 23.09.2009    source источник
comment
Я только что попытался использовать malloc вместо sbrk, и поведение такое же.   -  person tracy.brown    schedule 23.09.2009
comment
Ну, не похоже, что это связано с моим распределителем памяти. Я заменил все свои запросы динамической памяти простым старым malloc и free с тем же поведением (другое место в памяти), но с тем же нечетным смещением указателя на тот же элемент структуры.   -  person tracy.brown    schedule 23.09.2009


Ответы (1)


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

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

Простыми словами, я написал за пределы своего буфера. Поскольку я раздаю память из хвоста, перезапись снесет мой столь необходимый мета-адрес для моей глобальной структуры (или чего-то еще). Теперь я знаю, как выглядит неопределенное поведение.

person tracy.brown    schedule 23.09.2009
comment
если быть точным, вы знаете, как выглядит один пример неопределенного поведения. там еще может быть миллион других ;) - person Mikeage; 23.11.2009
comment
+1 за последнее предложение. @Mikeage: я думаю, что OP имел в виду то, как выглядит неопределенное поведение, как весь опыт попытки отследить неожиданное и труднообъяснимое поведение программы. - person R.. GitHub STOP HELPING ICE; 16.07.2011
comment
Похоже, у вас есть адрес управляющей структуры для вашего распределителя памяти, хранящийся непосредственно перед каждым выделением, поэтому вызов для освобождения памяти может найти эту структуру? Если это так, альтернативой, которую я использую, является выравнивание всей страницы по границе 64 КБ. Затем, если мне нужно освободить выделение, я могу найти структуру управления: pctrl = pvFreeing & ~0xffff; - person Swiss Frank; 25.05.2020