[C] 버퍼 초기화 - 실행할때마다 결과가 다르게 나오는 코드?

 

#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<fcntl.h>
#include<sys/stat.h>

#define BUFFER_SIZE 1024
#define WORD_MAX 100

int main() {

	int fd;
	int length=0, offset=0, count=0;
	char* fname = "ssu_test.txt";
	char buf[WORD_MAX][BUFFER_SIZE];
	int i;
	
	if((fd=open(fname, O_RDONLY))<0) {
		fprintf(stderr, "open error for %s.\n", fname);
		exit(1);
	}

	for(int a=0; a<WORD_MAX; a++) {
	
		if((read(fd, buf[a], BUFFER_SIZE))==-1) break;
		for(int i=0; i<BUFFER_SIZE; i++) {
		
			if(buf[a][i]=='\n') {
				offset = offset+i+1;
				lseek(fd, offset, SEEK_SET);
				count++;
				break;
			}
		}
	}
	//count--; //자동 추가된개행은 count하지 않음
	//printf("count : %d\n", count);
	close(fd);
	
	for(i=0; i<count; i++)
		printf("%s\n", buf[i]);
		
	printf("line number: %d\n", count);
	exit(0);
}

system call-open(2)함수로 파일을 열고 BUFFER_SIZE만큼씩 파일을 읽는다. 읽어들인 파일에서 char문자 하나씩을 읽어가며 개행이 처음 나오면 lseek로 offset을 개행이 나온 다음 위치로 이동시킨 후, offset부터 BUFFER_SIZE만큼 파일을 읽는 과정을 반복하는 간단한 코드이다. 

 

 

ssu_test.txt 파일이 아래와 같이 생겼다면

Linux System Programming!\nUnix System Programming!\nLinux Mania\nUnix Mania\n
(마지막은 파일 끝 자동개행)
//처음에는 모두 읽어들인다
Linux System Programming!\nUnix System Programming!\nLinux Mania\nUnix Mania\n

//첫 개행이 나온 다음 위치부터 읽어들인다
Unix System Programming!\nLinux Mania\nUnix Mania\n

//그 다음 개행이 나온 다음 위치부터 읽어들인다
Linux Mania\nUnix Mania\n

//그 다음 개행이 나온 다음 위치부터 읽어들인다. 이후에는 read할것이 없어서 
Unix Mania\n

line number: 4\n

과 같이 출력이 이루어질 것을 기대했는데, line number가 5가 나왔다.

 

먼저 왜 5가 나온 것인지도 몰랐는데, 더욱 심각한건 실행때마다 결과가 다르게나옴. 6, 7, 8, 10까지 나온다. 동일한 실행파일을 동작시킨건데..

처음에는 코드를 테스트하면서 printf의 \n개수를 조절하다가 값이바뀌길래 printf가 로직에 영향을 주는 말도안되는일이 일어나는줄 알았는데 그건 아니고 실행할때마다 파일에 \n개수가 다르게 설정된다정도의 이해만 가능했다. 

 

대체 어디에 개행문자가 추가되는건지 찾아보기 위해서 break문 부분에 개행 전 문자를 출력해보았다.

			if(buf[a][i]=='\n') {
				offset = offset+i+1;
				lseek(fd, offset, SEEK_SET);
                printf("%d\n", buf[a][i-1]); //추가
				count++;
				break;
			}

아스키코드 32는 '!', 97은 'a'이다. ssu_test파일의 개행을 적절하게 읽어온 것을 확인할 수 있다. 그런데 112('p'), 0('\0'), -32(음수 ASCII값은 없는데??)는 대체 어디서 읽어온걸까? 

 

해결

간단함... 그냥 사이즈에 딱 맞는 버퍼가 아니기때문에 다음 버퍼사이즈에 쓰레기값이 들어있을 경우 나오는거였음.

초기화만 해주면 된다.