2014-09-12 2 views
6

strlen은 종료 널 문자 앞에 오는 문자 수를 반환합니다. strlen의 구현은 다음과 같습니다이 특정 구현 s 불확정 값을 포함 할 수 s를 역 참조초기화되지 않은 값이있는 문자열의 strlen은 정의되지 않은 동작입니까?

size_t strlen(const char * str) 
{ 
    const char *s; 
    for (s = str; *s; ++s) {} 
    return(s - str); 
} 

. 그것은이 동등의 하나가 있다면

int a; 
int* p = &a; 
*p; 

그래서 예를 들어이 (strlen를 일으키는 잘못된 출력을 제공하기 위해) 할 :

char buffer[10]; 
buffer[9] = '\0'; 
strlen(buffer); 

가 정의되지 않은 동작인가?

+1

@ user2864740 문자열에 * 값을 입력해야합니까? C가 읽기 전에 쓰기에 행복하게 충돌 할 수 있습니까? – kay

답변

2

표준 함수 strlen을 호출하면 정의되지 않은 동작이 발생합니다. DR 451이를 명확히 : 더 심도있는 논의 see this thread를 들어 불확정 값

에 사용하는 경우

라이브러리 함수가 정의되지 않은 동작을 전시 할 예정이다.

+0

아래 내 의견은 포스터가 strlen 함수를 구현 한 것을 말합니다. 표준 라이브러리에는 다른 제약 또는 자유가 있다는 데 동의하십시오. –

+0

버퍼 [9] 꽤 결정적입니다 ... – Basilevs

+0

@ KC-NH는 OP의 의사 구현이 아닌 표준'strlen' 함수에 대해 설명하고 있음을 명확히하기 위해 게시물을 업데이트했습니다. –

1

아니요, 정의되지 않은 동작이 아닙니다. strlen 함수는 버퍼가 끝나기 전에 중지됩니다. strlen 함수가 buffer [10]을 참조하면 yes, undefined가됩니다.

버퍼의 대부분이 임의의 데이터를 포함하고 있기 때문에 확실히 예상치 못한 동작입니다. "정의되지 않은"은 언어 표준을 작성하는 사람들을위한 특별 단어입니다. 즉, 메모리 결함이나 프로그램 종료 등의 상황이 발생할 수 있습니다. 뜻밖의 말은, 프로그래머가 원했던 것이 아니라는 것입니다. 일부 실행에서는 strlen의 결과가 3이거나 10 일 수 있습니다.

0

예, 정의되지 않은 동작입니다.

동작은 다음과 같은 경우에 정의되지 않는다 :

...

자동 저장 기간이 객체의 값 초안 C11 표준, §J.2 "정의되지 않은 행동"에서 불확실한 동안 사용됩니다.

+2

이 코드는 실제로 불확정 값을 사용하지 않습니다 ('buffer'는 불확실하지 않지만'buffer [0]'은). 그러나'strlen'은 값을 사용합니다. 또한,이 부속서는 비 규범 적 (UB의 다양한 사례를 발견하기위한 일종의 색인이라고 여겨집니다)입니다. 규범적인 텍스트는보다 자세하고 불확정 한 사용이 UB가 아닌 경우에 대한 예외가있다. –

+1

개체는 "불확정"뿐만 아니라 값이 "지정되지 않음"이므로 아무런 문제가 발생하지 않습니다. –

2

표시되는 변형의 동작은 이러한 상황에서 잘 정의됩니다.

  • 0으로 설정 한 10 번째 요소를 제외하고 초기화되지 않은 배열의 바이트에는 모두 불확정 값이 있습니다.
  • indeterminate 값에 액세스하는 것은 기본 객체의 주소를 가져 오지 않거나 값이 해당 유형에 대한 트랩 인 경우에만 UB가됩니다.
  • 이것은 배열이며 배열 요소에 대한 액세스는 포인터 산술을 통하므로 첫 번째 경우는 관련이 없습니다.
  • char 값은 UB없이 액세스 할 수 있습니다. 표준에서 트랩 표현에 대한 절은 모든 문자 유형을 명시 적으로 제외합니다.
  • 따라서 다루는 값은 단순히 "지정되지 않음"입니다.
  • C 표준위원회의 일부 구성원은 불명확 한 값을 읽을 때마다 매번 다른 결과를 내고, 일부는 "whobly"상태라고 부릅니다. 함수는이 값을 최대 한 번 읽으므로 여기서는 관련이 없습니다.
  • 배열 요소에 액세스하면 임의의 유효하지만 char 값이 부여됩니다.
  • for 루프가 늦은 시각 9에 멈추지 않으므로 배열을 오버런하지 않을 것입니다.

특정 버전의 기능을 사용하면 보이는 것 이상의 "나쁜"일은 발생하지 않습니다. 그러나 불특정 결과를 생성하는 함수 호출을 갖는 것은 실제 코드에서 볼 수있는 것이 아무것도 아닙니다. 이것과 같은 것이 여기에 아주 미묘한 벌레가되고, 당신은 그것을 반드시 피해야합니다.