gdb로 배열의 값을 보다가..
글쓴이: quintus / 작성시간: 토, 2004/02/21 - 8:26오후
int main(int argc, char** argv){ int fd[argc]; int i; for(i=0;i<argc;i+){ fd[i]=open(argv[i],O_RDWR); printf("fd[%d]=%d\n",i,fd[i]); } return 0; }
파일 디스크립터를 배열로 저장하고
그걸 프린트 했습니다.
근데 gdb 로 그 때 그 때의 배열의 값을 보니
printf 된 값과 다르게 나오네요. 어찌 된건지...
Quote:
$gdb a.out
(gdb)run *
(gdb)b 6
(gdb) print fd[0]
$1=0xbfff9c0
(gdb)next
fd[0]=-1
...........
(gdb) print fd[1]
$3=oxbfff9c1
(gdb)next
fd[1]=5
왜 gdb 에서의 print fd[0]값과
main 함수에서의 printf("fd[0]=%d",fd[0]); 값과 차이가 있죠..
cast 같은게 필요한건가요?
Forums:
6째줄에 breakpoint설정하시고breakpoint에 걸리자마자
6째줄에 breakpoint설정하시고
breakpoint에 걸리자마자 값을 출력해보셨는데
그때는 값이 아직 fd[0]에 들어가지 않은 때가 아닌지요?
printf문까지 왔을때, print fd[0]하면 제대로 나올듯합니다.
추가 질문..
혹시나 해서 컴파일 환경을 바꿔 유닉스에서 돌려 봤더니 저런 에러가 나오네요. const 가 아닌 값으로 배열의 크기를 정해주려하다 보니 그랬나봅니다.
malloc을 쓰니까 제가 원하는 대로 나오는데
근데
위 디버그내용은 아마도 메모리의 주소 같거든요. oxbfff9c0 이니까 32비트.
그 메모리 값과 주소를 보려면 어찌 해야하는지..
대략 난감 ㅡ.ㅡ;; [b]happibum[/b]님께서 올려주신 답변을
대략 난감 ㅡ.ㅡ;; happibum님께서 올려주신 답변을 전혀
고려치 않으셨네요..
제가 argc를 사용하여서 배열의 크기를 설정하는 것을 처음 보았는데요..
-Wall 옵션으로 컴파일해두 아무런 메시지가 뜨지 않는군요 ~ 본론으루 들어가서..
fd 배열이 선언되면 스택 영역에서 sizeof int * argc 만큼 메모리가 할당되고
초기화는 하지 않습니다. 당연히 쓰레기 값이 fd[0]에는 들어가 있을 수 밖에
없겠죠.. breakpoint를 6에 설정하심은.. fd[0]에 파일 디스크립터 번호값이
쓰여지기 이전에 break하라는 뜻이고 즉, fd[0]에는 여전히 쓰레기값이
들어가있겠죠..
b 7에 설정하시고 다시 실행시켜보세요.. 그리고 argv[0]은 실행 파일의
이름이겠죠.. argv[1]부터 시작하심이 적절할 듯.. 그리고 -1값이 들어있다함은..
파일 오픈에 실패했음을 의미합니다. O_RDWR 모드로 open 하였을 경우는
이미 존재하고 있는 파일을 읽고 쓰기 모드로 오픈입니다. 파일이 O_CREATE
모드도 or 연산으루 추가해주세요..
---------------------------------------
세계는 넓고, 할일은 많다.
int fd[argc] 는 gcc 확장이거나 C99에 포함된 variab
int fd[argc] 는 gcc 확장이거나 C99에 포함된 variable-length array 구문이네요.
static-length array와 어떻게 다를까해서 static-length array도 포함하도록 코드를 조금 수정했습니다.
실행결과를 보시면 int fd[argc]와 int ia[10] 의 타입을 다르게
생각하는 것을 보실 수 있습니다.
gdb는 fd 을 int (*)[0] 의 타입으로 보고 있습니다.
(이는, fd의 크기가 run-time시에 결정되기 때문인 것으로 보입니다.
같은 맥락에서 sizeof(fd) 도 run-time시에 그 값이 *evaluate*되겠죠.)
아마 실제 코드생성에서 gcc (gcc 이용하셨죠? 아님 linux에서 cc이용하셨거나요) 가 variable length array 를 elment type의 size 0인 배열에 대한 포인터 (int [0] 에 대한 포인터)로 잡고서
run-time시에 malloc()해서 공간을 할당받고
(음.. 구현들에서는 malloc이 아니라 stack에서 할당한다고 얼핏 들었던 것 같은데요. malloc이면 내부적으로 free를 불러줘야 할텐데, stack에 잡으면 별도로 free해 줄 필요가 없을 듯한데요. 배열 크기를 크게잡으면 stack 깨지지 않을까요?)
이후 fd[i] 에 대한 참조를 실제로는 *(*fd_internal + i) == fd_internal[0][i] 로 바꾼 것이 아닌가 합니다.
위 실행결과를 보시면
p fd[0][0]
이나
p *fd[0] (p (*fd)[0] 이 더 맞는 표현이겠으나, 현재 상황에서는 equivalent)
값이 5 를 리턴해 준다는 것이 이를 알려주고 있고요.
근데 여기서 좀 이상한 점은,
p fd[0]과
p fd[1]의 값이 틀려진다는 것입니다.
나중값이 현재값보다 1이 더 크지요.
gdb 는 int [0]의 크기를 0이 아니라 1로 생각한 것 같습니다.
gcc에서는 int[0]의 크기를 0으로 생각하고,
fd_internal[0] 과 fd_internal[1]의 값은 같게 처리됩니다.
아래 코드와 실행결과를 참조하세요.
제 테스트 환경은 다음과 같습니다. (gcc 버젼이 좀 낮네요.. ㅡ.ㅡ;;)
% gcc --version
2.95.3
% uname -a
SunOS hostname 5.8 Generic_108528-05 sun4u sparc SUNW,Ultra-80
음.. variable length array는 hidden cost (어느 분이 토론게시판에서 쓰신 표현이 좋아서 가져왔습니다.)가 있다고 봐야할까요?
break 6 는...
gdb) break 6
gdb) next
break 6 다음에 계속 next 하는 거였거든요.
제가 리눅스에서 프로그래밍 하구.. 인터넷을 설정을 못해서. 윈도우로 재부팅하구 손으로 코드를 치다보니까..실수 했네요..
제가 뭐가 잘 못 됐는지 너무 궁금해 하다가 시간이 지나면서 잊어버렸는데.. 오늘 갑자기 다른 컴파일러로 하면 어떨까라는 생각이 들어서 해 봤더니. 뭔가 실마리가 잡히는듯해서...
어쨌든.. 제가 설명을 제대로 못 해서 도움을 주시는 분한테도 혼란을 주게 됐네요. 그래도 오늘 이렇게 답변을 달아주셔서 너무 기쁘네요. 몇일 전에도 비슷한 글 올렸는데 제가 질문의 요지를 제대로 전달하지 못해서 그랬는지 궁금증을 해결하지 못했는데... 오늘 이렇게 답변 달아 주셔서 감사합니다. 이곳이 정말 큰 도움이 됩니다.
근데. gdb 상에서의 " print *fd[i] " 도 "printf("fd[%d]=%d\n",i,fd[i])" 와는 다르게 나오네요.
print *fd[0] 은 printf("fd[%d]=%d\n",i,fd[i])" 값처럼 나오는데
print *fd[1] 부터 해서
print *fd[i]는 예상치 않은 값이 나오네요..
맘 값아선. gdb 한 내용들을 다 올려보고 싶은데.
리눅스 인터넷 설정도 못 하겠고. 그래픽 카드도 못 잡았고. 또 윈도우xp에선
어떻게 mount 시키는 지도 모르고..
나중에 제가 컴퓨터 다 설정하고 나서 gdb 한 내용을 다시 한번 올리겠습니다.
댓글 달기