2010-06-04 7 views
9

유닉스에서 C로 프로그래밍 중이며 이고 gets을 사용하여 키보드에서 입력을 읽습니다.gets()가 작동하지 않는 이유는 무엇입니까?

warning: this program uses gets(), which is unsafe. 

아무도 나에게 이런 일이 이유를 말할 수 : 난 항상이 경고 및 프로그램 중지 실행을 얻을?

+0

안전하지 않은 기능입니다. 버퍼 오버플로 공격은 프로그램이 버퍼 크기를 확인할 가능성을 제공하지 않는 함수를 사용하는 경우에 발생할 수 있습니다. – INS

+0

gets() 대신 scanf()를 사용하면 작동하지만 키보드와 프로그램에서 2 개의 입력을 읽어야합니다 내가 첫번째 것을 읽은 후에 멈 춥니 다. 왜? 이것은 다음 코드입니다. char user; char pass; printf ("Iser ID"); scanf ("% s", 사용자); printf ("핀 코드 :"); scanf ("% s", 통과); – Peiska

+1

@peiska : 두 번째 입력을 기다리고 있기 때문에 첫 번째 프로그램이 끝나면 프로그램이 멈 춥니 다. 당신은 그곳에 두 번째'scanf '를 넣었습니다. 왜 그 프로그램이 "멈춘다"는 것이 놀랍습니까? – AnT

답변

8

이전 대답에서 언급 한 것처럼 gets 대신 fgets을 사용하십시오.

그러나 전혀 작동하지 않는 것은 gets이 아닙니다. 매우 안전하지 않습니다. 내 생각 엔 코드에 fgets과 함께 표시되는 버그가 있으므로 소스를 게시하시기 바랍니다.

수정 의견에 제공된 업데이트 된 정보를 기반으로 몇 가지 제안 사항이 있습니다.

  • 모국어로 된 좋은 C 자습서를 찾는 것이 좋습니다. Google은 귀하의 친구입니다. 추천할만한 책으로 The C Programming Language

  • 새로운 정보가있는 경우 원본 게시물로 편집하는 것이 좋습니다. 특히 코드 인 경우 사람들이 의미하는 것을 더 쉽게 이해할 수 있습니다.

  • 기본적으로 문자 배열을 단일 문자로 읽으려고합니다. 물론 실패합니다. 당신이하고 싶은 것은 다음과 같은 것입니다.

    char username[256]; 
    char password[256]; 
    scanf("%s%s", username, password); 
    

    /편집 의견을 자유롭게, 심지어 기본적인 C로 매우 녹슨입니다

편집 2 jamesdlin는 경고로, scanf의 사용이 gets만큼 위험하다.

+0

'scanf' 사용법은'gets'와 마찬가지로 나쁩니다. ('scanf '도 사용하지 마십시오 : http://c-faq.com/stdio/scanfprobs.html) – jamesdlin

+0

@jamesdlin 머리를 위로 주셔서 감사합니다. 버퍼 오버 플로우 문제에 대해서는 잘 모릅니다. 전에 scanf와 관련된 다른 문제들. – ponzao

13

gets은 버퍼를 제공하기 때문에 안전하지 않지만 버퍼의 크기를 알려주지는 않습니다. 입력은 버퍼의 끝을 지나쳐 쓸 수있어 프로그램을 상당히 화려하게 날려 버릴 수 있습니다. fgets를 사용하는 대신이 같은 버퍼가 얼마나 큰지를 말해 때문에 조금 더 :

const int bufsize = 4096; /* Or a #define or whatever */ 
char buffer[bufsize]; 

fgets(buffer, bufsize, stdin); 

... 당신이 그것에게 올바른 정보를 제공하므로 제공, 버퍼의 끝을지나 쓰지 않습니다 그리고 물건을 날려 버려.

약간 OT :하지만,

당신은 버퍼 크기에 대한 const int를 사용해야하는 것은 아니지만 나는 것 강하게, 당신은 단지 두 곳의 문자 수를 두지 않는 것이 좋습니다 필연적으로 당신 때문에 하나는 바꾸지 만 다른 하나는 나중에 변경하지 않을 것입니다. 컴파일러는 다음을 도울 수 있습니다 :

char buffer[4096]; 
fgets(buffer, (sizeof buffer/sizeof buffer[0]), stdin); 

이 표현식은 런타임이 아닌 컴파일 타임에 해석됩니다. 그것은 입력 할 고통, 그래서 내가 헤더 평소 세트에서 매크로를 사용하는 데 사용 :

#define ARRAYCOUNT(a) (sizeof a/sizeof a[0]) 

...하지만 내 순수한 C와 유효 기간이 몇 년이야, 아마 더 좋은 방법이 요즈음.

+0

'char'의 배열을 다루는 경우'sizeof buffer [0]'을 정의에 따라 sizeof (char) == 1로 나눌 필요가 없습니다. 즉, 함수 호출을'fgets (버퍼, sizeof buffer, stdin)' – Christoph

+0

@Christoph : 모든 플랫폼에서'char'가 1 바이트가 될 것인가, (또는) 2 바이트라면'fgets '에 대한 buf 크기 인수 '* 바이트 *가 아닌 * chars *로 적용될 것인가? 내가 본 대부분의 워드 프로세서는 바이트라고 말했다. 나는 C 게임을 한동안 사용해 왔고,이 물건이 더 복잡해 졌음을 알고 코드에서 약간 방어 적이었습니다. 그러나 그렇습니다. @OP, *이 가정들이 안전하다면,'char' 배열로 계산을 생략 할 수 있습니다 (그러나'int','long' 등으로이 이디엄의 비슷한 적용은 아닙니다). –

+0

@ T.J. Crowder : C 표준은 * char *를 1 바이트로 정의합니다. – jamesdlin

5

man gets는 말한다 :

는 사용하지 마십시오

가져(). 불가능 많은 문자 이 (취득 방법 사전) 읽을 수있는 데이터를 모른 채 이야기하고, 가 도착하기 때문에() 버퍼의 끝을지나 문자를 저장하는 것 때문에, 은 사용하기 매우 위험합니다 . 컴퓨터 보안을 깨기 위해 이 사용되었습니다. 대신 fgets()를 사용하십시오.

1

gets()는 안전하지 않습니다. 하나의 매개 변수, char 버퍼에 대한 포인터를 사용합니다. 버퍼를 얼마나 크게 만들어야하는지와 사용자가 리턴 키를 누르지 않고 입력 할 수있는 기간을 스스로에게 물어보십시오.

기본적으로 gets()를 사용하여 버퍼 오버 플로우를 방지 할 수있는 방법이 없습니다. fgets()를 사용하십시오.

관련 문제