2012-05-24 3 views
2

정적 데이터에 대한 포인터 배열을 갖고 싶습니다. 예를 들어C++ 함수에서 정적 double에 대한 포인터의 배열

void func(...) { 
    ... 
    static int mysize = initial_size; 
    static double* d[3] = {new double[mysize], new double[mysize], new double[mysize]}; 
    for(int i=0; i < 3; ++i) { 
     if(cond) { 
      //-re-allocate d if necessary. 
      use d here; 
     } 
     else { 
      use d here; //-since d is static; it persists and so this is justified? 
     } 
    } 
    //-Can I get away with not deleting d here?? 
    } 

제 생각에는 d가 정적 double에 대한 포인터 배열이므로, 한 번은 함수 안에 할당되므로 모든 것이 범위를 벗어나면 잘 지워질 것입니다. 나는 어떻게 든 생각하지 않는다. 이것은 아마도 희망적인 사고이고 기억 누출로 이어질 것입니까?

아마 여기서 정적 C++ 벡터를 사용하는 것이 더 낫습니다. 일부 조건 (예 : cond 또는 부정의 조건과 같은 일부 조건이 충족되는 경우)이 충족 될 때 d에서 이전에 계산되고 저장된 데이터를 다시 사용하기 위해 여기서 정적을 사용하려고합니다. 희망이 어떤 아이디어에 대한 사전에 의미와 감사합니다.

+2

결코 할당이 해제되지는 않지만 어쨌든 프로세스의 수명이 지속되므로 누가 신경을 씁니까? – ildjarn

+0

@ildjarn : 누군가 나처럼 생각하면 다행입니다.하지만 여전히, 저의 어떤 구석은 조금 걱정됩니다. 오 잘. –

답변

1

는 @AdamLiss 당신이 재 할당 D에서 메모리 누수가 수 위의 말처럼 만약 당신이 다시 할당하는 전에 기존 배열을 삭제 조심하지 않으면 필요한 단계 :

void func(...) { 
    static int mysize = initial_size; 
    static double* d[3] = {new double[mysize], new double[mysize], new double[mysize]}; 
    for(int i=0; i < 3; ++i) { 
    if(cond) { 
     d[i] = new double[2*mysize]; // LEAK! 
     use d here; 

하더라도 이 같은 삭제 기억 : 새로운 할당, 예외를 throw 삭제 메모리를 가리키는 d[0]를 떠나,하지만 방법은 그것을 말할 할 수 있기 때문에 버그가, 그렇게 할 때 능있다

void func(...) { 
    static int mysize = initial_size; 
    static double* d[3] = {new double[mysize], new double[mysize], new double[mysize]}; 
    for(int i=0; i < 3; ++i) { 
    if(cond) { 
     delete[] d[i]; 
     d[i] = new double[2*mysize]; 

d[0]이 참조 해제 된 경우 n next가 호출됩니다. 정의되지 않은 동작입니다.

void func(...) { 
    static int mysize = initial_size; 
    static double* d[3] = {new double[mysize], new double[mysize], new double[mysize]}; 
    for(int i=0; i < 3; ++i) { 
    if(cond) { 
     double* tmp = new double[2*mysize]; 
     std::swap(tmp, d[i]); 
     delete[] tmp; 

하지만 동적 메모리 관리하는 벡터를 사용하는 경우에는 문제가 발생하지 않도록 다음과 같습니다 :

이 확인 될 것 이것은 또한 쿼리 할 수 ​​있다는 장점이 있습니다

void func(...) { 
    int mysize = initial_size; 
    typedef std::vector<double> dvec; 
    static dvec d[3] = {dvec(mysize), dvec(mysize), dvec(mysize)}; 
    for(int i=0; i < 3; ++i) { 
    if(cond) { 
     //-re-allocate d if necessary. 
     d[i].resize(2*mysize); 
     use d here; 
    } 
    else { 
     use d here; 
    } 
    } 
} 

을 기존 크기는 d[i].size()이며 다시 할당 할 때 수동으로 이전 배열의 요소를 새 배열로 복사하지 않아도됩니다.

+0

고마워, 내가 게시한지 오래 전에 끝난거야. 미안하지만, 내 질문을 올린 후 페이지를 다시 방문하지 않았다. 그러나 내가이 문제를 해결하는 방식으로 당신이 대답 했으므로, 저는 이것이 대답이 될 것이라고 투표하고 있습니다. 모두에게 감사드립니다. –

3

new으로 할당되지 않았기 때문에 d을 삭제하면 오류가 발생합니다. 그러나 개별 요소 new으로 할당 된이므로 메모리가 고아가되지 않도록주의해야합니다.

+0

"기억을 잃어 버리지 않도록 조심해야합니다"라는 말의 의미를 설명해 주시겠습니까? 가능한 재배문에 대한 언급을 언급하고 있습니까? 나는 개인적으로 통계를 삭제하지 않는 문제를 보지 않기 때문에 (ildjarn은 위에서 언급 한 것처럼). – nijansen

+1

'd '의 요소는 정적이 아니며 힙의 메모리를 가리키는 포인터이며, 이러한 요소에 새 값을 할당하면 이전에 가리킨 메모리가 누출됩니다. –

+0

@Jonathan Wakely 아, 무슨 뜻인지 알 것 같아요. 그래서 만약 내가 올바르게 해석했다면'static int * a [1] = {new int (42)}'는 안전하지 못하지만'static int const * a [1] = {new int (42)}'는 괜찮을까요? – nijansen

1

코드는 기본적으로 괜찮습니다. 시사점은 다음과 같습니다 퓨리 같은

  • 메모리 사용 검사 도구, 보험 및 Valgrind의 잠재적 메모리 누수에 대한 자세한 노이즈를보고 할 수 있지만, 그 자체의 단지 소음입니다. 스레드 별 복사본 애플리케이션 영역 별 복사본 쉽게 유닛 테스팅 프로세스를 재시작 할 필요없이 허용 호출자 func에 함수 파라미터로 다운 d 통과 갖는 -

  • static가 어렵게 스레드 안전성 코드를 생성 할 수있다 평생의 완전한 클라이언트 제어.

  • 응용 프로그램이 func()에 대한 호출을 완료 한 후 시스템 종료 전에 다른 메모리 집약적 인 계산을 시작하면 추가 단계/단계가 도입된다고 가정하면 메모리는 여전히 할당됩니다.그것은 당신에게 중요하지 않을 수 있습니다. 특히 가상 주소 공간이 많아서 디스크로 스왑되도록 할 수는 있지만, 코드가 발전함에 따라 잠재적 인 유지 관리 문제가 될 수 있습니다.

+0

유용한 의견을 보내 주셔서 감사합니다. 이것을 염두에 두려고 노력할 것입니다. –

관련 문제