C언어 함수내에서 배열 설정시..
오늘 하루의 절반을 잡아먹었던 문제가 있습니다 ^^; 지금은 해결했는데 갑자기 궁금해져서......
일단 간단히 설명드리면, mini shell을 만들고 있거든요.
문자열을 받아서 파싱하는 함수가 있는데, 이것은 공백이나 특정 문자들을 받으면 각 토큰으로 나누어서 인자로 보내진 배열에 저장시켜줍니다.
대충 함수를 보자면
int parse(char *string, token a_token[])
{
char word[MAX_WORD_LEN];
char *temp;
int word_offset;
temp = string;
......
어쩌구 저쩌구
......
return 0;
}이런 식이구요. 중간 부분은 temp를 하나씩 이동하면서 공백이나 기타 분리자가 나타날때까지 word에 저장시키는 내용입니다. word[word_offset]에 한 문자열씩 저장되고, 구분자가 나오면, word의 마지막에 '\0'을 첨가후 token에 strcpy로 옮깁니다. (소스를 가져다 설명하려면 너무 복잡해서리 ^^ 필요하면 이 함수만 올려드릴께요)
각설하구, 질문은요.
이 함수를 사용한 프로그램이 컴파일은 이상이 없고, 실행도 되는데, 실행때마다 결과값이 다르다는 것 입니다.
예를 들어 string에 'ls -al'이 들어가면 token[0].word에는 ls, token[1].word에는 -al이 들어가게 됩니다. 근데, 이 프로그램을 실행해, 결과값을 출력시키면 word[0]에 5번중 3번은 ls 가 들어가지만, 어느때는 'lsa'가 들어가고, 또 어느때는 'lsQ'가 들어가고, 대충 ls뒤에 한글자(깨진문자포함)가 들어가서 출력이 됩니다.
즉 ./a.out을 할때마다, 결과값이 예상대로 나올때도, 아닐때도 있다는 것입니다.
뭐, 안에서 랜덤함수를 부른것도 아니고 이게 뭔 조화인지-_-;;
해결은 word배열의 요소를 모두 '\0'으로 할당 시켜주니 정상적으로 돌아가네요.
쓰다보니 잡설이 됬네요. 암튼 궁금한 것은, 지역함수내에서 배열을 생성뒤 초기화 안하면 사용시 크게 문제가 생기는지 알고 싶고요.
두번째로는 왜 이함수가 실행때마다 다른 결과를 나타내는지 궁금합니다.
마지막으로 함수내에서 배열이 설정되면 어떻게 저장되는지도 간단히 부탁합니다.
맨날 신세만 지네여^^.. 프로그래밍을 시작한뒤 얼마안되서 아직은 모르는것만 늘어갑니다- 여기까지 읽어주시느냐 감사합니다 :wink:
추가)
한가지 더 설명하자면, parse함수를 한번 호출시에는 이상이 없습니다. 문자열을 변경한후 2번 3번 호출할때부터 저런 문제가 생기는 군요. 그러니까
parse("cd /root", token); --> 이상없음
parse("vi foo.txt", token); --> 여기부터 문제발생
parse("ls -al", token);
| 첨부 | 파일 크기 |
|---|---|
| 28.29 KB |


Re: C언어 함수내에서 배열 설정시..
parser 함수를 어떻게 구현하셨는지 코드라도 보여주셨으면 좋았을텐데, char word[MAX_WORD_LEN]; 는 함수가 불려질때마다 스택에 새롭게 생성됩니다. 자동으로 0으로 초기화가 되지 않기 때문에 보통 쓰레기 값이 채워집니다. 그래서 결과값이 실행할때마다
엉뚱하게 나오는것 같습니다.
char word[MAX_WORD_LEN] = {0,};하시거나memset(word,0,MAX_WORD_LEN)으로 해주시기 바랍니다.Re: C언어 함수내에서 배열 설정시..
증상만으로 원인을 알아내기는 힘들고 역시 소스가 있어야겠네요.
함수가 하는 일을 보니 strtok()과 많이 겹치는데 굳이 직접 만드시는 이유라도...?
=== [b]해결되었습니다. (아랫댓글) 이것은 그 전에 올린글입니다.
=== 해결되었습니다. (아랫댓글) 이것은 그 전에 올린글입니다. ===
일단 답변 감사드리구요. :D
리펙토링이 제대로 안된상황이라서 넘 복잡하네여. 함튼 함수 소스이구요.
Token은 symbol과 word로 이루어진 구조체입니다.
지금은 앞에서 말한 증상이 나타 나는 상태이구요. word배열을 '\0'으로 초기화 시켜주면 이상없이 작동합니다.
typedef struct token { SYMBOL symbol; char word[MAX_WORD]; } Token;// func: parseCommand // 인자: *s_command(전체 입력 명령), a_token(token별로 분류된 배열) // 기능: 문자열을 입력받아 종류별로 token에 넣습니다. // 반환값: 성공시 tokenSize, 실패시 SYNTEX_ERROR int parseCommand(char *s_command, Token a_token[]) { int idx_token; char *c_char; char word[MAX_WORD]; int word_offset; STATUS status; int i; idx_token = 0; word_offset = 0; status = INIT; // for(i = 0; i < MAX_WORD; i++) // word[i] = '\0'; c_char = s_command; while (status != END) { if(*(c_char) == ';' || *(c_char) == '&' || *(c_char) == '|' || *(c_char) == '<' || *(c_char) == '>' || *(c_ch ar) == ' ' || *(c_char) == '\t' || *(c_char) == '\0') { if(status == WORD) { word[word_offset+1] = '\0'; strcpy(a_token[idx_token].word, word); a_token[idx_token].symbol = getSymbol(a_token[idx_token].word); word_offset = 0; idx_token++; } } if(*(c_char) == ';' || *(c_char) == '&' || *(c_char) == '|' || *(c_char) == '<' || *(c_char) == '>') { if (status == S_COMMAND && *(c_char-1) == '>') { status = M_COMMAND; idx_token--; strcpy(word, ">>"); } else if (status == S_COMMAND || status == M_COMMAND) { return SYNTEX_ERROR; } else { status = S_COMMAND; word[0] = *(c_char); word[1] = '\0'; } strcpy(a_token[idx_token].word, word); a_token[idx_token].symbol = getSymbol(a_token[idx_token].word); idx_token++; } else if(*(c_char) == ' ' || *(c_char) == '\t') { status = BLANK; } else if(*(c_char) == '\0') status = END; else { word[word_offset] = *(c_char); word_offset ++; status = WORD; } c_char ++; } return idx_token; }Test 하는 함수는 다음과 같습니다.
void test() { char s_command[MAX_COMMAND_LEN+1]; Token a_token[MAX_TOKEN]; int tokenSize, tokenOffset; int argSize; int i; char *args[MAX_ARG]; for(i = 0; i < MAX_ARG; i++) args[i] = (char *)malloc(sizeof(char)*MAX_ARG_LEN+1); tokenOffset = 0; tokenSize = parseCommand("ls -al",a_token); printf("%s\n", a_token[0].word); for(i = 0; i < MAX_ARG; i++) free(args[i]); }실행 결과
원래는 TDD로 하나 씩 확인하면서 했구요. 엉뚱하게 다른 Test를 하는데, 그때까지 ok하던넘이 fail이 되더군요-_-;;
그리고, 해결책은 알구요. ^^; 이런문제가 일어나는 이유에 대해서 알고 싶네요.
쓰레기 값이 들어가는 것은 알고 있습니다- 하지만 함수에서 하나씩 덮어씌우고, 마지막에 '\0'로 종결한후, 그 부분까지를 매게변수로 들어온 type에 strcpy로 복사하면 상관없지 않나요? 널문자 이후의 쓰레기 문자열이 c언어 string인식에 영향을 미치지는 않는다고 생각하는데...
두가지 이유입니다. 1.학교 실습이구요^^; 2. 추가기능이 많이 필요해서 직접해보는것이 좋을것 같아서입니다.
찾았습니다 o-0
찾았습니다. o-O
역시나 단순했네여 -_-;
이부분에서 word[word_offset]으로 바꾸니 되네여 -_-;
kihongss님 말씀이 맞구요.
자세히 알아보지 못하고 질문을 올려서 미안합니다 :oops:
한가지 신기한거는, 분명이 저 부분을 예전에 확인했었는데, 그때는 고쳐도 안되었던 기억이 ㅠ.ㅠ... (둘중하나겠져.. 꿈에서 고쳤거나, make를 재대로 안돌리고 실행했거나...)
게리롱푸리롱 송이나 들으며 마음을 달래야 겠습니다 :roll:
댓글 달기