안녕하세요 저는 현재 정렬되지 않은 (때때로 때로는) 일련의 부동 소수점을 포함하는 데이터 BLOB를 처리해야하는 프로그램에서 작업하고 있습니다. ARM 코어 텍스 -a8에 대해 gcc 4.6.2로 컴파일 중입니다.GCC에서 배열되지 않은 부동 소수점 액세스를위한 어셈블리를 생성했습니다.
나는 최소한의 예를 쓴 예를 들어 : 내가 생성 된 어셈블리 코드에 대한 질문이 다음 테스트 코드
float aligned[2];
float *unaligned = (float*)(((char*)aligned)+2);
int main(int argc, char **argv)
{
float f = unaligned[0];
return (int)f;
}
컴파일러 (GCC 4.6.2 - 최적화 -O3 포함)의 경우는
을 생산00008634 <main>:
8634: e30038ec movw r3, #2284 ; 0x8ec
8638: e3403001 movt r3, #1
863c: e5933000 ldr r3, [r3]
8640: edd37a00 vldr s15, [r3]
8644: eefd7ae7 vcvt.s32.f32 s15, s15
8648: ee170a90 vmov r0, s15
864c: e12fff1e bx lr
여기서 컴파일러는 데이터 정렬 여부를 알 수 없지만 정렬 된 데이터가 필요한 VLDR을 사용하면 프로그램이 버스 오류로 인해 충돌합니다.
내 실제 질문은 다음과 같습니다.이 컴파일러에서 올바른지 및 내 C++ 코드에서 정렬 처리해야합니까 또는이 컴파일러 버그가 무엇입니까?
값을 액세스하기 전에 복사본을 만들 gcc가 제공하는 현재 해결 방법을 추가 할 수도 있습니다. 트릭은 gcc packed 속성을 가진 float 만 포함하고 struct 포인터를 통해 데이터에 액세스하는 구조체를 정의하는 것입니다. 코드 스 니펫 :
struct FloatWrapper { float f; } __attribute__((packed));
const FloatWrapper *x = reinterpret_cast<const FloatWrapper *>(rawX.data());
const FloatWrapper *y = reinterpret_cast<const FloatWrapper *>(rawY.data());
for (size_t i = 0; i < vertexCount; ++i) {
vertices[i].x = x[i].f;
vertices[i].y = y[i].f;
}
는 C99 표준은 포함 당신이 모든 시나리오에로드 할 주소 주소 등을 연결 한 후 사용할 수있는 것처럼 컴파일러, 찾을 수 없기 때문에 정렬 자신을 돌볼 필요가, 대답은 생각 이 각주 : "단항 * 연산자에 의한 포인터의 역 참조를위한 유효하지 않은 값 중에는 널 포인터, 가리키는 대상의 유형에 맞지 않는 주소가 있습니다 ...". C++ 표준에 비슷한 경고가 포함되어 있다는 것은 의심의 여지가 없습니다. 따라서 프로그램은 기술적으로 정의되지 않았으며 컴파일러는 버그없이 원하는 명령을 자유롭게 생성 할 수 있습니다. –