Imagix 4D User Guide


Function Cross Reference

The set of Function Cross Reference reports analyze specific aspects of the function calling hierarchy within your code, summarizing the results across your entire project. Unlike the Function Flow Checks reports that track data flow between functions, the Function Cross Reference reports examine just the calls made directly between functions and through function pointers.

Calls Via Pointers

While the use of function pointers to create vector tables or support callback functions make them useful, errors in design or coding can lead to problematic side effects. By listing all uses of function pointers and the potential calls made through them, the Calls Via Pointers report provides a valuable reference for systematically reviewing function pointer use in a body of software. Consider the following example.

#include <stdio.h>

typedef void (*FCPTR)() ;

void f0() {	printf("In f0! \n") ; }
void f1() {	printf("In f1! \n") ; }
void f2() {	printf("In f2! \n") ; }
void f3() {	printf("In f3! \n") ; }
void f4() {	printf("In f4! \n") ; }

//---------------------------------------------------		
FCPTR getFuncPtr(int i, FCPTR*  fptrs) {

	if (i >=0 && i <= 1 ) 	return fptrs[i] ;
	else 					return &f4 ; 
}
//---------------------------------------------------
void assignFuncPtr(FCPTR * fp) {	*fp = &f3; }
//---------------------------------------------------
struct OUTER_STRUCT {
     struct {
		int 	m_i;
		FCPTR 	m_inner_fp;
     } 		INNER_STRUCT[3];
	 
	FCPTR 	m_fp;
    float 	m_x;
    } 		
		s1 = { {{ 0, f2 }}, 		f1, 5.0  } ; 
		
FCPTR g_fptrs[5] ; 

//---------------------------------------------------
void useIndirectRef(FCPTR * ptr2fptr) {
	(*ptr2fptr)(); 
}
//---------------------------------------------------
void useStruct(struct OUTER_STRUCT * s2) {
	(s1.m_fp)();  						// f1
	(s2->INNER_STRUCT[2].m_inner_fp)(); // f2
}
//---------------------------------------------------
int useLocArr() {

	FCPTR fptrs[3] ; 
	fptrs[0] = &f0;
	fptrs[1] = &f1;
	fptrs[2] = &f2;

	int n; 
	printf("which function? Enter 0,1,2...\n"); 
	scanf("%d", &n); 
	
	switch (n) {
	case 0: 
	case 1: 	fptrs[n](); break;
	default: 	fptrs[0]();  
	}	// compilers detect: fptrs[2] is never called.
}
//---------------------------------------------------
void useAsRetVal() {	
		getFuncPtr(-1, g_fptrs)(); 		// f4
}
//+++++++++++++++++++++++++++++++++++++++++++++++++++++
int main(int argc, char* argv[])	{
	
	FCPTR 	fptr			= f0; 
	FCPTR * ptr2fptr 		= &fptr; 
	struct OUTER_STRUCT s2 	= 
		{ { {0, f0}, {1, f1} , {2, f2} },  f0, 5.0  } ; 
	
	fptr(); 							// f0
	assignFuncPtr(&fptr); 			
	(*fptr)(); 							// f3

	useIndirectRef(ptr2fptr); 			// indirect: f3
	useStruct(&s2); 					// indirect: f1 and f2
	useLocArr(); 						// indirect: f0 or  f1
	useAsRetVal();						// indirect: f3
}

The resulting report shows all functions that call via a function pointer. Where possible, it lists the possible target functions for the call as well. Due to limitations in function pointer resolution, the list of possible targets might include functions that are not called, or might not include any of the called functions. Details of Imagix 4D's function pointer resolution are found in the user guide section Analyzing Your C/C++ Code.

Calls Via Function Pointers

Function                                  File (Line)
          Line of Call
              Function Pointer
                  Potential Target Functions

main                                      fp1.c (66)
          73:     fptr(); 							// f0
              fptr                                      fp1.c (68)
                  f0  f3  
          75:     (*fptr)(); 							// f3
              fptr                                      fp1.c (68)
                  f0  f3  
useAsRetVal                               fp1.c (62)
          63:     getFuncPtr(-1, g_fptrs)(); 		// f4
              return                                    fp1.c
                  f4  
useIndirectRef                            fp1.c (35)
          36:     (*ptr2fptr)();
              ptr2fptr                                  fp1.c (35)
                  f0  f3  
useLocArr                                 fp1.c (44)
          57:     case 1: 	fptrs[n](); break;
              fptrs[]                                   fp1.c (46)
                  f0  f1  f2  
          58:     default: 	fptrs[0]();
              fptrs[]                                   fp1.c (46)
                  f0  f1  f2  
useStruct                                 fp1.c (39)
          40:     (s1.m_fp)();  						// f1
              m_fp                                      fp1.c (27)
                  f0  f1  
          41:     (s2->INNER_STRUCT[2].m_inner_fp)(); // f2
              m_inner_fp                                fp1.c (24)
                  f0  f1  f2  

Recursive Functions

The Recursive Functions report detects all functions that call themselves recursively, either directly, or transitively through calls to other functions. While the use of recursion can lead to concise implementations, care should be taken to avoid infinite loops, making sure that the recursion termination condition is correct. For embedded software, particular caution is important in the use of recursion because of the risk of stack overrun. The reported results can be reviewed to make sure that the maximum number of recursions has been estimated and tested, and that sufficient stack space is available. Consider the following example:

void funcD() {
    return;
}

void funcC() {
    funcA();
    funcD();
}

void funcB(int paramX) {
    while (paramX < 10) paramX = funcB(paramX);
    funcC();
}

void funcA() {
    funcB(1);
    funcC();
}

In displaying the recursion in this source code, the Recursive Functions report lists all the functions that can directly or transitively recurse, and the paths by which this recursion can occur. A table format is used for this. For each recursive path listing, just the functions involved with the recursion are shown. There may be multiple recursive paths for each recursive function.

Recursive Functions

Function                               File
          Recursive Path

funcA                                  recursive_funcs.c
      0   . funcA                                                             
      1   . . funcB                                                           
      2   . . . funcB                                      see (1)
      3   . . . funcC                                                         
      4   . . . . funcA                                    recursion
      5   . . funcC                                        see (3)

funcB                                  recursive_funcs.c
      0   . funcB                                                             
      1   . . funcB                                        recursion
      2   . . funcC                                                           
      3   . . . funcA                                                         
      4   . . . . funcB                                    recursion
      5   . . . . funcC                                    see (2)

funcC                                  recursive_funcs.c
      0   . funcC                                                             
      1   . . funcA                                                           
      2   . . . funcC                                      recursion
      3   . . . funcB                                                         
      4   . . . . funcC                                    recursion
      5   . . . . funcB                                    see (3)

Unused Code

Unused Code lists all of the root functions in the project. These are functions that are not called from any other functions in the code, are not entry functions for any tasks you have defined, and thus are candidates to be entry points into areas of dead code. Some of these functions might be entry points into the executable itself. Others might be called via statically indeterminate function pointers (see the Analysis Issues section of the User Guide). So some manual review is necessary, but the report indicates the full list of possible dead code entry points.

The report also shows the scope of unused code reached from each of the root functions. The Total Functions and Total Lines values include both the root function itself and any functions it uniquely calls; these are the additional functions that are reached via calls from just the single root function and no others. This scope is also shown graphically, via a link in the report.

Use of Variables

Through its various tools, Imagix 4D provides a lot of functionality for detailed analysis of the interaction of individual functions and variables in your software. In contrast, the Use of Variables report provides an overview of all variable use. It lists all global, static and member variables along with all non-library functions in your code, and shows every instance where a variable is set or read by a function.

The following report is generated for the example source code used in Calls Via Pointers section (above). An option enables you to flip the horizontal and vertical axises.

Functions Use of Variables

Key:
        R:                variable is read only
        S:                variable is set only
        U:                variable is used, both read and set

Settings:
        Global Variables:  displayed
        Static Variables:  displayed
        Member Variables:  displayed

                                         Variables  g_fptrs
                                                    . INNER_STRUCT
                                                    . . m_fp
                                                    . . . m_i
                                                    . . . . m_inner_fp
                                                    . . . . . m_x
                                                    . . . . . . return
                                                    . . . . . . . s1
Functions
assignFuncPtr ....................................  . . . . . . . . 
f0 ...............................................  . . . . . . . . 
f1 ...............................................  . . . . . . . . 
f2 ...............................................  . . . . . . . . 
f3 ...............................................  . . . . . . . . 
f4 ...............................................  . . . . . . . . 
getFuncPtr .......................................  . . . . . . . . 
main .............................................  . . . . . . . . 
useAsRetVal ......................................  R . . . . . . . 
useIndirectRef ...................................  . . . . . . . . 
useLocArr ........................................  . . . . . . . . 
useStruct ........................................  . R R . R . . R