서버 종료시 객체를 올바르게 폐기


9

큰 C ++ 프로젝트를 진행 중입니다. REST API를 노출하는 서버로 구성되어 다른 많은 서버로 구성된 매우 광범위한 시스템을위한 단순하고 사용자 친화적 인 인터페이스를 제공합니다. 코드베이스는 상당히 크고 복잡하며 적절한 디자인을하지 않고도 시간이 지남에 따라 발전했습니다. 내 임무는 더 안정적이고 신뢰할 수 있도록 새로운 기능을 구현하고 이전 코드를 리팩터링 / 수정하는 것입니다.

현재 서버는 프로세스가 종료 될 때 종료되거나 폐기되지 않는 많은 수명이 긴 객체를 만듭니다. 이로 인해 Valgrind는 "위험한"누수로부터 수천 건의 (정상적으로) 합법적 인 누수를 구별하는 것이 불가능하기 때문에 누수 감지에 거의 사용할 수 없게됩니다.

내 생각은 모든 객체가 종료되기 전에 폐기되도록하는 것이지만,이 제안을 할 때 동료와 상사는 OS가 그 메모리를 어쨌든 (모든 사람에게 분명하게) 해제하고 객체를 폐기 할 것이라고 지적했습니다. 서버의 종료 속도가 느려집니다 (현재는 기본적으로에 대한 호출입니다 std::exit). "깨끗한"종료 절차가 반드시이를 사용해야한다는 것을 의미하지는 않습니다. 우리가 참을성이 없다고 느끼면 언제든지 전화 std::quick_exit하거나 kill -9프로세스를 진행할 수 있습니다.

"대부분의 Linux 데몬과 프로세스는 종료시 메모리 확보를 방해하지 않습니다"라고 대답했습니다. 내가 알 수 있지만 이미 메모리 손상, 이중 해제 및 초기화되지 않은 변수를 발견 했으므로 프로젝트에 정확한 메모리 디버깅이 필요하다는 것도 사실입니다.

당신의 생각은 무엇입니까? 나는 무의미한 노력을 추구하고 있습니까? 그렇지 않다면 어떻게 동료와 상사를 설득 할 수 있습니까? 그렇다면 왜, 어떻게해야합니까?


성능 인수 (합리적입니다!) 외에도 오래 지속되는 객체를 격리하고 정리 코드를 추가하는 것이 많은 노력입니까?
Doc Brown

답변:


7

모든 메모리를 해제하는 Valgrind 측정 중에 사용할 수있는 서버 프로세스에 스위치를 추가하십시오. 이 스위치를 사용하여 테스트 할 수 있습니다. 정상 작동 중에는 영향이 최소화됩니다.

우리는 1000의 객체를 릴리스하는 데 몇 분이 걸리는 프로세스를 오래 실행했습니다. 그냥 나가서 죽게하는 것이 훨씬 더 효율적이었습니다. 불행히도, 알다시피, 이것은 valgrind 또는 다른 도구를 사용하여 실제 메모리 누수를 감지하기 어려웠습니다.

이는 정상적인 성능에는 영향을 미치지 않으면 서 테스트에있어 좋은 타협이었습니다.


1
실용주의 FTW +1 측정에는 가치가 있지만 빠른 종료에도 가치가 있습니다.
로스 패터슨

2
명령 행 스위치의 대안으로 #ifdef DEBUG 블록 내에서 영구 객체의 삭제를 구현하는 것이 좋습니다.
Jules

3

여기서 핵심은 다음과 같습니다.

내가 알 수 있지만 이미 메모리 손상, 이중 해제 및 초기화되지 않은 변수를 발견 했으므로 프로젝트에 정확한 메모리 디버깅이 필요하다는 것도 사실입니다.

이것은 거의 직접적으로 코드베이스가 희망과 문자열 이상으로 함께 묶여 있음을 의미합니다. 유능한 C ++ 프로그래머에게는 이중 여유 공간이 없습니다.

실제 문제의 작은 증상 중 하나를 해결하는 것처럼, 당신은 코드가 Apollo 13 서비스 모듈만큼 신뢰할 수 있다는 점에서 무의미한 노력을 추구하고 있습니다.

RAII로 서버를 올바르게 프로그래밍하면 이러한 문제가 발생하지 않으며 질문의 문제가 제거됩니다. 또한 코드가 실제로 올바르게 실행될 수 있습니다. 따라서 분명히 최선의 선택입니다.


확실히 문제는 더 큰 그림에 있습니다. 그러나 더 나은 형태로 프로젝트를 리팩터링 / 재 작성할 수있는 리소스와 권한을 찾을 수있는 경우는 매우 드 rare니다.
Cengiz는

@CengizCan : 버그를 수정하려면 리팩토링해야합니다. 그것이 작동하는 방식입니다.
DeadMG

2

좋은 접근 방법 중 하나는 분류를 통해 동료와의 토론 범위를 좁히는 것입니다. 코드 기반이 크면 장수 개체에 대한 단일 이유가 아니라 여러 가지 (식별 가능한) 이유가 있습니다.

예 :

  • 누구도 참조하지 않는 장수명 물체 (실제 누출). 프로그래밍 논리 오류입니다. 시간이 지남에 따라 메모리 사용 공간이 커지고 응용 프로그램 품질이 저하되는 경우를 제외하고 우선 순위가 낮은 사람을 수정하십시오. 메모리 공간이 시간이 지남에 따라 커지면 우선 순위를 더 높게 수정하십시오.

  • 수명이 긴 개체는 여전히 참조되지만 더 이상 사용되지는 않지만 (프로그램 논리로 인해) 메모리 공간이 늘어나지 않습니다. 코드를 검토하고 그로 인한 다른 버그를 찾으십시오. 의도적 인 (성능) 최적화 인 경우 코드베이스에 주석을 추가하십시오.

  • "디자인에 의해"장수 개체. 예를 들어 싱글 톤 패턴. 특히 다중 스레드 응용 프로그램 인 경우 실제로 제거하기가 어렵습니다.

  • 재활용 된 개체. 장수명 개체가 항상 나쁘지는 않습니다. 그들은 또한 유익 할 수 있습니다. 고주파 메모리 할당 / 할당 해제 대신에, 현재 사용되지 않는 객체를 컨테이너에 추가하여 이러한 메모리 블록이 다시 필요할 때 그릴 수 있도록하면 응용 프로그램의 속도를 높이고 힙 조각화를 피할 수 있습니다. 그들은 특별한 "계기 / 체크 된"빌드에서 종료 시간에 쉽게 풀 수 있어야합니다.

  • "공유 객체"-여러 개의 다른 객체에 의해 사용 (참조)되는 객체로, 언제 객체를 해제 할 것인지 정확히 알 수 없습니다. 그것들을 참조 카운트 대상으로 바꾸는 것을 고려하십시오.

정리되지 않은 개체의 실제 이유를 분류 한 후에는 사례 별 토론을 통해 사례를 입력하고 해결 방법을 찾는 것이 훨씬 쉽습니다.


0

IMHO, 이러한 개체의 수명은 시스템을 종료 할 때 절대로 만들어져 죽지 않아야합니다. 이것은 우리 모두가 나쁜 나쁜 나쁜 나쁜 나쁜 글로벌 변수에 영향을 미칩니다. 특히 똑똑한 포인터 시대에는 게으름 이외의 다른 이유는 없습니다. 그러나 더 중요한 것은 누군가가 언젠가 처리해야 할 수준의 기술적 부채를 시스템에 추가하는 것입니다.

"기술 부채"의 개념은 누군가가 나중에 코드를 변경하고 싶을 때 이와 같은 지름길을 취할 때입니다. ", 또는 프로세스를 다시 시작하지 않고 서버를 전환 할 수 있기를 원합니다.) 건너 뛰는 작업을 수행하기 위해 노력해야합니다. 그러나 그들은 코드를 유지 관리 할 것이므로, 당신만큼 코드에 대해 거의 알지 못하므로 훨씬 더 오래 걸릴 것입니다 (20 % 이상 이야기하지 않고 20 배 이상 이야기하고 있습니다!). 그것이 당신이더라도, 당신은 몇 주 또는 몇 달 동안이 특정 코드를 연구하지 않았을 것입니다.

이 경우 서버 개체와 "장수명"개체간에 매우 긴밀한 연결이있는 것으로 보입니다. 레코드가 서버에 대한 연결보다 오래 지속될 수있는 경우도 있습니다. 서버에서 오브젝트에 대한 모든 단일 변경 사항을 유지 보수하는 것은 엄청나게 비쌀 수 있으므로, 실제로 서버를 실제로 변경하는 저장 및 업데이트 호출을 통해 스폰 된 오브젝트가 실제로 서버 오브젝트에 대한 핸들을 처리하는 것이 좋습니다. 이것을 일반적으로 활성 레코드 패턴이라고합니다. 보다:

http://en.wikipedia.org/wiki/Active_record_pattern

C ++에서는 각 활성 레코드에 서버에 weak_ptr이있어 서버 연결이 어두워지면 지능적으로 처리 할 수 ​​있습니다. 이 클래스는 필요에 따라 느리게 또는 배치로 채워질 수 있지만 해당 객체의 수명은 사용되는 위치에만 있어야합니다.

또한보십시오:

프로세스를 종료하기 전에 리소스를 확보하는 데 시간이 낭비됩니까?

다른


This reeks of global variables"해제해야하는 수천 개의 개체가"에서 "전세계에 있어야합니다"로 어떻게 이동합니까? 그것은 꽤 비약적인 논리입니다.
Doval

0

무한정 존속해야 할 오브젝트가 할당 된 위치를 쉽게 식별 할 수 있으면 대체 할당 메커니즘을 사용하여 오브젝트를 할당하여 valgrind leak 보고서에 표시되지 않거나 단일 할당으로 표시 될 수 있습니다.

아이디어에 익숙하지 않은 경우 c ++로 커스텀 메모리 할당을 무력화하는 방법에 대한 기사가 있지만 삭제를 전혀 처리 할 필요가 없으므로 솔루션이 기사의 예제보다 훨씬 간단 할 수 있습니다. !

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.