2013-03-14 2 views
0

sscanf에 문제가 있습니다. 이를 확인하려면 나는 간단한 파일을 만든 그래서 컴파일 할 때이 :문자열이있는 sscanf의 이상한 동작

#include <stdio.h> 
main(){ 
    char *a; 
    /* */ 
    char *s = "GET /something HTTP/1.1\r\n"; 
    printf("sscanf: %d\n", sscanf(s, "GET %s HTTP", a)); 
    printf("a: %s\n", a); 
    /* */ 
    printf("sscan: %d\n", sscanf("GET /more HTTP/1.1\r\n", "GET %s HTTP", a)); 
    printf("a: %s\n", a); 
} 

나는 오른쪽 출력 수 :

sscanf: 1 
a: /something 
sscan: 1 
a: /more 

을하지만 빈 주석 사이의 라인을 언급 할 때, 나는 얻을 노래한다 :

sscan: 0 
a: (null) 

질문 1 : 어떻게 그렇게 할 수 있습니까?

그리고 조금 더 : 나는 char *a = NULL를 작성하는 경우, 내가 얻을 :

sscanf: 0 
a: (null) 
sscan: 0 
a: (null) 

질문 2 : 왜?

+2

'a'에 메모리를 할당하지 않았으므로'sscanf'는 정의되지 않은 동작입니다. 첫 번째 경우에 작동하는 척하는 이유는 컴파일러 출력을 조사해야만 결정할 수 있습니다. –

+0

몇 가지 설명 : 먼저 (Q2) 문제가 발생했습니다 (Q2)를 확인하면 문제 (Q1)이 나타납니다. 이 문제는'#pragma GCC diagnostic ... '없이'-Werror -Wall' 옵션을 사용하게하지 않습니다. –

+0

@DanielFischer, 고맙습니다. 나는 사람을 심하게 읽었습니다! –

답변

0

할당되지 않은 공간에 데이터를 쓰고 있습니다. char *a;은 임의의 메모리에 대한 포인터 일뿐입니다. "문자열"에 데이터를 넣으려고하면 정의되지 않은 동작이 발생하고 아무 것도 발생할 수 없습니다.

2

초기화되지 않은 포인터를 sscanf에 전달 중입니다. char *a;char a[100]으로 변경하면 제대로 작동합니다.

+0

'man sscanf'는 메모리를 동적으로 할당하는 수정 자 "% as"가 있지만 작동하지 않는다고 말합니다. 메모리를 사전 할당하는 것은 나쁜 일입니다. 왜냐하면 하위 문자열을 검색하는 버퍼만큼이나해야하기 때문입니다. –

5

문자열을 초기화되지 않은 포인터 (a)로 복사하고 있습니다. 배열에 대해 저장소를 할당하거나 (malloc) 배열을 선언해야합니다.

저장소를 할당하지 않으면 구현이 올바르게 작동하는 것처럼 보일 수 있습니다. a에 NULL을 할당하면 sscanf에 아무 것도 저장되지 않으므로 NULL 포인터 (printf(null)으로 인쇄 됨)와 함께 "문자열"을 인쇄하려고합니다. 일부 시스템에서는 프로그램이 중단되는 경우가 있습니다.

문자열의 자동 할당을 허용하는 컴파일러/라이브러리 확장이 있지만이 기능은 이식 가능하지 않으며 모든 컴파일러가 지원하지는 않습니다.

char *a; 
scanf("%ms", &a;) // allocates storage for a 

초기화되지 않은 포인터를 함수에 전달할 수 있지만 &에 유의하십시오.

+0

이것이 C99std에없는 이유는 무엇입니까? 저에게 매우 유용합니다 (특히 네트워크를 통한 정보 수신). 이 일의 몰락은 뭐죠? – zigo

0

글쎄, 내 경우에는 유일한 옳은 일이, 내가 생각하는이 될 것이다 : s 매우 큰 크기를 가질 수 있습니다 일반적인 경우 문자열에서

#include <string.h> 
#include <stdio.h> 
#include <stdlib.h> 

main(){ 
    char *s = strdup("GET /something HTTP/1.1\r\n"); 
    char *a, *e, *ans; 
    char *end = s + strlen(s); 
    a = strstr(s, "GET"); 
    if(!a) return -1; 
    a += 4; 
    if(a >= end) return -1; 
    e = strstr(a, "HTTP/1.1"); 
    if(!e) return -1; 
    *(--e) = 0; 
    ans = strdup(a); 
    printf("ans: %s\n", ans); 
} 

, 그래서 더 나은별로 할당하는 것 기억하지만, 필요에 따라 권리를 할당하십시오.

gcc (4.7.2)에서 "% as"가 (가) 사용되지 않는 케이스가 작동하지 않습니다.

+1

대신에'm'을 사용할 수 있습니다 - 저는 답안에 예제를 넣었습니다. – teppic

+0

작동하지 않았습니다. 이제 나는 그것을 시도한다 : 정말로, 만약 당신이''더 많은 것을 얻는다 "("더 많이 구해라 ","GET % ms ", &x);')라고 말하면, 나는 처음에는 앰퍼샌드를 잊어 버렸고 잘못된 결과를 얻었을거야 –

+0

예 -'sscanf '는 새로운 메모리에 대한 포인터를 변경해야하기 때문에'&'가 필요합니다. – teppic