Страницы

Поиск по вопросам

пятница, 13 декабря 2019 г.

Падает нативный код на c++ под андроид

#cpp #android #native


Написал библиотеку с нативными функциями под андроид. Собственно, вот эти функции:
Описание протокола websockets на русском языке. На компьютере эти функции работают
отлично. Наконец дошли руки до запуска на андроиде и в EncodeData() программа вылетает
с ошибкой.

Вылетает на этой строке, на первой итерации:

*(unsigned int*)l ^= mask;


Если убрать маску (mask = 0), то функция работает без ошибок.

В чем проблема в этом коде? Чем заменить, чтобы работало?
    


Ответы

Ответ 1



Я посмотрел Ваш код по ссылке. Действительно, это проблема с выравниванием. Для некоторых архитектур (в частности ARM) необходимо, чтобы обращения к памяти имели естественное выравнивание, т.е. адрес памяти должен быть кратен размеру данных (2 для short, 4 для int, 8 для uint64_t и double). У Вас это происходит из-за величины lpos (даже в предположении, что ret.data выровнена на границу слова (или двойного слова, как обычнно возвращает malloc())). Похоже, что проще всего будет перед основным циклом for(l; l < ft; l += 4) *(unsigned int*)l ^= mask; добавить несколько строчек for(; l < t && l & 0x3; l++) { // цикл выполнится 0, 1, 2 или 3 раза *l ^= *m; mask = (mask << 8) | ((mask >> 24) & 0xff); // циклический сдвиг влево на 1 байт } которые (по идее, на компе не проверял) побайтово меняют данные, пока не достигнуто выравниваание подходящее для int и крутят маску так, чтобы в следующем цикле для int она осталась правильной.

Ответ 2



Это называется "неопределенное поведение", также известное как "UB". Если l имеет тип unsigned char*, то каст (unsigned int*) l работает как reinterpret_cast(l). В требованиях к reinterpret_cast написано что для каста T1* в T2* выравнивание T1 должно быть не меньше выравнивания T2, иначе значение результата каста не определено. Сам по себе каст безобиден, но вот разыменование указателя имеющего такое неопределенное значение приводит к UB.

Комментариев нет:

Отправить комментарий