2015-01-10 4 views
-3

INT의 main() { 정렬 _aligned_free 메모리 함수에 의해 해제되지

  1. INT * 정렬;

    // 정렬 값 0xcccccccc ??? {

  2. }

  3. 정렬 = INT (*) _ aligned_malloc (는 sizeof (INT) * 1000, 16);

    // 정렬 값 0x001d9490 -842150451 {

  4. }

  5. _aligned_free (정렬);

    //// 정렬 값 0x001d9490 {} -17891602 변경하지 않은 주소

  6. 정렬 == * 100;

  7. int * y;

    // Y 값 0xcccccccc ??? {

  8. }

  9. 새로운 Y = INT();

    // Y 값 0x001d9480 {0}

  10. (Y)을 삭제;

    // Y 값 0x00008123 ??? {} 주소

    변경된
  11. * Y = 100; // 예외를 제공합니다

}

내 질문 :

왜 4 행의 코드가 예외를 제공하지 않습니다? 메모리가 제대로 _aligned_free에 의해 해제되지 않는다는 것을 의미합니까? 그렇다면 _aligned_malloc에 ​​의해 할당 된 메모리를 어떻게 해제해야합니까?

+0

1과 5의 경우 초기화되지 않은 값을 읽는 중입니다. 이는 버그입니다. 4와 8의 경우, 당신이 풀어 놓은 메모리에서 읽고 있습니다, 그것은 버그입니다. "왜 그 안에 버그가있는 코드는 안되니?"라는 일반적인 답은 "우리가 버그를 수정하는 이유는 무엇인가?" "버그가있는 코드는 예상대로 작동하지 않으며 버그를 수정하면 코드가 배고 있다". –

+0

데이비드에게 감사드립니다. 나는 이것이 고쳐 져야 할 버그라고 지적했다. 이 질문에 대한 나의 의도는 정렬 된 메모리 (_aligned_free 이후)가 잘못된 메모리로 설정되지 않는 반면, y (삭제 후)의 경우에는 메모리가 가리키는 이유입니다. 컴파일러 또는 힙 deallocator 일 (더 많은 종류의 의견을 읽은 후) 나에게 보인다. 방금 그걸 확인하고 싶었어. 그게 전부 야. – coder

답변

0

라인 4의 코드는 아무 것도하지 않습니다. == (동등성 테스트)을 사용하지 않고 해당 라인에 = (할당)을 사용하고 있습니다. 실제로, 일을합니다. 은 방금 해방 한 메모리 블록의 주소에서을 읽으려고 시도하고 그 값을 100으로 비교합니다. 이것은 반드시 예외를 유발하지 않을 수도 있습니다 - 많은 힙 관리자는 프로세스 주소 공간에 할당 된 큰 블록으로 덩어리를 조각 낼 것입니다. 따라서 힙 관리자를 다시 사용할 수 있도록 블록을 표시하면됩니다. 해제 후에이 공간을 읽거나 쓰면 매번 예외가 발생하지 않을 수도 있지만 (여전히 프로세스의 유효한 힙 공간에 포함될 수 있기 때문에) 오류가 발생합니다.

또한 _aligned_free을 호출 한 후 포인터 값 (aligned)이 변경되어서는 안됩니다. 즉 메모리가 해제되지 않았 음을 의미하지는 않습니다.

+0

감사합니다. 나는 예외가 없다면 메모리가 항상 _aligned_free에 의해 해방 될 것이라는 점을 알게되었다. – coder

0

int * aligned;

// 정렬 된 값 0xcccccccc {???}

당신은 포인터를 초기화하지 않았다, 그래서 main이 시작되기 전에 어떤 쓰레기 값 것은 거기 있어요. null을 시작하려면 int *aligned = NULL;을 입력하십시오.

정렬 = (int *) _ aligned_malloc (sizeof (int) * 1000, 16);

는 // 정렬 값 0x001d9490 -842150451 {}

는 OK

_aligned_free을 (정렬) 보인다; 정렬 값 0x001d9490 {-17891602} 주소가 free 호출

없음을 변경하지 않았다 ////

는 전달 된 포인터를 변경합니다. 적.

* aligned == 100;

frasnian이 지적했듯이, 이것은 비교를 수행하고 그 결과를 버립니다. 하지만 할당을 할당으로 변경하더라도 해제 된 포인터를 역 참조하는 것은 정의되지 않은 동작입니다. 그리고 그것은 어떤 일이 일어날 수도 있음을 의미합니다 : 일할 수 있고, 충돌 할 수 있으며, 예기치 않은 뭔가를 할 수 있습니다.

int * y;

// Y 값 0xcccccccc {} ???

다시

, 초기화.

y = new int();

좋아

// y 값은 {0}, 당신은 int에 대한 포인터를 가지고 0x001d9480.

삭제 (y);

// Y 값 0x00008123 ??? {} 주소 예기치

바뀌었다. 컴파일러의 기능 일 수 있습니다. 레지스터 재사용 최적화 수 있습니다.

* y = 100; // 예외가 발생했습니다.

삭제 된 포인터를 역 참조했기 때문에 다시 정의되지 않은 동작 영역에 있기 때문입니다. 외관상으로는 당신의 플래트 홈은 정수를위한 괴상한 주소를 좋아하지 않는다.모든 플랫폼에서 예외가 발생하는 것은 아닙니다.


규칙은 free 또는 delete에 통과 한 포인터가 사라지고 있다는 점이다. 죽은. 전 (前) 포인터. 비트 데이지를 밀어 올리십시오. 피요르드에 대한 피고인. 더 이상은 아니다.

레지스터에 값이 남아있을 수 있지만 더 이상 유효하지 않으므로 사용해서는 안됩니다. 컴파일러는 데드 포인터를 사용하려고하는 경우를 잡아낼 수 없습니다.

관련 문제