#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.
Комментариев нет:
Отправить комментарий