illegal seek error 에 대해서 알고싶습니다.....정말요...

majorofc의 이미지

처음으로 올리는 글이 질문이라 상당히 죄송스럽습니다.

c 프로그래밍 도중에 3~4개의 파일을 동시에 fopen() 하여 프로그래밍을

하다 fclose()로 닫는데 세그먼트 폴트가 나더군요.

그래서 perror(fp); 해보았더니

fclose(fp) : illegal seek

이라고 출력되네요....

지금 일주일째 이 문제에 대해서 고민하고 있습니다...

답변 부탁드립니다...

ps. 인터넷으로 찾아보니 google에 유사한 질문이 있었는데

영어에다가 저의 경우와는 좀 다른 내용이어서....이렇게 질문드립니다...

sjpark의 이미지

짐작인데요,

fclose에서 segment fault가 났다면 그 전 코드에서 해당 파일 포인터에 문제가
생긴거 같은데요...

코드가 없으니...후후...

majorofc의 이미지

전체 소스는 제 실력이 모자라서 vi 에서 어떻게 붙히는지 몰라서

에러나는 부분 일부분만 올려 드리겠습니다..

FILE *idx_fileopen()
{
        FILE *idx_fp;
        char *idx_file;

        idx_file = (char*)malloc(STRSIZE);
        sprintf(idx_file, "%s.%d", spec.tmpidx_prefix, filecnt);

        idx_fp = fopen(idx_file, "r");

        free(idx_file);
        return idx_fp;
}


FILE *off_fileopen()
{
        FILE *off_fp;
        char *off_file;

        off_file = (char*)malloc(STRSIZE);
        sprintf(off_file, "%s.%d", spec.tmpoff_prefix, filecnt);

        off_fp = fopen(off_file, "r");

        free(off_file);
        return off_fp;
}

FILE *read_tmpopen()
{
        FILE *fp;

//      tmp_file = (char*)malloc(STRSIZE);
//      sprintf(tmp_file, "%s.%d", "tmpfile", (filecnt - 1));

        fp = fopen(filename[filecnt - 1], "r");

//      free(tmp_file);
        return fp;
}

FILE *write_tmpopen()
{
        FILE *fp;
//      char *write_file;


//      write_file = (char*)  malloc(STRSIZE);
//      sprintf(write_file, "%s.%d", "tmpfile", filecnt);
        if ((fp = fopen(filename[filecnt], "w")) == NULL)
                perror("write fileopen error\n");

//      free(write_file);
        return fp;
}

void init_merge()
{

        FILE *idx_fp;
        FILE *off_fp;
        FILE *tmp_fp;
        int tmp;
        int tmp2;
        int offset;
        int i;

        tmp_fp = write_tmpopen();
        idx_fp = idx_fileopen();
        off_fp = off_fileopen();

        filecnt++;

        fseek(idx_fp, 0L, SEEK_END);
        tmp = ftell(idx_fp);
        fseek(idx_fp, 0L, SEEK_SET);

        while (!feof(idx_fp) && !feof(off_fp)) {
                fread(&offset, sizeof(int), 1, off_fp);
                fseek(idx_fp, offset, SEEK_SET);

                fread(&lex.size, sizeof(int), 1, idx_fp);

                tmp_offset = ftell(idx_fp);
                lex.token = (char*) malloc(lex.size);

                fgets(lex.token, lex.size + 1, idx_fp);

                fseek(idx_fp, tmp_offset + lex.size, SEEK_SET);
                fread(&lex.totalDoc, sizeof(int), 1, idx_fp);

                fwrite(&lex.size, sizeof(int), 1, tmp_fp);
                fprintf(tmp_fp, "%s", lex.token);
                fwrite(&lex.totalDoc, sizeof(int), 1, tmp_fp);
//              printf("%d %s %d", lex.size, lex.token, lex.totalDoc);

                for (i = 0; i < lex.totalDoc; i++) {
                        fread(&pos, sizeof(POSTING), 1, idx_fp);
                        fwrite(&pos, sizeof(POSTING), 1, tmp_fp);
//                      printf(" %d %d", pos.docNo, pos.term_fre);

                }
//              printf("\n");
                free(lex.token);

                if (tmp == ftell(idx_fp)) break;
        }
        perror("fclose(tmp_fp)");
        perror("fclose(idx_fp)");
        perror("fclose(off_fp)");
//      fcloseall();

}
sjpark의 이미지

파일 이름 만들어서 오픈 할때,

오픈이 성공했는지 실패 했는지 검사 해주세요.

perror를 쓰실때에는
오류가 나는 부분에서 쓰시면 도움이 되요.

fp = fopen(...);
if(fp == NULL) {
   perror(NULL);
}
...

오류 확인이 가능한 함수를 사용할때라면 항상 오류 확인 코드를 써주시는게
후에 디버깅에 많은 도움이 될거 같아요...

// fread, fwrite, fseek 등의 함수도 오류 확인이 가능한거 같아요..

majorofc의 이미지

검사한 결과 에러메세지가 뜨지 않는 것과 파일내의

데이터 처리는 정상적으로 처리되는 것으로 봐서는

정상적으로 열린 것 같습니다.

illegall seek 메세지는 다음과 같이 뜹니다.

fclose(idx_fp): Success
fclose(off_fp): Illegal seek
fclose(tmp_fp): Illegal seek

이때 이상한 것은 fclose 순서를 바꾸어도 에러는 같은위치에서 난다는 것입니다.

fclose(off_fp): Success
fclose(tmp_fp): Illegal seek
fclose(idx_fp): Illegal seek

좋은 답변 고맙습니다.

sjpark의 이미지

majorofc wrote:

fclose(idx_fp): Success
fclose(off_fp): Illegal seek
fclose(tmp_fp): Illegal seek

이때 이상한 것은 fclose 순서를 바꾸어도 에러는 같은위치에서 난다는 것입니다.

fclose(off_fp): Success
fclose(tmp_fp): Illegal seek
fclose(idx_fp): Illegal seek


if(fclose(off_fp) == EOF) {
   perror();
}

이런 식으로 perror를 쓰신거 맞지요?
이렇게 쓰면 순서가 바뀌지 않을거 같아요..
perror를 마지막에 몰아서 저렇게 쓰지 말고...
에러가 나서 에러 처리가 되어야 하는 루틴에 perror를 써보시면 어떻게 되요?
또 fseek 호출 함수 반환값도 확인하고 있는거죠?

또 fseek을 호출 한 후
errorno도 확인해 보세요,
EBADF가 설정되었다면 탐생가능 스트림이 아니라네요
EINVAL이 설정되었다면 인자가 잘못되었데요

majorofc의 이미지

답변 해주신대로

if(fclose(off_fp) == EOF) {
   perror();
}

fclose를 검사해 본 결과

바로 세그멘테이션 오류가 나더군요...

그래서 fclose의 perror부분을 다음과 같이 빼 보았더니....

기존
        perror("fclose(off_fp)\n");
        perror("fclose(idx_fp)\n");
        perror("fclose(tmp_fp)\n");
고친후
        fclose(off_fp)\n;
        fclose(idx_fp)\n;
        fclose(tmp_fp)\n;

역시 바로 세그멘테이션 오류가 나더군요.

fseek후의 errno검사는 0으로 아무런 이상이 없었구여.

fclose의 errno검사 결과 29가 나오네요..

그래서 헤더파일을 봤더니...

#define ESPIPE 29 /* Illegal seek */

이렇게 돼있네요 역시나 illegal seek으로 말이죠..

참 알 수가 없네요 정말......

다시한번 답변 고맙습니다.

lunarainbow의 이미지

저도 얼마전에 같은 현상을 발견했는데, 끝끝내 원인을 찾지 못하였습니다.

gdb로 확인해 보았는데, 파일 포인터를 몇번 사용한 뒤, fclose를 해주지 않고 다른 작업을 하게 하다보면,

중간에 어느 순간 갑자기 파일 포인터의 내용이 변경 되는 에러였습니다.

원인을 찾다 찾다 포기했는데, 이번 기회에 저도 배울 수 있었음 좋겠습니다. ^^

sjpark의 이미지

fclose에서 에러가 난다고 보기 보다,

파일 포인터에 문제가 생겨서그런것 같습니다.

FILE fp;
fp = fopen(파일,옵션);
if(fp == NULL) {
   perror(NULL);
}

를 반드시 써주세요
잘 작동하는 것 "같다고" 하는건...

 
int retcnt;
retcnt = fread(....)
if(retcnt != 읽은아이템수) {
   에러.
}

int retcnt;
retcnt = fwrite(...)
if(retcnt != 쓴 아이템수) {
   에러
}

if(fseek(...) == -1) {
   perror("fseek");
}

마지막으로
컴파일에..

   gcc 소스코드 -o 바이너리 -Wall

로 하세요.

반드시. 위 코드를 모두 적용시켜 보세요.

댓글 달기

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
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.