Cygwin의 fread에서 이상한 현상.
글쓴이: 송지석 / 작성시간: 금, 2003/08/22 - 11:16오전
파일을 hex로 덤프해서 헤더파일에 넣으려고 c로 간단한 프로그램을 짰습니다.
리눅스에서는 잘 되는 걸 확인했습니다. 그런데 같은 소스를 windows의 cygwin에서 컴파일하고 실행해보니 어디선가 무한루프를 돌길래 살펴봐더니 파일 사이즈보다 적게 읽었는데도 fread에서 리턴값이 0이라서 파일 길이만큼 읽기 위해 계속 읽기를 시도하는 것이었습니다.
이렇게요.
Quote:
$ ./convert hello.pcm
input file is hello.pcm
out_file_name = hello.pcm.txt
size=12210
len =1024 i=1024len =1024 i=2048
len =1024 i=3072
...........
len =1024 i=10240len =1024 i=11264
len =945 i=12209
len =0 i=12209
len =0 i=12209
12210만큼 읽어야 하는데 12209만 읽고는 계속 저러고 있습니다.
제 소스의 버그일까요? 흠..
16비트(short) 만큼씩 읽어와서 헥스 값을 쓰는 프로그램입니다.
꼭 한바이트만 차이나는 것은 아닙니다. 좀 더 짧은 파일을 시도해봤더니 제대로 되더군요.
그리고 더 큰 파일을 시도해봤더니 더 많은 바이트수가 차이났습니다.
Quote:
$ ./convert hello.pcm.txt
input file is hello.pcm.txt
out_file_name = hello.pcm.txt.txt
size=60928
len =1024 i=1024len =1024 i=2048
len =1024 i=3072
.............
len =1024 i=53248len =1024 i=54272
len =563 i=54835
len =0 i=54835
같은 파일은 매번 같은 결과가 나옵니다. 리눅스에서 실행할 때는 무한 루프 없이 제대로 되고요. Cygwin에서만 그렇습니다.
제 생각에 제 프로그램의 버그 같은데 어디가 잘못됐는지 잘 모르겠습니다.
한번 봐주세요.
#include <stdio.h> #include <string.h> #include <sys/types.h> #include <sys/stat.h> #include <unistd.h> #define BUF_MAX 1024 int main( int argc, char *argv[]) { char *in_file_name, *out_file_name; FILE *inf, *outf; struct stat statbuf; long long size, i; size_t read_len; #ifndef BIT8 short buf[BUF_MAX]; #else char buf[BUF_MAX]; #endif if (argc<2) { printf("error argument\n"); return 1; } in_file_name = argv[1]; printf("input file is %s\n", in_file_name); if (stat(in_file_name, &statbuf) == -1) { perror("fstat"); return 1; } #ifndef BIT8 size = statbuf.st_size/2;//size in short #else size = statbuf.st_size; #endif out_file_name = (char *) malloc( strlen(in_file_name)+5); sprintf(out_file_name, "%s.txt", in_file_name); printf("out_file_name = %s\n", out_file_name); outf = fopen(out_file_name, "w"); if (!outf) { perror("fopen"); return 1; } inf = fopen (in_file_name, "r"); if (!inf) { perror("fopen"); return 1; } printf("size=%ld\n", size); for (i=0; i<size;) { size_t len; #ifndef BIT8 short *p_buf=buf; len = fread(buf, sizeof(short), BUF_MAX, inf); #else char *p_buf=buf; len = fread(buf, sizeof(char), BUF_MAX, inf); #endif i += len; printf("len =%ld i=%ld\n", len, i); getchar(); while (len) { #ifndef BIT8 fprintf(outf, "\t0x%04x,\n", (*p_buf)&0xffff); #else fprintf(outf, "\t0x%02x,\n", (*p_buf)&0xff); #endif p_buf++; len--; } } fclose(inf); fclose(outf); return 0; }
Cygwin의 gcc 버전은 3.2입니다.
$ gcc --version
gcc (GCC) 3.2 20020927 (prerelease)
테스트한 리눅스의 gcc 버전은
[rommance@sjs converttest]$ gcc --version
gcc (GCC) 3.2.3 20030422 (Hancom Linux 3.2.3)
이렇게 되고요.
Forums:
헉.. 바로 해결됐습니다.아까 글 쓰면서 소스코드를 붙여넣고 있는
헉.. 바로 해결됐습니다.
아까 글 쓰면서 소스코드를 붙여넣고 있는데 보니까 fopen에서 읽을 파일을 "r"속서으로만 열었더군요.
혹시나 해서 "rb"로 읽었더니 제대로 되네요 -_- 어설프게 해프닝만 벌였습니다 죄송..
음. 리눅스랑 윈도랑 뭔가 조금씩 틀리군요. \r\b 차이 때문인가요? 음..
rommance.net
[quote="송지석"]헉.. 바로 해결됐습니다.아까 글 쓰면서
님께서는 아시는것 같지만 이글을 읽을 다른 분들을 위해 주저리 주저리 말을 하자면.
윈도우(MS계열 운영체제)는 ascii파일과 binary 파일로 파일을 구분합니다.
유닉스계열은 윈도우와 비교하면 무조건 binary파일이구요.
특히, 윈도우에서 ascii에 해당하는 파일은 유닉스로 넘길때는 CR을 제거하고 넘겨야 하는 귀찮음이 존재하게됩니다. 없애지 않으면 vi로 파일열때
^M즉, ascii 코드번호 13에 해당하는 문자가 매 줄마다 보이는 아픔이 있지요.
또는, 유닉스에서 ascii파일을(정확히는 ascii처럼 볼 파일을) 윈도우로
가져올때는 CR을 줄바꿈에 넣어줘야하는 아픔도 있지요.
(물론 툴을 잘~ 쓰면 됩니다. 아님 프로그램으로 간단하게 짜거나)
이렇게 안하면 모든 라인이 붙어서 나오는거 보신기억들 있으리라 보이고요.
두 계열운영체제를 오가며 코딩할때는, 항상 잊어서는 안되는것이었습니다.
아주 오래전에 도스의 경우는 file descriptor의 처리였었지요.
DOS가 2바이트 운영체제라, int가 2바이트라서 long을 잘~ 사용하던 기억도 나는군요. 그중 파일오픈시에는(open()) 리턴값이 둘다 정수이긴 하지만, 도스 2바이트, 유닉스 4바이트...... , 따라서, 호환코드를 만든다는 목적하에
long을 남발해도 결국 파일오픈하는 부분등에서는 int를 써야만 하는 상황을
고려해야하지요.
저도 오래도록 쓸일이 없어, 잠시 잊을뻔 했는데 다시 remind하게 되었네요.
------------------ P.S. --------------
지식은 오픈해서 검증받아야 산지식이된다고 동네 아저씨가 그러더라.
&#54783; 뱀다리로...
전에 iostream에서 이런적이 있습니다.
'어째서 gcount()랑 tellg()랑 연관이 없는거지-_-;;;'라며
결국 'c++은 그냥 클래스만 써야겠군;;;'이라고 생각할때
겨우 떠올려서 삽질했음을 느꼈었답니다;;;
----
The future is here. It's just not widely distributed yet.
- William Gibson
댓글 달기