c++ malloc 예제




컴파일러가 realloc을 최적화 할 수 있습니까? (3)

그들은 그렇게 할 수 없습니까?

어쩌면이 경우에는 최적화가 이루어지지 않을 수 있습니다. 기능 차이가있을 수 있습니다.

150 바이트의 할당 가능한 메모리가 남아 있으면,
data = malloc(100); data = realloc(data, 200); 100 바이트가 소비되고 (유출 된) NULL 이 반환되고 50 개가 남습니다.

data = malloc(200); 0 바이트가 소비되고 (누출되지 않음) NULL 이 반환되고 150은 남아 있습니다.

이 좁은 경우 다른 기능 을 사용하면 최적화를 방해 할 수 있습니다.

컴파일러가 realloc을 최적화 할 수 있습니까?

아마도 - 나는 그것이 가능할 것이라고 기대할 것입니다. 그러나 컴파일러를 향상 시켜서 할 수있는 시점을 결정하는 것은 효과가 없습니다.

성공한 malloc(n); ... realloc(p, 2*n) malloc(n); ... realloc(p, 2*n)malloc(2*n); 과 다릅니다 malloc(2*n); 언제 ... 일부 메모리를 설정할 수 있습니다.

빈 코드가 메모리를 설정하지 않은 경우에도 컴파일러의 설계를 넘어서 ... 보장 할 수 있습니다.

최적화 된 realloc 에 불필요한 호출을하는 것이 유용 할 수있는 상황을 발견했습니다. 그러나 clang이나 gcc와 같은 일은 godbolt 것입니다 ( godbolt ). - malloc 을 여러 번 호출하여 최적화가 이루어지고 있지만

예제 :

void *myfunc() {
    void *data;
    data = malloc(100);
    data = realloc(data, 200);
    return data;
}

나는 다음과 같이 최적화 될 것으로 기대했다.

void *myfunc() {
    return malloc(200);
}

clang도 gcc도 그것을 최적화하지 않는 이유는 무엇입니까? - 그렇게 할 수없는거야?


malloc / calloc / free / realloc의 자체 내장 버전을 번들로 제공하는 컴파일러는 작성자가 그렇게 생각할 경우 표시된 최적화를 합법적으로 수행 할 수 있습니다. 외부에서 제공되는 함수로 연결되는 컴파일러는 관찰 가능한 부작용과 같은 함수 호출의 정확한 시퀀스를 고려하지 않았 음을 문서화하면 이러한 최적화를 수행 할 수 있지만 이러한 처리는 조금 더 어려울 수 있습니다.

malloc ()과 realloc () 사이에 기억 장치가 할당되거나 할당 해제되지 않으면 malloc ()이 수행되고 realloc () 크기가 malloc () 크기보다 클 때 realloc malloc () 및 realloc () 작업을 하나의 큰 할당으로 통합하는 것이 좋습니다. 그러나 임시로 메모리 상태가 변경 될 수있는 경우 이러한 최적화로 인해 성공해야하는 작업이 실패 할 수 있습니다. 예를 들어, 주어진 시퀀스 :

void *p1 = malloc(2000000000);
void *p2 = malloc(2);
free(p1);
p2 = realloc(p2, 2000000000);

p1이 해제 될 때까지 시스템에서 p2에 대해 2000000000 바이트를 사용할 수 없습니다. 코드를 다음과 같이 변경해야하는 경우 :

void *p1 = malloc(2000000000);
void *p2 = malloc(2000000000);
free(p1);

그 결과 p2 할당에 실패하게됩니다. 표준은 할당 요청이 성공할 것이라고 결코 보장하지 않기 때문에 그러한 행동은 부적합하지 않을 것입니다. 한편, 다음은 "준수하는"구현 일 것입니다.

void *malloc(size_t size) { return 0; }
void *calloc(size_t size, size_t count) { return 0; }
void free(void *p) {  }
void *realloc(void *p, size_t size) { return 0; }

그러한 구현은 대부분 다른 것들보다 더 "효율적"이라고 여겨 질 수도 있지만 위의 기능들이 코드 경로에서 호출되는 아주 드문 경우를 제외하고는 매우 유용하다고 간주하기에는 다소 혼란 스럽습니다. 결코 실행되지 않았습니다.

적어도 본래의 질문 에서처럼 단순한 경우에는 표준이 명확하게 최적화를 허용한다고 생각합니다. 다른 방법으로 성공할 수있는 작업이 실패 할 수도있는 경우에도 표준은 여전히이를 허용합니다. 대부분의 컴파일러가 최적화를 수행하지 않는 이유는 저자가 안전하고 유용 할 수있는 사례를 식별하는 데 필요한 노력을 정당화하기에 충분할 것이라고 생각하지 않기 때문입니다.


하지만 두 번째 realloc ()에서 사용할 첫 번째 malloc ()의 반환 값을 확인하지는 않습니다. 그것은 단지 NULL 일 수도 있습니다.

컴파일러는 첫 번째 호출의 반환 값에 대해 부당한 가정을하지 않고 어떻게 두 호출을 하나의 호출로 최적화 할 수 있습니까?

그런 다음 또 다른 가능한 시나리오가 있습니다. FreeBSD는 이전에 malloc + memcpy + old 포인터였던 realloc()사용했습니다 .

여유 메모리의 230 바이트 만 남아 있다고 가정하십시오. 이 구현에서 ptr = malloc(100) 다음에 realloc(ptr, 200) 이 실패하지만 단일 malloc(200) 은 성공합니다.





compiler-optimization