Что означает ошибка «BUS_ADRALN - Неверное выравнивание адресов»? - PullRequest
5 голосов
/ 14 июля 2010

Мы находимся на HPUX, и мой код на C ++. Мы получаем

BUS_ADRALN - Неверное выравнивание адресов

в нашем исполняемом файле при вызове функции. Что означает эта ошибка? Одна и та же функция работает много раз, затем внезапно выдает дамп ядра. в GDB, когда я пытаюсь напечатать значения объекта, он говорит не в контексте. Любая подсказка, где проверить?

Ответы [ 4 ]

11 голосов
/ 14 июля 2010

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

Проблема с выравниванием данных заключается в том, что адрес, на который указывает указатель, не «правильно» выровнен.Например, некоторые архитектуры (например, старый Cray 2) требуют, чтобы любая попытка чтения из памяти чего-либо, кроме одного символа, осуществлялась только через указатель, в котором последние 3 бита значения указателя равны 0. Если какой-либо из последних3 бита равны 1, аппаратное обеспечение сгенерирует ошибку выравнивания, что приведет к возникновению проблемы, которую вы видите.

Большинство архитектур не столь строги, и зачастую требуемое выравнивание зависит от того, какой именно типдоступ.Например, 32-разрядное целое число может требовать, чтобы только 2 последних бита указателя были равны 0, но 64-разрядное значение с плавающей запятой может требовать, чтобы последние 3 бита были равны 0.

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

Реализация системыиз malloc и / или operator new почти наверняка верны, иначе ваша программа будет аварийно завершена раньше, чем в данный момент.Поэтому я думаю, что плохой распределитель памяти - это наименее вероятное дерево, которое будет лаять.Сначала я бы проверил наличие неинициализированного указателя, а затем неверную арифметику указателей.

В качестве примечания, архитектуры x86 и x86_64 не имеют требований к выравниванию.Но из-за того, как работают строки кэша, а также по ряду других причин, часто для производительности рекомендуется выровнять данные по границе, равной размеру хранимого типа данных (то есть 4-байтовой границе для 32-битного целого).

3 голосов
/ 14 июля 2010

Большинству процессоров (не x86 и не друзей, а чернокожих из семейства lol) требуется, чтобы доступ к определенным элементам был выровнен по кратным числам байтов.Т.е. если вы читаете целое число с адреса 0x04, это нормально, но если вы попытаетесь сделать то же самое с 0x03, вы вызовете прерывание.

Это потому, что проще реализовать аппаратное обеспечение загрузки / храненияесли он всегда кратен размеру данных, с которым вы работаете.

Поскольку HP-UX работает только на процессорах RISC, которые обычно имеют такие ограничения, вы должны увидеть здесь -> http://en.wikipedia.org/wiki/Data_structure_alignment#RISC.

1 голос
/ 29 мая 2014

Большинство этих проблем вызвано множественными зависимостями восходящего потока, связанными с разными версиями одной и той же библиотеки.

Например, и gnustl, и stlport предоставляют разные реализации стандартной библиотеки C ++. Если вы компилируете и связываете с gnustl, в то время как одна из ваших зависимостей была скомпилирована и связана с stlport, то у каждого из вас будет своя реализация стандартных функций и классов. Когда ваша программа запускается, динамический компоновщик попытается разрешить все экспортированные символы и обнаружит известные символы с неправильными смещениями, что приведет к сигналу BUS_ADRALN.

1 голос
/ 14 июля 2010

На самом деле HP-UX имеет собственный отличный форум по ITRC, и некоторые сотрудники HP очень полезны. Я только что посмотрел на ту же тему, что и вы, и вот некоторые результаты . Например аналогичная проблема была вызвана на самом деле неправильным входным параметром. Я настоятельно советую вам сначала прочитать ответы на аналогичный вопрос и при необходимости опубликовать свой вопрос там.

Кстати, вполне вероятно, что вас попросят опубликовать результаты этих gdb команд:

(gdb) bt
(gdb) info reg
(gdb) disas $pc-16*8 $pc+16*4
...