It can be difficult to diagnose and debug memory access violations, buffer overruns, and other issues with reading from and writing to volatile memory. This can be especially problematic because the manifestation of the error may be much later in time than the actual cause of the issue. Many issues can be resolved by not ignoring and analyzing compiler warnings regarding undeclared functions or typecast issues. However, MxVDev provides a few methods to assist in diagnosing and finding these issues in a timely fashion.
When linking against the Virtual Micro Controller libraries, the SUT may be linked against the Debug version of the harness libraries. Doing so adds additional run time checks to allow detection of much memory and stack corruption. To link against these versions of the libraries, ensure the following settings are enabled by opening the project properties for the SUT:
a)C/C++ Properties->Warning Level: Level 4 (/W4)
b)Optimization->Optimization: Disabled (/Od)
c)Preprocessor->Processor Definitions: _CRT_SECURE_NO_DEPRECATE;WIN32;_DEBUG;_WINDOWS;_USRDLL;MXVDEV_EXPORTS;MXVDEV
d)Code Generation->Basic Runtime Checks: Both (/RTC1, equiv. to /RTCsu)
e)Code Generation->Runtime Library, either one of:
i.Multi-threaded Debug DLL (/MDd)
ii.Multi-threaded Debug (/MD)
f)Code Generation->Struct Member Alignment: 1 Byte (/Zp1)
g)Code Generation->Buffer Security Check: Yes
Available in version 3.36.42. This enables certain run time checks of MxVDev internal memory buffers at the expense of simulation speed. Internally, the MxV RTE environment may make use of memory on the heap which may be accidentally overrun by the SUT. An example of this is memory that is allocated internally by MxVDev but is later overwritten. While every effort has been made to provide a robust emulation environment through several other checks, there are unsafe programming practices, such as typecasting a const qualifier on a pointer, that can cause undesired effects at runtime. To allow MxVDev to perform internal heap validation, call the function MxVCrtCheckMemory(mxTrue)in the MxVOpen()function provided by the AppIF.c file. This will cause an assertion during runtime about invalid internal writes which may have occurred during the run.
a)Due to memory layout differences between an embedded controller and the Windows operating system, global or module local variables may not lay out physically as anticipated. In the Windows environment, for example, two global 16 bit integers that are declared sequentially may not exist in sequential memory (for example, the memory may exist in two distinct data pages, the compiler may lay them out in completely separate locations, or there may be padding inserted between for alignment). Therefore, it is an unsafe programming practice to make any assumptions on the layout of global or module local memory. An example of an unsafe programming practice would be the following C code snippet:
b)Some typecasts may perform unexpectedly, especially when typecasting away a const qualifier on a pointer type. In general, a const qualifier on a pointer is an indication that it is read-only memory. Casting these qualifiers away to pass the pointer to a function that may potentially write to a memory area can cause access violations. In addition, casting a byte array to an integer pointer, then pointer arithmetic on the integer pointer may not perform as expected. Again, these errors, if performed on global memory blocks, are not possible to detect in a normal situation. For example, the following code shows two examples of improper type casts:
c)Ensure that any functions that are the "string" functions are actually functioning on NULL terminated strings and that buffers are large enough to contain these strings. This is a common issue with buffer overruns, in that either the buffer is too small to contain the resulting string, or the string that is passed is not null terminated. The most common of these functions are sprintf, strcpy, and strcat.
Overrunning a global variable bound can be difficult to detect, because unlike the MxVDev internal heap, there are no detection methods available. However, by converting global array variables to pointers that are allocated on the heap, it is possible to utilize the MxVDev internal memory error detection to also detect memory issues that may occur while accessing these variables. There are a couple of things to keep in mind when utilizing this method:
•This method may be time consuming to implement, as it may require changes in multiple source code files. However, this may be mitigated by the fact that there may already be a clue (for example recent source code changes) that may help point towards which variables may be causing the issue.
•This method requires some fundamental code changes, namely a different definition of some underlying pointers. It is important, therefore, that the declarations and definitions be properly guarded. In addition, it must be ensured that the AppIF.c file has access to these pointers so that the allocation routines can take place.
Use the following steps to perform this type of advanced memory detection:
a)Ensure that steps 1 and 2 above have been performed.
b)At the beginning of each .c file that defines a global variable, insert the following lines to allow the heap detection to occur (notice that they are protected by a conditional so they are only included during a build for simulation):
c) Convert any array variables into pointers for MxVDev. This is a several step process, first declaring the variables as pointers, then allocating those pointers on the heap for use.
i.Convert the array declarations and definitions to pointers:
(a)For every array variable declaration that is to be checked (declarations normally found in .h header files):
(b)In each .c source file that defines the variable to be checked:
ii.Ensure that the variable declaration is available to the AppIF.c file, so that they may be allocated properly, either by #include statement that points to the proper header file, or declaring the variable explicitly.
iii.In the MxVOpen function, allocate the memory on the heap that will be used for the variable:
iv.In the MxVClose function, free the memory that has been allocated in MxVOpen.
If a variable is static (module local) in a particular source code file, it will have to be made global so that it can be accessible to MxVDev for heap allocation. This is a matter of removing the static qualifier from the variable and then following the steps described above to make it accessible for global access from AppIF.c