Start here

Home
About Klocwork
What's new
Fixed issues
Release notes
Installation

Reference

C/C++ checkers
Java checkers
C# checkers
MISRA C 2004 checkers
MISRA C++ 2008 checkers
MISRA C 2012 checkers
MISRA C 2012 checkers with Amendment 1
Commands
Metrics
Troubleshooting
Reference

Product components

C/C++ Integration build analysis
Java Integration build analysis
Desktop analysis
Refactoring
Klocwork Static Code Analysis
Klocwork Code Review
Structure101
Tuning
Custom checkers

Coding environments

Visual Studio
Eclipse for C/C++
Eclipse for Java
IntelliJ IDEA
Other

Administration

Project configuration
Build configuration
Administration
Analysis performance
Server performance
Security/permissions
Licensing
Klocwork Static Code Analysis Web API
Klocwork Code Review Web API

Community

View help online
Visit RogueWave.com
Klocwork Support
Rogue Wave Videos

Legal

Legal information

PORTING.STORAGE.STRUCT

Uncertain storage structure results

The PORTING checkers identify code that might rely on specific implementation details in different compilers. The PORTING.STORAGE.STRUCT checker detects situations in which the byte position of elements in a structure could differ, depending on alignment and packing attributes.

Vulnerability and risk

This checker warns you of situations in which the use of the various memory layout directives are applied to data structures, so that you can plan your approach to the new platform appropriately.

Depending on the alignment used by the compiler or target platform, the overall size and value of the fields in the structure can be quite different. The byte position of elements in the structure depends on alignment and packing attributes, so it's important to take that into account in the ported code. For example, these layout directives can significantly affect the behavior of the compiler when the field values are read from storage and used in files or sent out on the network.

Vulnerable code examples

struct my_struct {
    int16_t flag1;
    int32_t value;
    int16_t flag2;
};

In this example, the overall size and offset of the second (value) and third (flag2) fields could be different, depending on the compiler options and target platform. For example, the default alignment would be:

 offset of 'flag1' = 0
 offset of 'value' = 4 (aligned by 32-bit boundary)
 offset of 'flag2' = 8 (aligned by 32-bit boundary)
 size of 'my_struct' = 12

However, if the 'packed struct' compiler option or pragma is used, the result is different:

offset of 'flag1' = 0
offset of 'value' = 2
offset of 'flag2' = 6
size of 'my_struct' = 8

With this alignment, the process of serializing the data structure to a file or network socket would produce totally different results than in the default alignment.

Fixed code examples

One way of fixing the problem is to re-order the 'struct' fields:

   strut my_struct {
     int16_t flag1;
     int16_t flag2;
     int32_t value;
   };

This way, the offset of the fields and the overall size of the structure would always be the same, regardless of alignment and packing attributes.

Another option is to use larger types for the fields, so that they don't need any alignment or padding:

   struct my_struct {
     int32_t flag1;
     int32_t value;
     int32_t field2;
   };