Support for projects written in C ++ / CLI is not a priority in PVS-Studio. There are quite a few such projects, but nevertheless from time to time we come across them. Microsoft currently has no plans to stop supporting the C ++ / CLI language, so we decided to support this type of language.
C ++ / CLI support
Wikipedia:
C ++ / CLI -
C ++ programming language binding to Microsoft .NET programming environment. It integrates the C ++ ISO standard with the Unified Type System (UTS), considered as part of the Common Language Infrastructure (Common Language Infrastructure, CLI). It supports both the source level and the interoperability of executables compiled from native and managed C ++. C ++ / CLI is a further development of C ++.
We implemented C ++ / CLI support in PVS-Studio at a level sufficient for testing most projects. However, we didn’t have enough projects to test and some language constructs may be processed incorrectly or will produce obviously false positives. It's hard to keep track of everything. If you have any problems with checking your projects, please let us know.
This article can be finished, but it is not interesting. Therefore, we checked a small project SlimDX about what and describe below.
')
Slimdx
Wikipedia:
SlimDX is an open source API to DirectX programming under .NET. SlimDX can be used for any language under the .NET runtime (due to the CLR). SlimDX can be used to develop multimedia and interactive applications (eg games). It makes it possible to use the graphical hardware.
Official site:
http://slimdx.org/
The check was carried out with the help of the
PVS-Studio code analyzer. Since the project is small and represents a wrapper over another library, there were very few suspicious places. However, they are enough to write about them.
Test results
Below are the code snippets that seemed to me wrong.
Fragment N1
ContainmentType BoundingBox::Contains( BoundingBox box, BoundingSphere sphere ) { .... if( box.Minimum.X + radius <= sphere.Center.X && sphere.Center.X <= box.Maximum.X - radius && box.Maximum.X - box.Minimum.X > radius && <<<=== box.Minimum.Y + radius <= sphere.Center.Y && sphere.Center.Y <= box.Maximum.Y - radius && box.Maximum.Y - box.Minimum.Y > radius && box.Minimum.Z + radius <= sphere.Center.Z && sphere.Center.Z <= box.Maximum.Z - radius && box.Maximum.X - box.Minimum.X > radius) <<<=== return ContainmentType::Contains; .... }
PVS-Studio warning: V501 There are identical sub-expressions 'box.Maximum.X - box.Minimum.X> radius' operator. boundingbox.cpp 94
Most likely this code was written using Copy-Paste and forgot to make changes in the last line. At the end of the expression should be written "box.Maximum.Z - box.Minimum.Z> radius".
Fragment N2
typedef struct DIJOYSTATE2 { .... LONG rglSlider[2]; .... LONG rglVSlider[2]; .... LONG rglASlider[2]; .... LONG rglFSlider[2]; .... } DIJOYSTATE2, *LPDIJOYSTATE2; void JoystickState::AssignState(const DIJOYSTATE2 &joystate) { .... for( int i = 0; i < 2; i++ ) { sliders[i] = joystate.rglSlider[i]; asliders[i] = joystate.rglASlider[i]; vsliders[i] = joystate.rglVSlider[i]; fsliders[i] = joystate.rglVSlider[i]; } .... }
PVS-Studio warning: V525 The code containing the collection of similar blocks. Check items 'rglSlider', 'rglASlider', 'rglVSlider', 'rglVSlider' in lines 93, 94, 95, 96. joystickstate.cpp 93
I think this code contains a typo. The last line probably should have used the rglFSlider array:
sliders[i] = joystate.rglSlider[i]; asliders[i] = joystate.rglASlider[i]; vsliders[i] = joystate.rglVSlider[i]; fsliders[i] = joystate.rglFSlider[i];
Fragment N3
array<SoundEffectResult>^ SecondarySoundBuffer::SetEffects( array<Guid>^ effects ) { DWORD count = effects->Length; .... if( effects != nullptr && count > 0 ) .... }
PVS-Studio warning: V595 The 'effects' pointer was used before it was verified against nullptr. Check lines: 66, 73. secondarysoundbuffer.cpp 66
At the beginning, the 'effects' pointer is dereferenced. Then, in the code below, it is checked for equality to zero.
Fragment N4
There is a 'TVariable' class that contains virtual functions:
template<typename IBaseInterface> struct TVariable : public IBaseInterface { virtual BOOL IsValid() { .... } .... };
The class SMember is inherited from this class. Note that zeros are written to the fields of this class using the ZeroMemory () function.
struct SMember : public TVariable<TMember<ID3DX11EffectVariable> > { }; CEffectVectorOwner<SMember> m_pMemberInterfaces; ZeroMemory HRESULT CEffect::CopyMemberInterfaces(....) { .... ZeroMemory( &m_pMemberInterfaces[i], sizeof(SMember) * ( Members - i ) ); .... }
PVS-Studio warning: V598 The 'memset' function is used to make it clear the fields of the 'SMember' class. Virtual method table will be maintained by this. effectnonruntime.cpp 1739
Since there are virtual functions, the SMember class contains a pointer to a table of virtual methods. This pointer will be corrupted when the ZeroMemory () function is called.
Similarly:
- effectload.cpp 1106
- effectload.cpp 1107
Fragment N5
#pragma warning(disable: 4369) public enum class WaveFormatTag : System::Int32 { Pcm = WAVE_FORMAT_PCM, AdPcm = WAVE_FORMAT_ADPCM, IeeeFloat = WAVE_FORMAT_IEEE_FLOAT, MpegLayer3 = WAVE_FORMAT_MPEGLAYER3, DolbyAC3Spdif = WAVE_FORMAT_DOLBY_AC3_SPDIF, WMAudio2 = WAVE_FORMAT_WMAUDIO2, WMAudio3 = WAVE_FORMAT_WMAUDIO3, WmaSpdif = WAVE_FORMAT_WMASPDIF, Extensible = WAVE_FORMAT_EXTENSIBLE, }; #pragma warning(default: 4369)
PVS-Studio warning: V665 Possibly, the usage of #pragma warning (default: X) 'is incorrect in this context. The '#pragma warning (push / pop)' should be used instead. Check lines: 1089, 1102. enums.h 1102
Incorrect compiler warnings suppressed. At the end, the default value is restored. More correctly at the beginning to save the state of the settings, and then restore. This is not a serious mistake. However, for libraries it is important not to spoil the alert level settings in user projects. The correct way to suppress warnings is described in the
V665 warning
description .
There are several similar shortcomings in the header file "enums.h". Line numbers: 224, 267, 346.
Conclusion
I admit that the first article about checking the C ++ / CLI project turned out to be boring and brief. The first pancake is lumpy. I hope in the future it will be possible to check out some larger and more interesting project.
I suggest to download and test your C ++ / CLI projects using
PVS-Studio . We will be happy to receive your feedback and comments.
This article is in English.
If you want to share this article with an English-speaking audience, then please use the link to the translation: Andrey Karpov.
C ++ / CLI Now Supported in PVS-Studio .