2012-06-26 2 views
0

저는 C++에서 상당히 큰 네트워크 시뮬레이터를 작성하고 있습니다. 필자는 개별적인 조각들을 내가 개발할 때마다 정기적으로 테스트 해왔다. 그리고 모든 것을 합친 후에는 시뮬레이터에 부과하는 하중이 너무 크지 않은 한 작동하는 것처럼 보인다. (P2P 콘텐츠 배포 시뮬레이터이므로 다른 " 내용 "시뮬레이터가 처리해야 할 더 많은 데이터 전송을 소개합니다). 시뮬레이션되는 서로 다른 컨텐츠의 수에 대한 특정 임계 값을 초과하는 항목은 수 분의 원활한 실행 후에 갑자기 SIGSEGV가됩니다. 결국 메모리 누수가 너무 커져서 엉망이되었다고 가정했지만 임계 값 아래의 매개 변수로 실행되는 valgrind는 완벽하게 종료되었습니다.프로그램 매개 변수가 일정한 임계 값을 초과하면 분할 오류가 발생합니다.

==5987== Invalid read of size 8 
==5987== at 0x40524E: Scheduler::advanceClock() (Scheduler.cpp:38) 
==5987== by 0x45BA73: TestRun::execute() (TestRun.cpp:73) 
==5987== by 0x45522B: main (CDSim.cpp:131) 
==5987== Address 0x2e63bc70 is 0 bytes inside a block of size 32 free'd 
==5987== at 0x4C2A4BC: operator delete(void*) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) 
==5987== by 0x405487: Scheduler::advanceClock() (Scheduler.cpp:69) 
==5987== by 0x45BA73: TestRun::execute() (TestRun.cpp:73) 
==5987== by 0x45522B: main (CDSim.cpp:131) 
==5987== 
==5987== Invalid read of size 4 
==5987== at 0x40584E: Request::getSimTime() const (Event.hpp:45) 
==5987== by 0x40525C: Scheduler::advanceClock() (Scheduler.cpp:38) 
==5987== by 0x45BA73: TestRun::execute() (TestRun.cpp:73) 
==5987== by 0x45522B: main (CDSim.cpp:131) 
==5987== Address 0x2e63bc78 is 8 bytes inside a block of size 32 free'd 
==5987== at 0x4C2A4BC: operator delete(void*) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) 
==5987== by 0x405487: Scheduler::advanceClock() (Scheduler.cpp:69) 
==5987== by 0x45BA73: TestRun::execute() (TestRun.cpp:73) 
==5987== by 0x45522B: main (CDSim.cpp:131) 
==5987== 

내가이 수도 알고 : 나는 특정 시점 이후, 컨텐츠 번호의 임계 값을 사용하여 Valgrind의와 프로그램을 실행하려고하면 그러나, 나는 이전에 아무런 문제를 발표하지 기능의 메모리 액세스 에러가 발생하기 시작 전체 코드를 보지 않고 대답을하기는 어려울 지 모르지만 여기에서 무슨 일이 벌어 질지에 대한 "하이 레벨"힌트가 있습니까? 정상적으로 작동하는 것처럼 보이는 기능이 갑자기 오작동하는 이유를 이해할 수 없습니다. 내가 놓친 게 분명 할까?

이전 Valgrind의 로그에 incriminated 행은 다음 블록 if (nextEvent->getSimTime() < this->getSimTime())입니다 :

pendingEvents가 부스트 :: 힙 :: binomial_heap입니다
bool Scheduler::advanceClock() { 
    if (pendingEvents.size() == 0) { 
    std::cerr << "WARNING: Scheduler::advanceClock() - Empty event queue before " 
     "reaching the termination event" << std::endl; 
    return false; 
    } 
    const Event* nextEvent = pendingEvents.top(); 
    // Check that the event is not scheduled in the past 
    if (nextEvent->getSimTime() < this->getSimTime()) { 
    std::cerr << "Scheduler::advanceClock() - Event scheduled in the past!" << 
     std::endl; 
    std::cerr << "Simulation time: " << this->getSimTime() 
     << ", event time: " << nextEvent->getSimTime() 
     << std::endl; 
    exit(ERR_EVENT_IN_THE_PAST); 
    } 
    // Update the clock with the current event time (>= previous time) 
    this->setSimTime(nextEvent->getSimTime()); 
    ... 

.

+0

'nextEvent' 또는'this'가 유효하지 않은 포인터 일 가능성이 높습니다. –

+0

@OliCharlesworth : O RLY ??? 하하는 단지 농담이야. 일종의. – Daniel

+0

@Daniel : 여기에 제공된 정보보다 더 유용한 결론에 도달 할 수 있을지 확신 할 수 없습니다. –

답변

1

마침내 문제가 무엇인지 발견했습니다. 이벤트가 완료하고 목록에서 제거 될 필요가되었을 때, 내 코드는 다음과 같이 갔다 :

문제는 oracle->notifyCompletedFlow() 동적으로 예약 된 이벤트의 우선 순위를 업데이트 스케줄러에 대한 몇 가지 방법을 호출이었다
... 
// Data transfer completed, remove event from queue 
// Notify the oracle, which will update the cache mapping and free resources 
// in the topology 
oracle->notifyCompletedFlow(nextEvent, this); 
// Remove flow from top of the queue 
pendingEvents.pop(); 
handleMap.erase(nextEvent); 
delete nextEvent; 
return true; 

(예 : 네트워크에서 사용 가능한 대역폭의 변화에 ​​대응하기 위해), 따라서 어떤 경우에는 pendingEvents.pop()으로 큐의 맨 윗부분을 제거했을 때 다른 이벤트가 발생하여 거기에 삭제 된 nextEvent를 남겨 두었습니다. Oracle을 호출하기 전에 큐를 팝핑함으로써 문제가 해결되었습니다.

더 빠른 답변을 이끌어 낼 수있는 코드 조각을 남겨두고 사과 드리며, 실수로 배우려고합니다. 올바른 방향으로 나를 안내해 주셔서 감사합니다.

0

뭔가있을 수 있습니다 const Event* nextEvent = pendingEvents.top(); 보이는 것 같습니다 pendingEvents은 일종의 스택입니다. 당신이 시도 할 수 있습니다 :

  1. 악기 (수단이 표준 출력 :: cerr 일부 추적 등의 간단한 추가 | 파일) 당신이 할당하고 malloc에이/새로운 사용하는 경우 (메모리 할당을 해제 코드, 무료/삭제);
  2. 디버깅 도구로, 역 참조 (operator ->) 중에 포인터 유효성을 검사하는 이벤트 용 스마트 포인터를 사용해보십시오.
관련 문제