Main Content

Non-terminating call

Called function does not return to calling context

Description

This check on a function call appears when the following conditions hold:

  • The called function does not return to its calling context. The call leads to a definite run-time error or a process termination function like exit() in the function body.

  • There are other calls to the same function that do not lead to a definite error or process termination function in the function body.

When only a fraction of calls to a function lead to a definite error, this check helps identify those function calls. In the function body, even though a definite error occurs, the error appears in orange instead of red because the verification results in a function body are aggregated over all function calls. To indicate that a definite error has occurred, a red Non-terminating call check is shown on the function call instead.

Otherwise, if all the calls to a function lead to a definite error or process termination function in the function body, the Non-terminating call error is not displayed. The error appears in red in the function body and a dashed red underline appears on the function calls. However, following the function call, like other red errors, Polyspace® does not analyze the remaining code in the same scope as the function call.

You can navigate directly from the function call to the operation causing the run-time error in the function body.

  • To find the source of error, on the Source pane, place your cursor on the loop keyword and view the tooltip.

  • Navigate to the source of error in the function body. Right-click the function call and select Go to Cause if the option exists.

    If the error is the result of multiple causes, the option takes you to the first cause in the function body. Multiple causes can occur, for instance, when some values of a function argument trigger one specific error and other values trigger other errors.

Examples

expand all

#include<stdio.h>
double ratio(int num, int den) {
  return(num/den);
}

void main() {
  int i,j;
  i=2;
  j=0;
  printf("%.2f",ratio(i,j));
}

In this example, a red Division by zero error appears in the body of ratio. This Division by zero error in the body of ratio causes a dashed red underline on the call to ratio.

#include<stdio.h>
double ratio(int num, int den) {
  return(num/den);
}

int inputCh();

void main() {
  int i,j,ch=inputCh();
  i=2;

  if(ch==1)  {
    j=0;
    printf("%.2f",ratio(i,j));
  }
  else {
    j=2;
    printf("%.2f",ratio(i,j));
  }
}

In this example, there are two calls to ratio. In the first call, a Division by zero error occurs in the body of ratio. In the second call, Polyspace does not find errors. Therefore, combining the two calls, an orange Division by zero check appears in the body of ratio. A red Non-terminating call check on the first call indicates the error.

typedef void (*f)(void);  
// function pointer type 

void f1(void) { 
  int x; 
  x++;   
} 

void f2(void) { } 
void f3(void) { } 

f fptr_array[3] = {f1,f2,f3}; 
unsigned char getIndex(void); 

void main(void) { 
 unsigned char index = getIndex() % 3; 
 // Index is between O and 2 

 fptr_array[index]();  
 fptr_array[index]();  
} 

In this example, because index can lie between 0 and 2, the first fptr_array[index]() can call f1, f2 or f3. If index is zero, the statement calls f1. f1 contains a red Non-initialized local variable error, therefore, a dashed red error appears on the function call. Unlike other red errors, the verification continues.

After this statement, the software considers that index is either 1 or 2. An error does not occur on the second fptr_array[index]().

#include <stdio.h>
#include <stdlib.h>

typedef unsigned char uint8;
typedef unsigned short uint16;
typedef unsigned int uint32;

typedef void (*WrFuncPtr)(const void* src, void* dest);

typedef struct {
    WrFuncPtr pWrFuncPtr;
}FuncPtrStruct;


void Write_8(const void* pSource, void* pDest) {
    *(uint8*)pDest =  *(const uint8*) pSource;
}

void Write_16(const void* pSource, void* pDest) {
    *(uint16*)pDest =  *(const uint16*) pSource;
}

void Write_32(const void* pSource, void* pDest) {
    *(uint32*)pDest =  *(const uint32*) pSource;
}

#define SIZE_ARRAY 3

const FuncPtrStruct FuncPtrArray[SIZE_ARRAY] =
{
    { &Write_8  },
    { &Write_16 },
    { &Write_32 }
};

uint8 source[4];
uint8 dest[2];

void function(int uiSignalType) {
    uint8* srcPtr = &source[0];
    uint8 *destPtr = &dest[0];
    assert (uiSignalType>=0 && uiSignalType < SIZE_ARRAY);
    FuncPtrArray[uiSignalType].pWrFuncPtr(srcPtr, destPtr);
}

In this example, the function pointer pWrFuncPtr can point to one of the three functions Write_8, Write_16, or Write_32. Only the call to Write_32 contains a possible Illegally dereferenced pointer error (orange check) because the buffer pDest might not have enough memory for the content written. Since the check in the function body is orange, a red Non-terminating call error appears on the call to the function via the function pointer.

Check Information

Group: Control flow
Language: C | C++
Acronym: NTC