2013-11-08 2 views
1

У меня есть существующий проект на C++, который я хотел бы передать в android. К сожалению, программа вызывает ошибку «Fatal signal 7 (SIGBUS)» на Android. Он отлично работает на других платформах (32-битный/64-битный Linux и Windows). Вот часть кода, который вызывает проблему:Выравнивание в проекте андроида NDK

RawMem3::RawMem3(uint8_t packet_version, uint32_t flags, uint64_t packet_id, 
    uint64_t packet_nr, uint64_t timestamp, vector<uint16_t>& nr_channels, 
    vector<uint16_t>& samples_per_channel, vector<double>& data) : 
    size_(0) { 

size_ = sizeof(packet_version) + sizeof(size_) + sizeof(flags) 
     + sizeof(packet_id) + sizeof(packet_nr) + sizeof(timestamp) 
     + nr_channels.size() * sizeof(boost::uint16_t) 
     + samples_per_channel.size() * sizeof(boost::uint16_t) 
     + data.size() * sizeof(float); // FIXXXXXME ... hardcoded sizeof() !!!! 

mem_ = malloc(size_); 

uint8_t* ui8_ptr = reinterpret_cast<uint8_t*>(mem_); 
*ui8_ptr++ = packet_version; 

uint32_t* ui32_ptr = reinterpret_cast<uint32_t*>(ui8_ptr); 
*ui32_ptr++ = size_; 
*ui32_ptr++ = flags; 

uint64_t* ui64_ptr = reinterpret_cast<uint64_t*>(ui32_ptr); 
*ui64_ptr++ = packet_id; 
*ui64_ptr++ = packet_nr; 

uint64_t* time_ptr = reinterpret_cast<uint64_t*>(ui64_ptr); 
*time_ptr++ = timestamp; 

uint16_t* ui16_ptr = reinterpret_cast<uint16_t*>(time_ptr); 

for (unsigned int n = 0; n < nr_channels.size(); n++) 
    *ui16_ptr++ = nr_channels[n]; 
for (unsigned int n = 0; n < samples_per_channel.size(); n++) 
    *ui16_ptr++ = samples_per_channel[n]; 

try { 
    float* flt_ptr = reinterpret_cast<float*>(ui16_ptr); 
    for (unsigned int n = 0; n < data.size(); n++) 
     *flt_ptr++ = numeric_cast<float>(data[n]); 
} catch (negative_overflow& e) { 
    cerr << "RawMem -- Constructor: " << e.what(); 
} catch (positive_overflow& e) { 
    cerr << "RawMem -- Constructor: " << e.what(); 
} catch (bad_numeric_cast& e) { 
    cerr << "RawMem -- Constructor: " << e.what(); 
} 

Строго говоря, со своей стороны:

uint32_t* ui32_ptr = reinterpret_cast<uint32_t*>(ui8_ptr); 
*ui32_ptr++ = size_; 
*ui32_ptr++ = flags 

Я предполагаю, что это проблема выравнивания. Я не специалист в этом, поэтому любые идеи, как я могу это исправить? Я уже пытался изменить packet_version на uint32_t. После этого ошибка SIGBUS ушла, однако мое клиентское программное обеспечение предполагает, что packed_version является uint8_t. Я не могу изменить код клиента, поэтому мне нужно исправить это по-другому.

+0

Является ли это устройство или эмулятор? Последние ARM-процессоры должны быть в порядке с невыровненной 32-разрядной целой записью (но взорваться с 64-битной записью и поплавками). – fadden

+0

Это устройство (Nexus 4). – tlimbacher

ответ

3

Использование memcpy() вместо заданий:

#define APPEND(x) memcpy(ui8_ptr, &(x), sizeof((x))); ui8_ptr += sizeof((x)); 

uint8_t* ui8_ptr = reinterpret_cast<uint8_t*>(mem_); 
APPEND(packet_version); 
APPEND(size_); 
APPEND(flags); 
APPEND(packet_id); 
APPEND(packet_nr); 
APPEND(timestamp); 
for (unsigned int n = 0; n < nr_channels.size(); n++) 
    APPEND(nr_channels[n]); 
for (unsigned int n = 0; n < samples_per_channel.size(); n++) 
    APPEND(samples_per_channel[n]); 
for (unsigned int n = 0; n < data.size(); n++) { 
    float qq = numeric_cast<float>(data[n]); 
    APPEND(qq); 
} 
+1

Спасибо, что работает отлично! Мне приходилось добавлять фигурные скобки в циклы for. – tlimbacher

Смежные вопросы