2012-10-11 3 views
0

가능한 중복 : 나는 이상한 일이 일어나고 있음을 깨달았을 때 난 그냥 포인터와 함께 연주했다
Why don’t I get a segmentation fault when I write beyond the end of an array?세분화 오류가 발생하지 않는 이유는 무엇입니까?

. 나는 우리가 예를 들어, strcpy와을 사용하여 다른 문자열 DST에 됨 src 문자열 을 복사 할 때마다, 우리는 SRC에 필요한 공간을 할당해야한다고 알고 있습니다.

char *dst,*src = "asdlskafksdhfklshfkshdkfhksdhfçsahdflçsdhfçklshadfç"; 

    dst = (char*)malloc(1); //only one char allocated 
    strcpy(dst,src); 

    printf("dst=%s.\n",dst); 

이 코드는 실행하지 않아야합니다. 그러나 그것은 일어나지 않습니다. 코드가 실행되고 srcdst에 성공적으로 복사하고 dst이라는 매력을 인쇄합니다. 누군가 왜 나 한테 설명해 줄 수 있니? 왜 이런 일이 일어나고있는거야?

+9

정의되지 않은 동작입니다. 프로그래머가 의도 한대로 수행 될 수 있습니다. 아니. –

+0

@DanielFischer : C를 발명 한 과학적으로 엄격한 사람들이 C 스펙에서 너무 많은 세부 사항을 제외 시켰다는 사실에 조금 실망하지 않는가? C에는 너무 많은 "정의되지 않은 동작 기능"이 있습니다! – Razvan

+0

@Razvan : 이것은 매우 의도적입니다. – akappa

답변

2

C의 성능 중 일부는 내장 된 오류 검사 방법이별로 없다는 것입니다. 모든 strcpy 알고 올바른 유형의 포인터를 전달했습니다, 얼마나 많은 할당 된 메모리를 가리키는 지 알 수 없습니다. 결과 머신 코드는 단순히 src 포인터에서 첫 번째 null 바이트까지 읽은 다음 dst 포인터에 붙여 넣습니다. 다른 사람의 메모리를 덮어 쓰지 않으면 오류가 없습니다.

"다른 사람의 기억"이란 무엇입니까? 일반적으로 프로세스는 pages에 메모리가 할당됩니다. malloc을 1 바이트로 만들 때, 프로세스는 필요에 따라 슬라이스하고 다이스하기 위해 전체 페이지 메모리 (아마도 수 킬로바이트)를받습니다. 분할 오류는 프로세스가 할당 된 페이지 외부에 쓰기를 시도 할 때 발생합니다 (and for other reasons). 오류는 일반적으로 메모리 관리를 수행하는 운영 체제 및/또는 하드웨어에 의해 생성됩니다. src는 단지 12 바이트 밖에 없으므로 프로세스의 페이지 외부로 이동할 가능성은 거의 없습니다. src를 긴 문자열로 만들면 기대하는 segfault를 얻을 수 있습니다.

다양한 트릭을 통해 메모리 실수를 확인하는 디버깅에 사용되는 다양한 malloc 래퍼 라이브러리가 있습니다. ValgrindElectric Fence이 가장 유명합니다.

추신 : 나는이 물건이 어떻게 작동하는지 정확히 알기 어렵지만, "그것은 정의되지 않은 행동"보다 만족 스럽습니다. 제 설명이 부족한 부분을 자유롭게 편집하십시오.

+0

감사합니다. 제 생각에 '다른 사람의 기억'에 대한 개념이 잘못되었거나 매우 모호했습니다. 나는 Valgrind를 실행했고 즉시 문제를 확인했습니다. ;) – Leaurus

+1

'malloc '은 * kernel * (일반적으로)에 의해 할당 된 페이지를 관리하는 사용자 공간 라이브러리의 일부라고 덧붙일 수 있습니다. 그렇지 않으면 "free()를 호출 할 때 페이지 전체를 할당 해제합니까?"라는 혼란이있을 수 있습니다. – rliu

+0

그러나 free() 호출로 전체 페이지 또는 여러 페이지가 비어 있다고 상상해보십시오. 그럼 그들은 할당 해제됩니다, 그렇죠? – Leaurus

1

릴리스 빌드에서 * dst는 프로세스의 주소 공간에있는 일부 메모리를 가리 킵니다 - 쓰기 만하면 응용 프로그램과 같은 유용한 정보가있을 경우 충돌합니다.

디버그 빌드에서 컴파일러는 * dst를 0으로 설정하거나 0xDEADBEEF와 같은 인식 가능한 값을 설정하므로이 사실을 알 수 있습니다.

1

할당 된 메모리 외부에 쓸 경우 결과는 정의되지 않습니다. 운이 좋다면 세고 폴트를 얻습니다. 운이 좋으면 다른 변수를 덮어 씁니다. 최종선 : 무언가가 간다!

2

문자열이 힙에 할당됩니다. 힙의 크기는 1 바이트가 아니고 물리적 RAM (기본 Windows 콘솔 응용 프로그램 크기) 약 4kb입니다.

힙 외부의 메모리 영역에 쓸 때 세그먼트 화 오류 만 발생합니다. 그러나 응용 프로그램의 다른 부분에 대한 메모리가 손상 될 수 있습니다. 그러나 프로그램이 너무 작아서 할당 된 메모리를 초과하여 작성한 직후 종료되면 오류가 발생하지 않을 것입니다.