2011. 7. 29. 02:01
Q.

p.130~131 op_client.c 부분에서 막혀서 이렇게 글을 씁니다.

학교 서버 리눅스 환경에서 이 소스를 돌려보았습니다.. 그런데..

클라이언트 쪽에서 연결도 됐고, Operand conunt 까지 입력이 되는데

Operand 1 부터 입력을 하면 버스 오류 (core dumped)라는 게 뜨네요..

아무리 찾아봐도 잘 모르겠어서 올립니다.. ㅠㅠ

아무래도 39행인 scanf("%d", (int*)&opmsg[i*OPSZ+1]); 에서 오류가 나는 것 같은데요.

왜 그럴까요 ? ㅠㅠ

미심적어서 소스를 scanf("%d", (int*)&opmsg[i*OPSZ+4]);

이렇게 고쳐보면, 그 뒤 값들은 받아지긴 하지만, 전체적인 로직과, 구현 목적(char 문자에 계산할만큼 숫자를 담아라)이

달라지기에...

34라인의 opmsg[0] = (char)opnd_cnt; 여기서 char형인 1바이트만큼만 기록되야 맞는게 아닌가요?

인터넷에서 대략 찾아보니 메모리가 덤프되는게.. 뭐 겹쳐써지고.. 이런 말도 있고..... ㅠㅠ

알려주세요!!!!!! ㅠㅠㅠㅠㅠ



A.

안녕하세요 해결하지 못해 답변이라 하긴 뭐하지만...

빅엔디안 시스템이 원래 이런 것인지는 잘 모르겠습니다.

op_client.c에서,
문제가 발생하는 부분만 요약했습니다.

1 #include <stdio.h>
2 #include <string.h>
3
4 #define BUFMAX 9
5
6
7 int main(void){
8 int i;
9 char buf[BUFMAX];
10
11 memset(buf, 0, BUFMAX);
12 scanf("%d", (int *)&buf[1]);
13
14 for(i=0; i<BUFMAX; i++)
15 printf("buf[%d]=%0x , %p\n",i, buf[i], &buf[i]);
16
17 return 0;
18
19 }



12번 줄이 문제가 되는 부분인데,
리틀엔디안 시스템의 리눅스에서는 (int *)&buf[숫자]의 숫자 부분을
범위 내에서 마음대로 줄 수가 있었습니다. 원하는 대로 포인터가 갑니다.

그러나, 솔라리스만 이런 것인지 빅엔디안 시스템이 다 이런 것인지는 모르겠지만,
솔라리스 빅엔디안 시스템에서는 반드시 (int *)&buf[숫자]부분의 숫자가 0, 4, 8 이런 식으로
int의 크기에 맞춰서 써줘야 했고, 중간 숫자 1, 2, 3, 5, 6, 7 같은 숫자를 넣는다면
반드시 Core Dump가 일어났습니다.


** 숫자를 0을 주었을 때...
$./a.out
9
buf[0]=0 , ffbff9a8
buf[1]=0 , ffbff9a9
buf[2]=0 , ffbff9aa
buf[3]=9 , ffbff9ab <-- 하위 바이트의 값을 높은 번지 주소에 저장.
buf[4]=0 , ffbff9ac
buf[5]=0 , ffbff9ad
buf[6]=0 , ffbff9ae
buf[7]=0 , ffbff9af
buf[8]=0 , ffbff9b0
$


** 숫자를 1을 주었을 때...
$./a.out
3
Bus error (core dumped)
$



*** 리틀엔디안 시스템의 리눅스에서 숫자 1주고 실행했을 때
$ ./a.out
3
buf[0]=0 , 0xbfb10b83
buf[1]=3 , 0xbfb10b84 <--- buf의 1번 주소에 바로 들어갑니다.
buf[2]=0 , 0xbfb10b85 하위 바이트의 값을 낮은 번지 주소에 저장.
buf[3]=0 , 0xbfb10b86
buf[4]=0 , 0xbfb10b87
buf[5]=0 , 0xbfb10b88
buf[6]=0 , 0xbfb10b89
buf[7]=0 , 0xbfb10b8a
buf[8]=0 , 0xbfb10b8b
$


솔라리스 빅엔디안 시스템에서
op_client.c, op_server.c의 소스를 그대로 쓸 수 없는 것은
맞는 것 같습니다.


A2.

그냥 되도록 바꿨습니다.

서버 프로그램 쪽에서는 바꿀 코드가
int형으로 선언된 opnd_cnt를
char형으로 바꿔주고,


클라이언트 프로그램 쪽에서는

typedef union charInt{
char intByte[4];
int cInt;
}UsrInt;

위와 같이 scanf()를 통해 받을 정보를
임시저장할 공용체 형을 정의하고 후에 선언한 뒤,
이것을 사용해서 클라이언트에서
피 연산자 값을 입력 받는 부분을 아래와 같이 고쳐서

for(i=0; i<opnd_cnt; i++)
{
printf("Operand %d: ", i+1);
scanf("%d", &usrInt.cInt);

opmsg[i*OPSZ+1]=usrInt.intByte[0];
opmsg[i*OPSZ+2]=usrInt.intByte[1];
opmsg[i*OPSZ+3]=usrInt.intByte[2];
opmsg[i*OPSZ+4]=usrInt.intByte[3];
}

opmsg[]에 수동으로 값을 맞춰 넣어주니..

솔라리스에서도 잘되네요..


출처: http://cafe.naver.com/cstudyjava.cafe?iframe_url=/ArticleRead.nhn%3Farticleid=20401&

초보01님의 답변^^ 친절한 답변 감사드립니다 - 소켓 공부ing...

Posted by Triany