포인터 관련.. 캐스팅 에러
글쓴이: sharefeel / 작성시간: 목, 2004/01/29 - 9:32오후
솔라리스 GCC 3.3에서 다음과 같은 문제로 에러를 겪고 있습니다.
char buf[1000]; view_t *vi; vi = (view_t *)buf; vi->member_variable = 0;
위의 코드는 컴파일&링크 잘 됩니다.
하지만 네번째 라인에서 세그멘테이션 폴트가 일어납니다.
당연히 view_t 크기는 1000보다 훨씩 작습니다.
원래 저런식으로 캐스팅해서 쓰면 에러입니까?
웃기는 것은.. 다음과 같이 하면 잘 실행된다는 겁니다.
장난하는 것도 아니고...
char buf[1000]; view_t vi; memcpy(&vi, buf, sizeof(view_t)); vi.member_variable = 0;
Forums:
답변은 아닙니다만...
혹시 세그폴트가 아니라
bus error 아니셨나요?
전에 제가 그런식으로 마구 casting 하니까
bus error 가 나던데...
개념없는 초딩들은 좋은 말로 할때 DC나 웃대가서 놀아라. 응?
아.. 버스 오류가 맞습니다.gdb 로 돌리면 SIGSEGV, 세그멘
아.. 버스 오류가 맞습니다.
gdb 로 돌리면 SIGSEGV, 세그멘테이션 폴트가 납니다.
그런데 도대체 저게 왜 에러의 이유일까요?
에러가 나는 원리가 무엇인지 참 궁금합니다.
===============
Vas Rel Por
자문 자추측입니다..
자답이라고 하긴 뭐한 내용이어서 추측이라고 합니다..
제가 캐스팅 하려고 했던 버퍼는 다음과 같이 구성되어 있습니다..
원래는 저 type이라는 것이 4바이트로 되어 있었는데요..
제가 저것을 2바이트로 바꾸고 나서부터 계속 버스 에러가 났습니다.
이유는 아마도 view_t 의 변수를 읽을 때..
두개의 워드를 동시에 access 해야하기 때문이 아닐까 생각해봅니다.
즉...
위와 같이 int가 두 워드에 걸쳐서 존재하게 되고..
저렇게 배치된 int를 access해서 BUS error가 난 듯 합니다.
찾아보니 버스 에러가 invalid memory alignment 에서 비롯된다고 합니다.
실제로 제일 앞의 타입을 2바이트에서 4바이트로 늘리니 에러가 나지 않습니다.
===============
Vas Rel Por
패딩에 관한 문제입니다.
이것은 structure에 대한 alignment 를 지정하는 부분에서 발생하는 문제가 그 원인입니다. 다른 이기종이나 혹은 내부적으로도 데이터호환을 위해서는 XDR을 지켜주는 것이 맞습니다.
예전에 써놓은 글이 있으니 한번 참고해보시기 바랍니다.
http://www.sunyzero.com/zboard/data/sunycomputer/1062057860/sigbus_pack_pad.txt
========================================
* The truth will set you free.
글쎄여
전 간단한 소스를 통해 테스트 했었는데.
전혀 에러나 SIGNAL이 발생치 않네요.
구조체 멤버로 접근하는데 ..
패딩의 문제라는건..좀 이상하네요.
경험담.. -.-;;
ㅎㅎ bus error는 모르겠고, 전 network driver의 packet처리때도 나타날수 있는 문제입니다.
전 x86에서 정상적으로 돌던 network driver를 arm9 에 porting하는 중에 이런 현상을 발견했답니다. 컴파일러 이론을 몰라서 고생한 경우인데...
packet size를 처리할때 홀수 byte인경우 bad tcp header가 계속 발생 -.-;;
패킷 사이즈가 홀수 짝수 dependent하다는것 찾는데만도 보름 정도 걸렸고 -.-;; :oops:
해결은 강제로 padding을 넣어서 했습니다.(structure에)
그때는 이론을 모르고 해결했던 것인데...
위의 글을 보니 이제야 정확한 이론을 알겠네요 :D
x86에서 돌던 드라이버를 다른 platform에 porting할 경우 고려해야 할 문제인것 같네요~
즉, 이기종간 porting시에 발생할 가능성이 높은 문제인것 같습니다. :!:
Be Postive!
뻐스 에러가 발생하는 예제 입니다. [code:1]typede
뻐스 에러가 발생하는 예제 입니다.
위 memcpy 에서 뻐스오류가 발생하지않는 이유는,
1 byte 문자로 억세스 하기 때문임.
버스 에러는 플랫폼마다 다릅니다..
버스 에러를 내는 플랫폼도 있고 그렇지 않은 플랫폼도 있습니다.
저는 Win 2000(Intel)에서도 네트웍 프로그램을 합니다.
네트웍 프로그램을 하다보니 패딩같은 거 넣으면 프로토콜이 커지고..
그러다보니 그냥 앞에서부터 차곡차곡 데이터를 쌓게 되고,,
그러다보면 수도없이 word alignment를 어깁니다.
하지만 Win 2000(Intel)의 경우,,
특별히 버스에러로 프로그램이 죽거나 하지는 않습니다.
아마 속도는 느려지겠지요..
하지만 이번에 Solaris(Sparc)의 경우에는,,
곧바도 버스에러를 내버리더군요..
그래서 왠만하면 다 패딩을 넣어서 프로토콜을 만들고 있는데,,
전송량을 줄인다는 측면에서는 좀 불만입니다..
리눅스(Intel)도 있지만 귀찮아서 테스트 안해봤습니다..^^;;
언제 시간나면 테스트 해보고 결과 올리지요..
===============
Vas Rel Por
주제와 직접 관련은 없지만 버스 에러 얘기가 나오길래...리눅스에서
주제와 직접 관련은 없지만 버스 에러 얘기가 나오길래...
리눅스에서 netscape 4.76 으로 인터넷을 다니다 보면
버스에러라는 메시지를 뱉으며 netscape가 종료되는 현상이 자주 발생하더군요.
세벌 https://sebuls.blogspot.kr/
x86의 경우 alignment가 맞지 않으면 하드웨어적으로 메모리에 두
x86의 경우 alignment가 맞지 않으면 하드웨어적으로 메모리에 두번 접근해서 이를 조합한 뒤 넘깁니다.
하지만 제가 알기론 대부분의 RISC 머신들은 이 기능 자체가 아예 없습니다. sparc도 여기 포함될겁니다.
이경우 해결책은 alignment가 맞지 않는경우 shift로 alignment 걸리는부분을 자른뒤 or 등으로 해서 집어넣거나
아니면 바이트 단위로 분리해서 넣을 수 있습니다. 굳이 padding 포함하는 것까지는 필요없고요.
Written By the Black Knight of Destruction
댓글 달기