[Mistakable Codes - #2] 정상적으로 opne했는데 write 시 무엇이 문제인가

No Comments

최시 내용은 아래 위키에서 볼 수 있다.
in my wiki

  • initial version: 2007.08.06

목차

1 정상적으로 open했는데 write 시 무엇이 문제인가
2 무리한 open()과 open() 체크

1 정상적으로 open했는데 write 시 무엇이 문제인가 #

아래 코드를 얼핏 보면 파일이 정상적이고 open()이 제대로 되었는데 write()가 ‘-1′을 리턴해버린다.

도대체 무엇이 문제란 말인가?



#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <io.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#define BUFF_SIZE 256
void main()
{
int nErr;
int nRetWrite;
int fh1;
char buff[BUFF_SIZE];
sprintf(buff, "test contents");
// open file and check fd
if(fh1 = open( "OPEN.OUT",
_O_WRONLY | _O_CREAT, _S_IREAD | _S_IWRITE ) < 0)
{
perror( "Open failed on output file" );
}
// write
nRetWrite = write(fh1, buff, strlen(buff));
if( nRetWrite == -1)
{
nErr = errno;
//EBADF Bad file number 9
if(nErr == EBADF)
{
perror("write fail");
}
}
// close file
close( fh1 );
}

//

실행 해보면 에러 메시지는 아래와 같다.

write fail: Bad file descriptor

2 무리한 open()과 open() 체크 #

문제는 open()과 동시에 open() 결과에 대한 error 체크를 할 때, 코드를 잘 못 써버린 것이다.

문제의 코드는 아래이다.

의도는 open()을 하고 open() 시 리턴되는 file handle이 음수인지 체크하려는 것인데 연산자 우선 순위를 간과해서 문제가 발생한 것이다.


// open file and check fd
if(fh1 = open( "OPEN.OUT",
_O_WRONLY | _O_CREAT, _S_IREAD | _S_IWRITE ) < 0)

//

open()의 리턴 값이 file handle을 fh1에 담고 그 것이 음수 인지 (<0) 비교하려고 했지만
실제로는 부등호가 대입 연산자 보다 우선순위가 높아서 open()에서 리턴된 file handle이 음수인지 먼저 비교되고 그
결과가 fh1에 대입된 것이다.

정상적인 파일이기 때문에 open()의 결과인 file handle은 양수가 되고 이 것이 음수와 비교 되니 비교 결과는 false (-1)가 되어 fh1에 대입된 것이다.

아래와 같이 코드를 수정 할 것이다.


// open file and check fd
if( (fh1 = open( "OPEN.OUT",
_O_WRONLY | _O_CREAT, _S_IREAD | _S_IWRITE ) ) < 0)

[Mistakable Codes - #1] writ mode로 열고 read 하기

3 Comments

실수 하기 쉬운 코드에 대해서 생각나는 대로 다뤄보려고 한다.

당연한 것이지만 너무 당연해서 찾기 힘든 코드나 경험하지 않으면 찾기 힘든 error 대처 법 이나 bug에 대해서 다뤄 보려고 한다.

시간에 쫓기다 보면 또는 머릿 속이 가끔 정전이 될 경우 사람을 미치게 만드는 (자기가 세상에서 제일 바보 처럼 느껴지게 하는) 코드에 대해서 다룰 예정이다.

첫 번째는 다음과 같다.

최신 내용은 아래 wiki에서 볼 수 있다.

in my wiki: http://alones.byus.net/moniwiki/wiki.php/mistakable_code_open_write_read

  • initial version: 2007.08.02

목차

1 open()을 했는데 왜 read()가 안될까?
2 file을 write 모드로 열었기 때문이다

1 open()을 했는데 왜 read()가 안될까? #

아래 코드를 보자 왜 read()가 안될까?


#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <io.h>
#include <stdio.h>
#include <errno.h>
#define BUFF_SIZE 256
void main()
{
int fh1;
// open file
fh1 = open( "OPEN.OUT",
_O_WRONLY | _O_CREAT, _S_IREAD | _S_IWRITE );

// check file handle
if( fh1 == -1 )
{
perror( "Open failed on output file" );
}
char buff[BUFF_SIZE];
// read
int nRead = read(fh1, buff, BUFF_SIZE);
// close file
close( fh1 );
}

//

“OPEN.OUT”이라는 파일도 있고 내용도 있는데 왜 read가 제대로 되지 않을까?
nRead의 return 값은 ‘-1′이다.

2 file을 write 모드로 열었기 때문이다 #

제목을 읽자 마자 또는 코드를 보자 마자 단번에 문제점을 찾을 수도 있겠지만
사람이라는 것이 시간에 쫓기거나 가끔 백지 상태가 될 때는 위 코드의 아주 초보적인 버그도 사람을 미치게 만드는 것 같다.
(※ 코드 사이즈가 클 때는 이런 문제가 더 심각해지는 것 같다)

아래와 같이 read() 후의 예외 처리 코드를 넣어 두었다면 에러의 원인을 머리 속이 잠시 정전이 되었거나 시간이 없을 때도 빨리 찾아서 실수를 방지해 줄 수 있을 것 같다.

이런 점에서는 java의 try~catch 문이나 최신 c++의 try~catch가 좋은 것 같다.



#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <io.h>
#include <stdio.h>
#include <errno.h>
#define BUFF_SIZE 256
void main()
{
int nErr;
int fh1;
// open file
fh1 = open( "OPEN.OUT",
_O_WRONLY | _O_CREAT, _S_IREAD | _S_IWRITE );

// check file handle
if( fh1 == -1 )
{
perror( "Open failed on output file" );
}
char buff[BUFF_SIZE];
int nRead = read(fh1, buff, BUFF_SIZE);
if( nRead == -1)
{
nErr = errno;
//EBADF Bad file number 9
if(nErr == EBADF)
{
perror("read fail");
}
}
// close file
close( fh1 );
}

//