Может кто-нибудь помочь мне выяснить, почему указатель «следующий» в моем связанном списке разыменовывается по неверному адресу памяти в коде на 32-битной платформе, но отлично работает на 64-битной платформе? Моя программа построена как универсальный двоичный файл на Xcode 7.3 и написана на C ++.
У меня есть связанный список, и разыменование указателя «следующий» в отладчике показывает правильную память, но разыменование его в коде считывает память, которая на 4 байта больше, чем должна считываться. Я постараюсь объяснить ..
Объекты в списке составляют 4144 байта каждый, последние 4 байта являются 32-битным указателем на «следующий» элемент в списке. Глядя на «следующий» указатель в памяти (0xBFFD63AC), мы видим, что это 4 нуля (NULL), это правильно. НО обратите внимание, что память в 0xBFFD63B0 является 0x01. Это байт за указателем «следующий». Когда я прошу отладчик напечатать следующую переменную, он печатает правильное значение (NULL):
(lldb) print l_pObject->Next
(Object__t *) $0 = 0x00000000
(lldb) memory read &(l_pObject->Next)
0xbffd63ac: 00 00 00 00 01 00 00 00 00 00 00 00 00 00 00 00 ................
Однако, если я выполняю код, который разыменовывает указатель «следующий», он фактически читает данные из 0xBFFD63B0 вместо 0xBFFD63AC:
l_pObject = l_pObject->Next;
(lldb) print l_pObject
(Object_t *) $3 = 0x00000001
(lldb) memory read &(l_pObject)
0xbffd2504: 01 00 00 00 80 53 fd bf 00 00 00 00 6c 82 2e
Я уверен, что он читает 0x01 из 0xBFFD63B0. Кажется, что отладчик знает, что «next» указывает на память в 0xBFFD63AC, но по какой-то причине разыменование «next» в коде фактически читает из 0xBFFD63B0, но я не уверен, как выяснить почему. Я пытался добавить __attribute__((packed))
к структуре, но это не имело никакого значения. Трудно определить, где что-то идет не так, потому что отладчик говорит мне что-то отличное от того, что на самом деле происходит. Любые советы о том, как действовать дальше, будут очень благодарны!
ИЗМЕНЕНО, ЧТОБЫ ДОБАВИТЬ БОЛЬШЕ ИНФОРМАЦИИ:
По крайней мере, здесь есть ошибка отладчика! Я прошу отладчик напечатать размер структуры, и это дает мне 4144, но в коде я использую функцию C sizeof (), и это дает мне 4148! Так что в структуре определенно происходит заполнение, но отладчик и, очевидно, этот раздел кода не видят его. Это корень моей проблемы.
Debugger:
(lldb) print sizeof(*l_pObject)
(без знака) $ 0 = 4144
Код:
unsigned int iSizeOf = sizeof(*l_pObject); /* iSizeOf will equal 4148! */
Что-то смешное происходит …
Не видя код, невозможно сказать. В целом, как правило, указатели имеют ширину 8 байт в 64-разрядных системах и ширину 4 бита в 32-разрядных системах. Очевидно, вы заметили, что он прыгает на 4 байта больше, чем должно быть, что является сильным показателем. (0xBFFD63B0 - 0xBFFD63AC) == 4
,
Хорошо, я нашел проблему, я должен был понять это сразу. Код, который вылетал, находится в библиотеке. И библиотека, и вызывающее приложение совместно используют определения для типов переменных. Из-за отсутствия флага препроцессора на стороне приложения одному из этих типов выделялось на 4 байта меньше на стороне приложения, чем в коде библиотеки. Поэтому, когда приложение создавало связанный список объектов и передавало ссылку на библиотеку, каждый объект в этом списке был на 4 байта меньше, чем ожидала библиотека. То, что сделало это менее очевидным, было то, что отладчик показывал мне адреса и смещения, основанные на том, что было выделено в приложении, так что на первый взгляд все казалось правильно настроенным. Я решил не доверять отладчику и написал собственный код для проверки адресов и смещений, и тогда стало очевидно, что происходит. В любом случае, в общем, убедитесь, что ваше приложение и библиотека выделяют типы одинакового размера, и тогда все будет работать намного лучше. 🙂