초기화되지 않은 변수
Uninitialized variable컴퓨팅에서 초기화되지 않은 변수는 선언된 변수이지만 사용되기 전에 이미 알려진 값으로 설정되지 않습니다.어느 정도 가치는 있지만 예측 가능한 가치는 아닙니다.따라서 이는 프로그래밍 오류이며 소프트웨어의 일반적인 버그 원인입니다.
C 언어의 예
초보 프로그래머에 의한 일반적인 가정은 모든 변수가 선언될 때 0과 같은 알려진 값으로 설정된다는 것입니다.이것은 많은 언어에 해당되지만 모든 언어에 해당하지는 않기 때문에 오류가 발생할 가능성이 있습니다.C 등의 언어는 변수에 스택스페이스를 사용하며 서브루틴에 할당된 변수의 컬렉션은 스택프레임이라고 불립니다컴퓨터는 스택 프레임에 적절한 공간을 확보하지만 일반적으로 스택 포인터의 값을 조정하는 것만으로 충분한 공간을 확보할 수 있으며 메모리 자체를 새로운 상태로 설정하지 않습니다(일반적으로 효율성에 대한 우려에서).따라서, 그 시점에서 그 메모리의 내용이 무엇이든, 그 주소를 차지하고 있는 변수의 초기치로 표시됩니다.
C의 간단한 예를 다음에 나타냅니다.
무효 세어보세요( 무효 ) { 인트 k, i; 위해서 (i = 0; i < > 10; i++) { k = k + 1; } 인쇄물(%d, k); }
최종 가치k
정의되어 있지 않습니다.10이어야 한다는 답변은 0에서 시작했다고 가정하고 있습니다.이것은 사실일 수도 있고 아닐 수도 있습니다.이 예에서 변수는i
의 첫 번째 절에 의해 0으로 초기화됩니다.for
진술.
또 다른 예로는 구조물을 다루는 경우가 있습니다.아래 코드 스니펫에는struct student
학생에 대한 정보를 설명하는 몇 가지 변수가 포함되어 있습니다.함수register_student
멤버를 완전히 초기화하지 못했기 때문에 메모리 누수가 발생합니다.struct student new_student
좀 더 자세히 보면 처음에age
,semester
그리고.student_number
초기화됩니다.단, 의 초기화는first_name
그리고.last_name
멤버가 올바르지 않습니다.이것은 만약 그 길이가first_name
그리고.last_name
문자 배열이 16바이트 미만인 경우strcpy
각 멤버용으로 예약된 16바이트의 메모리 전체를 완전히 초기화하지 못했습니다.[1]그 후memcpy()
'결과 구조물을 에 입력'output
스택 메모리가 발신자에게 리크됩니다.[2]
구조 학생입니다 { 서명되어 있지 않다 인트 나이; 서명되어 있지 않다 인트 학기; 차 이름[16]; 차 성_이름[16]; 서명되어 있지 않다 인트 student_number; }; 인트 register_disclossible(구조 학생입니다 *산출량, 인트 나이, 차 *이름, 차 *성_이름) { // 이러한 포인터 중 하나가 Null이면 실패합니다. 한다면 (!산출량 !이름 !성_이름) { 인쇄물(에러!\n"); 돌아가다 -1; } // 문자열의 길이가 16바이트 미만(늘바이트 포함)인지 확인합니다. // 오버플로우를 피하기 위해 한다면 (스트렌(이름) > 15 스트렌(성_이름) > 15) { 인쇄물("first_name과 last_name은 16자를 초과할 수 없습니다.\n"); 돌아가다 -1; } // 멤버 초기화 중 구조 학생입니다 new_displays(신규_displaces); new_displays(신규_displaces).나이 = 나이; new_displays(신규_displaces).학기 = 1; new_displays(신규_displaces).student_number = get_new_module_number(); 스트럭시(new_displays(신규_displaces).이름, 이름); 스트럭시(new_displays(신규_displaces).성_이름, 성_이름); //결과를 출력에 표시 메모리(산출량, &new_displays(신규_displaces), 크기(구조 학생입니다)); 돌아가다 0; }
어떤 경우에도 변수가 암묵적으로 0과 같은 기본값으로 초기화된 경우에도 일반적으로 이 값은 올바른 값이 아닙니다.값이 기본 값인 경우 Initialized가 올바른 것은 아닙니다.(단, 포인터 및 포인터 배열에 대한 기본 초기화는 올바른 값으로 실제로 초기화되기 전에 비활성화되기 때문에 올바른 방법입니다).C에서는 명시적으로 초기화되지 않은 정적 저장 기간의 변수가 0(또는 포인터의 [3]경우 null)으로 초기화됩니다.
초기화되지 않은 변수는 버그의 빈번한 원인일 뿐만 아니라 이러한 종류의 버그는 재현할 수 없기 때문에 특히 심각합니다.예를 들어 변수는 프로그램의 일부 브랜치에서만 초기화되지 않은 상태로 남아 있을 수 있습니다.경우에 따라서는 초기화되지 않은 변수를 가진 프로그램이 소프트웨어 테스트에 합격할 수도 있습니다.
영향
초기화되지 않은 변수는 경우에 따라서는 임의 메모리를 누출하거나 임의 메모리 덮어쓰기를 달성하거나 코드를 실행하기 위해 악용될 수 있기 때문에 강력한 버그입니다.Address Space Layout Randomization(ASLR; 주소 공간 레이아웃 랜덤화)을 사용하는 소프트웨어를 이용할 때는 메모리 내의 소프트웨어의 기본 주소를 알아야 하는 경우가 많습니다.초기화되지 않은 변수를 부정 이용하는 것으로, ASLR 를 바이패스 할 수 있습니다.
언어로 사용
초기화되지 않은 변수는 어셈블리 언어, C 및 C++와 같은 시스템 프로그래밍용으로 설계된 언어에서 특히 문제가 됩니다.이러한 언어의 개발에는 성능과 안전성 사이의 상충이 일반적으로 성능에 유리하게 해결되는 설계 철학이 수반되었다.프로그래머에게는 초기화되지 않은 변수와 같은 위험한 문제를 인지해야 하는 부담이 주어졌다.
다른 언어에서는 변수가 생성될 때 알려진 값으로 초기화되는 경우가 많습니다.예를 들어 다음과 같습니다.
- VHDL은 모든 표준 변수를 특별한 'U' 값으로 초기화합니다.이것은 시뮬레이션에서 디버깅을 위해 사용되며 다중값 로직을 통해 사용자에게 상관 없음 초기값이 언제 출력에 영향을 미치는지 알려주기 위해 사용됩니다.
- Java에는 초기화되지 않은 변수가 없습니다.명시적 이니셜라이저와 배열 요소가 없는 클래스 및 객체의 필드는 해당 유형의 기본값(부울의 경우 false, 모든 숫자 유형의 경우 0, 모든 참조 [4]유형의 경우 null)으로 자동으로 초기화됩니다.Java의 로컬 변수는 액세스하기 전에 확실하게 할당해야 합니다.그렇지 않으면 컴파일 오류입니다.
- Python은 로컬 변수를 초기화하여
NULL
(에서 취득)None
)를 기동합니다.UnboundLocalError
이러한 변수가 유효한 값으로 초기화되기 전에 액세스되는 경우. - D는 프로그래머가 명시적으로 지정하지 않는 한 모든 변수를 초기화합니다.
초기화되지 않은 변수가 허용되는 언어에서도 많은 컴파일러가 초기화되지 않은 변수의 사용을 식별하여 컴파일 시 오류로 보고합니다.
「 」를 참조해 주세요.
레퍼런스
- ^ 스트럭시
- ^ memcpy()
- ^ "ISO/IEC 9899:TC3 (Current C standard)" (PDF). 2007-09-07. p. 126. Retrieved 2008-09-26. 섹션 6.7.8, 제10항
- ^ "Java Language Specification: 4.12.5 Initial Values of Variables". Sun Microsystems. Retrieved 2008-10-18.