Cygwin의 fread에서 이상한 현상.

송지석의 이미지

파일을 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=1024

len =1024 i=2048

len =1024 i=3072
...........
len =1024 i=10240

len =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=1024

len =1024 i=2048

len =1024 i=3072
.............
len =1024 i=53248

len =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)
이렇게 되고요.
송지석의 이미지

헉.. 바로 해결됐습니다.

아까 글 쓰면서 소스코드를 붙여넣고 있는데 보니까 fopen에서 읽을 파일을 "r"속서으로만 열었더군요.

혹시나 해서 "rb"로 읽었더니 제대로 되네요 -_- 어설프게 해프닝만 벌였습니다 죄송..

음. 리눅스랑 윈도랑 뭔가 조금씩 틀리군요. \r\b 차이 때문인가요? 음..

mach의 이미지

송지석 wrote:
헉.. 바로 해결됐습니다.

아까 글 쓰면서 소스코드를 붙여넣고 있는데 보니까 fopen에서 읽을 파일을 "r"속서으로만 열었더군요.

혹시나 해서 "rb"로 읽었더니 제대로 되네요 -_- 어설프게 해프닝만 벌였습니다 죄송..

음. 리눅스랑 윈도랑 뭔가 조금씩 틀리군요. \r\b 차이 때문인가요? 음..


님께서는 아시는것 같지만 이글을 읽을 다른 분들을 위해 주저리 주저리 말을 하자면.

윈도우(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. --------------
지식은 오픈해서 검증받아야 산지식이된다고 동네 아저씨가 그러더라.

ageldama의 이미지

전에 iostream에서 이런적이 있습니다.

'어째서 gcount()랑 tellg()랑 연관이 없는거지-_-;;;'라며
결국 'c++은 그냥 클래스만 써야겠군;;;'이라고 생각할때
겨우 떠올려서 삽질했음을 느꼈었답니다;;;

----
The future is here. It's just not widely distributed yet.
- William Gibson

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.