AndroidФорумПрограммирование

падение в Native при приведении типов.

Страницы: 1 2 3 Следующая »
#0
14:01, 23 апр 2013

столкнулся с такой проблемой что ловил падения в следующем коде:

void somefunc( unsigned char* buffer )
{
  int mSomeIntegerVal = ((int*)buffer)[ 0 ];
}

валилось на строке   int mSomeIntegerVal = ((int*)buffer)[ 0 ]; в зависимости от фаз луны. но чаще валилось чем не валилось.
в итоге код пришлось переписать так:

void somefunc( unsigned char* buffer )
{
  int mSomeIntegerVal = buffer[ 0 ] | ( buffer[ 1 ] << 8 ) | ( buffer[ 2 ] << 16 ) | ( buffer[ 3 ] << 24 );
}


Сегодня случайно с хардварщиком обсуждали андроид и ARM процессоры и он поджаловался что 2 часа убил выясняя причину краша в аналогичной ситуации в его девайсе а арме.
выяснилось что если адрес переменной при таком приведении типа не кратен 4 то в силу архитектуры арма вываливается эксепшен некорректного доступа к памяти.


возможно кому то этот совет сэкономит несколько дней отладки кода в поисках "девушки в красном"

#1
14:11, 23 апр 2013

Спасибо, возьмем на заметку.

#2
14:14, 23 апр 2013

апдейт

void somefunc( unsigned char* buffer )
{
  int mSomeIntegerVal = ((int*)&buffer[ i ])[0]; при любом значении i данный код будет вызывать эксепшен на арме если &buffer[ i ] не кратен 4. т.е по сути с вероятностью 75% :-)
}
#3
15:24, 23 апр 2013

EXC_BAD_ALIGN, если не ошибаюсь. Было такое, да.
Привильнее будет сначала привести к указателю на int, потом уже брать значения.

#4
15:41, 23 апр 2013

Кстати, а так?

void somefunc( unsigned char* buffer )
{
  int mSomeIntegerVal;
  memcpy( &mSomeIntegerVal, buffer, sizeof( mSomeIntegerVal ) );
}
#5
15:44, 23 апр 2013

Помеха
> Кстати, а так?
ради копирования 4х байт вызывать memcpy это дикость о_О
Я не пробовал. Мне такое даже в голову не пришло :-)

но могу лишь предположить что работать должно.

#6
15:45, 23 апр 2013

progman
> это дикость о_О
я понимаю)

#7
15:48, 23 апр 2013

Sergio
> Привильнее будет сначала привести к указателю на int, потом уже брать значения.
фиг там

int* mSomeIntegerPtr = (int*)&buffer[ i ];
int mSomeIntegerVal = mSomeIntegerPtr[ 0 ];   <- падать будет

mSomeIntegerPtr будет указывать один фиг на адрес не кратный 4 в 75% случаях. и чтение инта из этого не кратного адреса вызовет тот же самый эксепшен.

#8
15:52, 23 апр 2013

вон нарыл только что по EXC_BAD_ALIGN


ARM Hacking: EXC_ARM_DA_ALIGN exception

I came across a problem today that I’d seen before but couldn’t remember when. Then I stumbled across Peter Bakhirev writing up his findings at Byte Club about a problem I’d helped him with. So I thought I’d quickly write up my summary here incase it helps anyone else.
It started back when I was browsing the Apple developer forums once - I came across someone having a problem where the EXC_ARM_DA_ALIGN exception was thrown. It turned out that this was a problem with setting the value of a variable by dereferencing a pointer, like so:

char *mem = malloc(16); // alloc 16 bytes of data
double *dbl = mem + 2;
double set = 10.0;
*dbl = set;

The compiler was emitting a STMIA instruction that was using a memory location that isn’t word (32-bit) aligned (because of the +2 into the ‘mem’ memory location - assuming mem is word aligned). This causes the processor to throw the exception that bubbles up as an EXC_ARM_DA_ALIGN.

The solution above would be to memcpy instead of dereferencing like so:

char *mem = malloc(16); // alloc 16 bytes of data
double *dbl = mem + 2;
double set = 10.0;
memcpy(dbl, &set, sizeof(set));

This is just a simple example of the problems that can occur when you’re not careful with reading/writing arbitrary memory that you have allocated. Granted, it’s probably a compiler bug in this case, but it illustrates the point.


источник http://www.galloway.me.uk/2010/10/arm-hacking-exc_arm_da_align-exception/

#9
16:10, 23 апр 2013

progman
> int* mSomeIntegerPtr = (int*)&buffer[ i ];
> int mSomeIntegerVal = mSomeIntegerPtr[ 0 ]; <- падать будет
не не, я не о том.

int* intPtr = (int*)buffer;
int val = intPtr[i];
#10
16:31, 23 апр 2013

Sergio
А если в буфере необходимый int лежит со смещением? То есть у тебя там, например, char | char | char | int
Кроме того, мне кажется, что даже без смещения требуемого int'a твой код тоже упадет.

#11
16:36, 23 апр 2013

Помеха
1. Копировать байтиками.
2. При сохранении сразу сохранять с нужными смещениями.

#12
16:42, 23 апр 2013

Я бы привел инт к указателю на char и присвоил бы отдельно - по сути тот же memcpy

#13
16:44, 23 апр 2013

zlos
Как видно из поста #8 - копировать можно и не батиками. Но в чем тогда смысл каста? )

#14
16:45, 23 апр 2013

progman
> в итоге код пришлось переписать так:
так и надо было изначально писать.

progman
> ради копирования 4х байт вызывать memcpy это дикость о_О
какая разница, у тебя в любом случае происходит копирование 4х байт.

Помеха
> Но в чем тогда смысл каста? )
в данном случае? в том, что бы прострелить себе ногу же ;)

Страницы: 1 2 3 Следующая »
AndroidФорумПрограммирование

Тема в архиве.