Assertion Failure

Collapse
X
 
  • Time
  • Show
Clear All
new posts
  • IanWright
    New Member
    • Jan 2008
    • 179

    Assertion Failure

    I'm struggling with an assertion failure and was wondering if anyone can help. I understand why its failing, but don't quite have the C++ knowledge to be able to decide how it should be fixed...

    The line that causes the fault is within the updateStats_thr ead() method.

    Code:
    delete(tq_current);
    This works while there are still more elements within the timing queue. However once we reach the last one, so tq_current->next looks like garbage it errors with a _BLOCK_TYPE_IS_ VALID failing its check on phead->nBlockUse.

    I've tried things like if(tq_current->next) which if I'm not mistaken checks that tq_current->next is not null before deleting it, but that didn't work and never entered the code at all...

    I've listed the structures of the queue, the PERIODS are set to different times in seconds. Also I've shown the update code where the actual timing queue appears to get added to... Any advice would be muchly appreciated!

    Code:
    typedef struct _timingQueue {
      struct timeval time ; 
      double qryTime ;
      struct _timingQueue *next ;
    } TimingQueue ;
    Code:
    // updates the timing queues
    double timing(char *msg, struct timeval t1, struct timeval t2)
    {
      double rtn = timediff(t1, t2);
    
    	TimingQueue *tqp = new TimingQueue ;
        tqp->time = t1 ;
    	tqp->qryTime = rtn ;
        tqp->next = NULL ;
    
        pthread_mutex_lock(&timingMutex) ;
        timeQEnd->next = tqp ;
        timeQEnd = tqp ;
        pthread_mutex_unlock(&timingMutex) ;
    
      if (msg)
        sprintf (msg, "%f", rtn) ;
      return(rtn) ;
    }

    Code:
    	
    void * updateStats_thread(void *)
    {
    	double lastQueryAvg1 = -1 ;
    	double lastQueryAvg2 = -1 ;
    	double lastQueryAvg3 = -1 ;
    	double lastQueryAvg1Cnt = 0 ;
    	double lastQueryAvg2Cnt = 0 ;
    	double lastQueryAvg3Cnt = 0 ;
    	int period1 = 0 ;
    	int period2 = 0 ;
    	int period3 = 0 ;
    	double currentDiff ;
    
    	double totalQueryTime1=0.0;
    	double totalQueryTime2=0.0;
    	double totalQueryTime3=0.0;
    
    	struct timeval now ;
    	struct timeval then ;
    
    	gettimeofday(&then, NULL) ;
    
    	while (running) {
    
    		// First of all, let's only bother with updates if the window is visible.
    		if (visible) {
    		    period1 = 0 ;
    			period2 = 0 ;
    			period3 = 0 ;
    			totalQueryTime1=0.0;
    			totalQueryTime2=0.0;
    			totalQueryTime3=0.0;
    
    			gettimeofday(&now, NULL) ;
    
    			// And only update every 5 seconds.
    			if (now.tv_sec - then.tv_sec >= UPDATE_PERIOD)
    			{
    				TimingQueue *tq_current = timeQ.next ;
    				TimingQueue *tq_prev = &timeQ ;
    
    				while (tq_current)
    				{
    					double currentDiff = timediff(tq_current->time, now) ;
    					if (currentDiff >= 0) {
    						if (currentDiff <= PERIOD1)
    						{
    							totalQueryTime1+=tq_current->qryTime;
    							period1++ ;
    						}
    						if (currentDiff <= PERIOD2)
    						{
    							totalQueryTime2+=tq_current->qryTime;
    							period2++ ;
    						}
    						if (currentDiff <= PERIOD3) {
    						  totalQueryTime3+=tq_current->qryTime;
    						  period3++ ;
    						} else {
    							// drop it from the queue
    							if (tq_current != timeQEnd)
    							{
    								tq_prev->next = tq_current->next ;
    							} else {
    								pthread_mutex_lock(&timingMutex) ;
    								timeQEnd->next = NULL ;
    								timeQEnd = tq_prev ;
    								pthread_mutex_unlock(&timingMutex) ;
    							}
    
    						    delete(tq_current);
    						    tq_current = NULL ;
    							break ;
    						}
    					}
    					tq_current = tq_current->next ;
    				}
    				/* Don't change the stats if we haven't been doing anything */
    				if (period1 > lastQueryAvg1Cnt)
    				{
    					lastQueryAvg1 = totalQueryTime1/period1; 
    				}
    				lastQueryAvg1Cnt = period1;
    
    				if (period2 > lastQueryAvg2Cnt)
    				{
    					lastQueryAvg2 = totalQueryTime2/period2; 
    				}
    				lastQueryAvg2Cnt = period2;
    				if (period3 > lastQueryAvg3Cnt)
    				{
    					lastQueryAvg3 = totalQueryTime3/period3; 
    				}
    				lastQueryAvg3Cnt = period3;
    
    				char msg[100];
    				WCHAR wMsg[100] ;
    				sprintf (msg, "Avg qry load: %3.2f, %3.2f, %3.2f qry/s", 
    					period1/PERIOD1, period2/PERIOD2, period3/PERIOD3) ;
    				wsprintf (wMsg, L"%hs",msg) ;
    				SetWindowText(StatusLines[queryThrougput], wMsg) ;
    				sprintf (msg, "Avg qry time: %3.2f, %3.2f, %3.2f s", lastQueryAvg1, lastQueryAvg2, lastQueryAvg3) ;
    				wsprintf (wMsg, L"%hs",msg) ;
    				SetWindowText(StatusLines[queryAvgTime], wMsg) ;
    				then = now ;
    			}
    		}
    		Sleep(1000) ;
    	}
    	return NULL ;
    }
  • Banfa
    Recognized Expert Expert
    • Feb 2006
    • 9067

    #2
    Originally posted by IanWright
    Code:
    	
    <snip>
    								timeQEnd->next = NULL ;
    								timeQEnd = tq_prev ;
    <snip>
    These 2 lines of code are the wrong way round.

    Comment

    • IanWright
      New Member
      • Jan 2008
      • 179

      #3
      Originally posted by Banfa
      These 2 lines of code are the wrong way round.
      Banfa, thanks very much, it appears you are correct. Could you explain why this is the case, as I'm not sure even after looking at it...

      Thanks,

      Ian

      Comment

      • Banfa
        Recognized Expert Expert
        • Feb 2006
        • 9067

        #4
        OK taking a look at an abstract list of n items then the last 2 items would be

        Item(n-1){Data, Next=&Item(n)}
        Item(n){Data, Next=NULL}

        I hope you understand my syntax, and the end, previous and current pointers are

        EndPtr = &Item(n)
        PrevPtr = &Item(n-1)
        CurrentPtr = &Item(n)

        When you execute

        1: EndPtr->Next = NULL;
        2: EndPtr = PrevPtr;
        3: FreeMemory(Curr entPtr);


        Then EndPtr is pointing to item(n) so line 1 NULLs the already NULL Next Pointer in item(n), line 2 Sets EndPtr to point at item(n-1) and line 3 releases the memory of item(n). You are left with

        Item(n-1){Data, Next=&Item(n)}
        EndPtr = &Item(n-1)

        Note that the Next pointer of the last item in them list now (item(n-1)) still points to where item(n) used to be but that that memory location has been freed, ie it is no longer valid.

        If on the same list you execute

        1: EndPtr = PrevPtr;
        2: EndPtr->Next = NULL;
        3: FreeMemory(Curr entPtr);

        The line 1 sets EndPtr to item(n-1), line 2 sets the next pointer of EndPtr, which is now item(n-1) to NULL and line 3 releases the memory of item(n). You are left with

        Item(n-1){Data, Next=NULL}
        EndPtr = &Item(n-1)

        Note that now the next pointer in item(n-1) is NULL.

        In most lists the Next pointer of the final entry is supposed to be NULL as a marker they way you had it did not preserve this end condition. However by swaping the 2 lines of code I suggested you altered the structure that EndPtr->Next = NULL; operated on so that it did preserve the list end condition correctly.

        Comment

        • IanWright
          New Member
          • Jan 2008
          • 179

          #5
          Banfa,

          Thanks very much. I do understand your syntax and I think I also understand your explanation, but its much appreciated!

          Ian

          Comment

          Working...