And back into space: like the unicorn, Stellarium visited

 3r31093. 3r3-31. For all the time of its existence, people have made a tremendous amount of effort to study almost the entire area of ​​the starry sky. To date, we have considered hundreds of thousands of asteroids, comets, nebulae and stars, galaxies and planets. To see all this beauty on your own, it’s not necessary to leave the house and buy a telescope for yourself. You can install on the computer Stellarium - a virtual planetarium, and look at the night sky, lying comfortably on the couch But with the comfort? To find out the answer to this question, check Stellarium for errors in the computer code. 3r31078.  3r31093. 3r31078.  3r31093. 3r31073.
And back into space: like the unicorn, Stellarium visited 3r31078.  3r31093. Stellarium Is an open source virtual planetarium available for Linux, Mac OS X, Microsoft Windows, Symbian, Android and iOS, and MeeGo. The program uses OpenGL and Qt technologies to create a realistic sky in real time. With Stellarium it is possible to see what can be seen with an average and even large telescope. The program also provides observations of solar eclipses and the movement of comets. 3r31078.  3r31093. 3r31078.  3r31093. Stellarium was created by French programmer Fabian Chereau, who launched the project in the summer of 2001. Other prominent developers include Robert Spearman, Johannes Hajdozik, Matthew Gates, Timothy Reeves, Bogdan Marinov and Johan Meeris, who are responsible for the artwork. 3r31078.  3r31093. 3r31078.  3r31093. 3r3996. and about the analyzer 3r3997. 3r31078.  3r31093. The project was analyzed using the PVS-Studio static code analyzer. It is a tool for identifying errors and potential vulnerabilities in the source code of programs written in C, C ++ and C # languages ​​(in a short time and in Java!). Works on Windows, Linux and macOS. It is designed for those who need to improve the quality of their code. 3r31078.  3r31093. 3r31078.  3r31093. To conduct the analysis was simple enough. First I have downloaded Stellarium project with GitHub, then installed all the necessary packages for the assembly. Since the project is built using Qt Creator, I used the launch compiler tracking system, which is embedded in 3r343. Standalone
version of the analyzer. You can also view the finished analysis report. 3r31078.  3r31093. 3r31078.  3r31093. New readers and users 3r3-1020. Stellarium [/i] they may have wondered: why does the unicorn appear in the title of the article, and how is it related to code analysis? I answer: I am one of the developers of PVS-Studio, and the unicorn is our favorite naughty mascot. So up! 3r31078.  3r31093. 3r31078.  3r31093. 3r31073.
3r31078.  3r31093. I hope that thanks to this article, readers will learn something new, and the developers of Stellarium will be able to eliminate some of the errors and improve the quality of the code. 3r31078.  3r31093. 3r31078.  3r31093. Bring yourself a coffee with an air croissant and make yourself comfortable, because we turn to the most interesting - a review of the analysis results and analysis of errors! 3r31078.  3r31093. 3r31078.  3r31093. 3r3996. Suspicious conditions 3-33997. 3r31078.  3r31093. For more pleasure from reading, I suggest not looking directly at the analyzer warning, but try here and further to find errors on your own. 3r31078.  3r31093. 3r31078.  3r31093.
3r33981. void QZipReaderPrivate :: scanFiles ()
{
//find EndOfDirectory header
int i = 0; 3r31093. int start_of_directory = -1; 3r31093. EndOfDirectory eod; 3r31093. while (start_of_directory == -1) {
const int pos = device-> size ()
- int (sizeof (EndOfDirectory)) - i; 3r31093. if (pos < 0 || i > 65535) {
qWarning () "QZip: EndOfDirectory not found"; 3r31093. return; 3r31093.}
3r31093. device-> seek (pos); 3r31093. device-> read ((char *) & eod, sizeof (EndOfDirectory)); 3r31093. if (readUInt (eod.signature) == 0x06054b50)
break; 3r31093. ++ i; 3r31093.}
} 3r33987. 3r31078.  3r31093. 3r33339. PVS-Studio warning: [/b] 3r3111. V654 3r31081. The condition 'start_of_directory == - 1' of loop is always true. qzip.cpp 617
 3r31093. 3r31078.  3r31093. Could you find a bug? If yes, then praise. 3r31078.  3r31093. 3r31078.  3r31093. The error lies in the condition of the cycle while . It is always true, since the variable is start_of_directory does not change in the body of the cycle. Most likely, the cycle will not last forever, since it contains return and 3r31020. break [/i] but this code looks weird. 3r31078.  3r31093. 3r31078.  3r31093. It seems to me that in the code they forgot to make the assignment start_of_directory = pos in the place where the signature is being checked. Then the operator break , perhaps, superfluous. In this case, the code can be rewritten as:
 3r31093. 3r31078.  3r31093.
3r33981. int i = 0; 3r31093. int start_of_directory = -1; 3r31093. EndOfDirectory eod; 3r31093. while (start_of_directory == -1) {
const int pos = device-> size ()
- int (sizeof (EndOfDirectory)) - i; 3r31093. if (pos < 0 || i > 65535) {
qWarning () "QZip: EndOfDirectory not found"; 3r31093. return; 3r31093.}
3r31093. device-> seek (pos); 3r31093. device-> read ((char *) & eod, sizeof (EndOfDirectory)); 3r31093. if (readUInt (eod.signature) == 0x06054b50)
start_of_directory = pos; 3r31093. ++ i; 3r31093.} 3r33987. 3r31078.  3r31093. However, I am not sure that the code should be like this. It is best that the project developers themselves analyze this part of the program and make the necessary edits. 3r31078.  3r31093. 3r31078.  3r31093.
3r33981. Another weird condition:
class StelProjectorCylinder: public StelProjector
{
public:
protected: 3r31093.
virtual bool
intersectViewportDiscontinuityInternal (const Vec3d & capN,
double capD) const
{
static const SphericalCap cap1 (??0); 3r31093. static const SphericalCap cap2 (-??0); 3r31093. static const SphericalCap cap3 (?? -1); 3r31093. SphericalCap cap (capN, capD); 3r31093. return cap.intersects (cap1)
&& cap.intersects (cap2)
&& cap.intersects (cap2); 3r31093.}
}; 3r33986. 3r33987. 3r31078.  3r31093. 3r33339. PVS-Studio warning: [/b] 3r3195. V501
There are identical sub-expressions 'cap. Intersects (cap 2)' of the operator. StelProjectorClasses.hpp 175
 3r31093. 3r31078.  3r31093. As you have probably already guessed, the error lies in the last line of the function: the programmer made a typo, and in the end it turned out that the function returns the result regardless of the value 3r31020. cap3 3r31021. . 3r31078.  3r31093. 3r31078.  3r31093. This type of error is extremely common: in almost every proven project we encountered typos related to the names of the form 3r31020. name1 [/i] and 3r31020. name2 [/i] and the like. As a rule, such errors are related to copy-paste. 3r31078.  3r31093. 3r31078.  3r31093. This copy of the code is a vivid example of another common error pattern, about which we even conducted a separate mini-study. My colleague, Andrei Karpov, called it "3r33215. The effect of the last line, 3r?1081." If you are not familiar with this material, then I suggest opening the tab in the browser to read later, but for now let's continue. 3r31078.  3r31093. 3r31078.  3r31093.
3r33981. void BottomStelBar :: updateText (bool updatePos)
{
updatePos = true; 3r31093.
if (location-> text ()! = newLocation || updatePos)
{
updatePos = true; 3r31093.
}
if (fov-> text ()! = str)
{
updatePos = true; 3r31093.
}
if (fps-> text ()! = str)
3r31093. {
updatePos = true; 3r31093.
}
3r31093. if (updatePos)
{
}
} 3r33987. 3r31078.  3r31093. 3r33339. PVS-Studio warnings: [/b] 3r31078.  3r31093. 3r31078.  3r31093.
 3r31093. 3r31065. V560 A part of the conditional expression is always true: updatePos. StelGuiItems.cpp 732
 3r31093. 3r31065. V547 3r31081. Expression 'updatePos' is always true. StelGuiItems.cpp 831
 3r31093. 3r31065.
V763
Parameter 'updatePos' is always rewritten in function body before being used. StelGuiItems.cpp 690
 3r31093.
3r31078.  3r31093. The value of the parameter 3r31020. updatePos [/i] always overwritten before being used, i.e. the function will work the same way, regardless of the value passed to it. 3r31078.  3r31093. 3r31078.  3r31093. Looks weird, right? In all places where parameter 3r31020 participates. updatePos [/i] , it matters true . This means conditions if (location-> text ()! = newLocation || updatePos) and 3r31020. if (updatePos) [/i] will always be true. 3r31078.  3r31093. 3r31078.  3r31093. Another fragment:
 3r31093. 3r31078.  3r31093.
3r33981. void LandscapeMgr :: onTargetLocationchanged (StelLocation loc)
{
if (pl && flagEnvironmentAutoEnabling)
{
QSettings * conf = StelApp :: getInstance (). GetSettings (); 3r31093. setFlagAtmosphere (pl-> hasAtmosphere ()
& conf-> value ("landscape /flag_atmosphere", true) .toBool ()); 3r31093. setFlagFog (pl-> hasAtmosphere ()
& conf-> value ("landscape /flag_fog", true) .toBool ()); 3r31093. setFlagLandscape (true); 3r31093.}
} 3r33987. 3r31078.  3r31093. 3r33339. PVS-Studio warnings: [/b] 3r31078.  3r31093. 3r31078.  3r31093.
 3r31093. 3r31065. 3r33336. V792 3r31081. The "toBool" function is located on the left of the operand. Perhaps, it is better to use '&&'. LandscapeMgr.cpp 782
 3r31093. 3r31065. 3r33336. V792 3r31081. The "toBool" function is located on the left of the operand. Perhaps, it is better to use '&&'. LandscapeMgr.cpp 783
 3r31093.
3r31078.  3r31093. The analyzer detected a suspicious expression in the arguments of the functions setFlagAtmosphere and 3r31020. setFlagFog [/i] . Indeed: on both sides of the bit operator & values ​​are of type bool . Instead of the operator 3r31020. & [/i] It is necessary to use the operator 3r31020. && 3r31021. and now I will explain why. 3r31078.  3r31093. 3r31078.  3r31093. Yes, the result of this expression will always be correct. Before using the bitwise "and" both operands will rise to type 3r31020. int 3r31021. . In C ++, this conversion is unambiguous : false is converted to ? and true is converted to 1. Therefore, the result of this expression will be the same as if the operator was used. && 3r31021. . 3r31078.  3r31093. 3r31078.  3r31093. But there is a nuance. When calculating the result of operation && 3r31021. The so-called “lazy calculation” is used. If the value of the left operand is false , then the right value is not even calculated, because the logical “and” in any case will return false . This is done to save computational resources and allows you to write more complex structures. For example, you can check that the pointer is not null, and, if so, dereference it for additional verification. Example: 3r31020. if (ptr && ptr-> foo ()) 3r3-1021. . 3r31078.  3r31093. 3r31078.  3r31093. SoThis “lazy calculation” is not performed using the bitwise 3r31020 operator. & : expressions 3r31020. conf-> value ("", true) .toBool () will be calculated every time, regardless of the value pl-> hasAtmosphere () . 3r31078.  3r31093. 3r31078.  3r31093. In rare cases, this is done on purpose. For example, if the calculation of the right operand has “side effects”, the result of which is used later. It’s not very good to do this either, because it makes it difficult to understand the code and makes it more difficult to care for it. In addition, the order of calculation of the operands & is not defined, so in some cases of using such "tricks" you can get undefined behavior. 3r31078.  3r31093. 3r31078.  3r31093. If you want to save side effects - do it on a separate line and save the result in a separate variable. People who will work with this code in the future will be grateful to you :)
 3r31093. 3r31078.  3r31093. 3r31073.
3r3404.
3r31078.  3r31093. Go to the next topic. 3r31078.  3r31093. 3r31078.  3r31093. 3r3996. Incorrect work with memory 3r3997. 3r31078.  3r31093.
3r33981. Let's start the topic of dynamic memory with this fragment:
/************ Basic Edge Operations **************** /
/* __gl_meshMakeEdge creates one edge,
* two vertices, and a loop (face). 3r31093. * The loop consists of the two new half-edges. 3r31093. * /
GLUEShalfEdge * __gl_meshMakeEdge (GLUESmesh * mesh)
{
GLUESvertex * newVertex1 = allocVertex (); 3r31093. GLUESvertex * newVertex2 = allocVertex (); 3r31093. GLUESface * newFace = allocFace (); 3r31093. GLUEShalfEdge * e; 3r31093. 3r31093. /* if any one is null then all get freed * /
if (newVertex1 == NULL
|| newVertex2 == NULL
|| newFace == NULL)
{
if (newVertex1! = NULL)
{
memFree (newVertex1); 3r31093.}
if (newVertex2! = NULL)
{
memFree (newVertex2); 3r31093.}
if (newFace! = NULL)
{
memFree (newFace); 3r31093.}
return NULL; 3r31093.}
3r31093. e = MakeEdge (& mesh-> eHead); 3r31093. if (e == NULL)
{
return NULL; 3r31093.}
3r31093. MakeVertex (newVertex? e, & mesh-> vHead); 3r31093. MakeVertex (newVertex? e-> Sym, & mesh-> vHead); 3r31093. MakeFace (newFace, e, & mesh-> fHead); 3r31093. 3r31093. return e; 3r31093.} 3r33987. 3r31078.  3r31093. 3r33339. PVS-Studio warnings: [/b] 3r31078.  3r31093. 3r31078.  3r31093.
 3r31093. 3r31065. V773 The newVertex1 pointer. A memory leak is possible. mesh.c 312
 3r31093. 3r31065. V773 The newVertex2 pointer. A memory leak is possible. mesh.c 312
 3r31093. 3r31065. V773 The 'newFace' pointer. A memory leak is possible. mesh.c 312
 3r31093.
3r31078.  3r31093. The function allocates memory for several structures and passes it to pointers 3r31020. newVertex1 [/i] , 3r31020. newVertex2 [/i] (interesting names, right?) and 3r31020. newFace [/i] . If one of them turns out to be zero, then all the memory reserved within the function is released, after which the control flow leaves the function. 3r31078.  3r31093. 3r31078.  3r31093. What happens if the memory for all three structures is allocated correctly, and the function 3r31020. MakeEdge (& mesh-> eHead) [/i] will return NULL ? The control flow reaches the second in a row, 3r3-1020. return [/i] . 3r31078.  3r31093. 3r31078.  3r31093. Since pointers newVertex1 , 3r31020. newVertex2 [/i] and 3r31020. newFace [/i] are local variables, then after exiting the function they will cease to exist. But the release of the memory that belonged to them will not happen. It will remain reserved, but we will no longer have access to it. 3r31078.  3r31093. 3r31078.  3r31093. Such situations are called “memory leak”. A typical scenario with such an error: with a long program running, it begins to consume more and more RAM, until it is completely exhausted. 3r31078.  3r31093. 3r31078.  3r31093. It should be noted that in this example, the third return not a mistake. Functions 3r3-1020. MakeVertex [/i] and 3r31020. MakeFace [/i] transfer the addresses of the allocated memory to other data structures, thereby delegating responsibility for its release. 3r31078.  3r31093. 3r31078.  3r31093. The next flaw is in the method that takes 90 lines. For convenience, I cut it, leaving only problem areas. 3r31078.  3r31093. 3r31078.  3r31093.
3r33981. void AstroCalcDialog :: drawAngularDistanceGraph ()
{
QVector
xs, ys; 3r31093.
} 3r33987. 3r31078.  3r31093. Only one line left. I'll give a hint: this is the only mention of objects xs and 3r31020. ys [/i] . 3r31078.  3r31093. 3r31078.  3r31093. 3r33339. PVS-Studio warnings: [/b] 3r31078.  3r31093. 3r31078.  3r31093.
 3r31093. 3r31065. 3r? 3574. V808
The 'xs' object of the 'QVector' type was created but it was not used. AstroCalcDialog.cpp 5329
 3r31093. 3r31065. 3r? 3574. V808
The “ys” object of the QVector type was created but it was not used. AstroCalcDialog.cpp 5329
 3r31093.
3r31078.  3r31093. Vectors xs and 3r31020. ys [/i] are created but not used anywhere. It turns out that with each use of the method drawAngularDistanceGraph unnecessary creation and deletion of an empty container occurs. I think this ad remains in the code after refactoring. This, of course, is not an error, but it is worth removing the extra code. 3r31078.  3r31093. 3r31078.  3r31093. 3r3996. Strange type conversions 3-33997. 3r31078.  3r31093. Another example after a little formatting looks like this:
 3r31093. 3r31078.  3r31093.
3r33981. void SatellitesDialog :: updateSatelliteData ()
{
//set default
buttonColor = QColor (0.? 0.? 0.4); 3r31093.
} 3r33987. 3r31078.  3r31093. In order to understand what the error is, you will have to look at the prototypes of the 3r-33611 constructors. class Qcolor
:
 3r31093. 3r31078.  3r31093. 3r31073.
3r3620.
3r31078.  3r31093. 3r33339. PVS-Studio warnings: [/b] 3r31078.  3r31093. 3r31078.  3r31093.
 3r31093. 3r31065. V674 3r31081. The literal '0.4' of 'double' type is being implicitly casting the 'int' type while calling the 'QColor' function. Inspect the first argument. SatellitesDialog.cpp 413
 3r31093. 3r31065.
V674 3r31081. The literal '0.4' of 'double' type is being implicitly casting the 'int' type while calling the 'QColor' function. Inspect the second argument. SatellitesDialog.cpp 413
 3r31093. 3r31065.
V674 3r31081. The literal '0.4' of 'double' type is being implicitly casting the 'int' type while calling the 'QColor' function. Inspect the third argument. SatellitesDialog.cpp 413
 3r31093.
3r31078.  3r31093. In class 3r31020. Qcolor [/i] There are no constructors that accept the type double , therefore, the arguments in the example will be implicitly converted to int 3r31021. . This leads to the fact that the field r , 3r31020. g , 3r31020. b [/i] object 3r31020. buttonColor [/i] will have values ​​of 3r31020. 0 [/i] . 3r31078.  3r31093. 3r31078.  3r31093. If the programmer intended to create an object from values ​​of type 3r31020. double [/i] , he should have used a different constructor. 3r31078.  3r31093. 3r31078.  3r31093. For example, you could use a constructor that accepts Qrgb by writing:
 3r31093. 3r31078.  3r31093.
3r33981. buttonColor = QColor (QColor :: fromRgbF (0.? 0.? 0.4)); 3r33986. 3r33987. 3r31078.  3r31093. It could have been done differently. In Qt, real values ​​in the[0.0, 1.0]range are used to designate RGB colors. or integers in the[0, 255]range. . 3r31078.  3r31093. 3r31078.  3r31093. Therefore, the programmer could translate values ​​from real to integer, writing like this:
 3r31093. 3r31078.  3r31093.
3r33981. buttonColor = QColor ((int) (255 * 0.4),
(int) (255 * 0.4),
(int) (255 * 0.4)); 3r33986. 3r33987. 3r31078.  3r31093. or just
 3r31093. 3r31078.  3r31093.
3r33981. buttonColor = QColor (10? 10? 102); 3r33986. 3r33987. 3r31078.  3r31093. Are you bored? Do not worry: ahead of us are waiting for more interesting mistakes. 3r31078.  3r31093. 3r31078.  3r31093. 3r31073.
3r33737.
3r31078.  3r31093.
3r3-1020. "Unicorn in space." View from Stellarium. 3r31021. 3r31022. 3r31078.  3r31093. 3r31078.  3r31093. 3r3996. Other errors 3r3997. 3r31078.  3r31093. Finally, I left you a few more tasty things :) Let's get down to one of them. 3r31078.  3r31093. 3r31078.  3r31093.
3r33981. HipsTile * HipsSurvey :: getTile (int order, int pix)
{
if (order == orderMin &&! all all.isNull ())
{
int nbw = sqrt (12 * 1 (2 * order)); 3r31093. int x = (pix% nbw) * allsky.width () /nbw; 3r31093. int y = (pix /nbw) * allsky.width () /nbw; 3r31093. int s = allsky.width () /nbw; 3r31093. QImage image = allsky.copy (x, y, s, s); 3r31093.
}
} 3r33987. 3r31078.  3r31093. 3r33339. PVS-Studio warning: [/b] 3r33762. V634
The operation of the operation is higher than that of the operation. It's possible that parentheses should not be used in the expression. StelHips.cpp 271
 3r31093. 3r31078.  3r31093. Well, could you find a mistake? Consider the expression in more detail. (12 * 1 (2 * order)) 3r31021. . The analyzer reminds you that operation ' [i] * 'has higher priority than bit-shift operation' 3r31021. '. It is easy to understand that the multiplication is [i] 12 on 3r31020. 1 3r31021. meaningless, and brackets around 2 * order Not needed. 3r31078.  3r31093. 3r31078.  3r31093.
3r33981. Most likely, the programmer was going to write this:
int nbw = sqrt (12 * (1 2 * order)); 3r31093. In this case, the value of 12 will be multiplied by the correct number. 3r33986. 3r33987. 3r31078.  3r31093. Note. Additionally, I want to note that if the value of the right operand is' 3r31021. 'is greater than or equal to the number of bits of the left operand, the result is not defined. Since numeric literals are type [i] by default. int 3r31021. which takes 3r3-1020. 32 bits, the value of the parameter order should not exceed 3r31020. 15 3r31021. . Otherwise, the evaluation of the expression may result in undefined behavior. 3r31078.  3r31093. 3r31078.  3r31093. We continue. The method given below is quite confusing, but I am sure that the sophisticated reader will cope with the detection of an error :)
 3r31093. 3r31078.  3r31093.
3r33981. /* inherits documentation from base class * /
QCPRange QCPStatisticalBox ::
getKeyRange (bool & foundRange, SignDomain inSignDomain) const
{
foundRange = true; 3r31093. if (inSignDomain == sdBoth)
{
return QCPRange (mKey - mWidth * 0.? mKey + mWidth * 0.5); 3r31093.}
else if (inSignDomain == sdNegative)
{
if (mKey + mWidth * ???r3r3896. return QCPRange (mKey - mWidth * 0.? mKey + mWidth * 0.5);
else if (mKey 3r3r9696. return QCPRange (mKey - mWidth * 0.? mKey); 3r???.???.???.3383) {
FoundRange = false;
Return QCPRange ();
} 3r3pc31093.}
Else if (inSignDomain == sdPositive)
mKey - mWidth * 0.? mKey + mWidth * 0.5);
else if (mKey> 0)
return QCPRange (mKey, mKey + mWidth * 0.5);
else
33. return QCPRange ();
}
}
foundRange = false;
return QCPRange (); rrr31093.} 3r33986. 3r33987.
 3r31093. 3r33339. PVS-Studio warning: [/b] 3r33855. V779 3r31081. Unreachable code detected. It is possible that an error is present. qcustomplot.cpp 19512.
 3r31093. 3r31078.  3r31093. The fact is that all branches if else have return . Therefore, the control flow never reaches the last two lines. 3r31078.  3r31093. 3r31078.  3r31093. By and large, this example will run normally and work correctly. But the presence of an unreachable code is itself a signal. In this case, it indicates the wrong structure of the method, which greatly complicates the readability and clarity of the code. 3r31078.  3r31093. 3r31078.  3r31093. This code snippet should be refactored to produce a tidier function. For example, like this:
 3r31093. 3r31078.  3r31093.
3r33981. /* inherits documentation from base class * /
QCPRange QCPStatisticalBox ::
getKeyRange (bool & foundRange, SignDomain inSignDomain) const
{
foundRange = true; 3r31093. 3r31093. switch (inSignDomain)
{
case sdBoth:
{
return QCPRange (mKey - mWidth * 0.? mKey + mWidth * 0.5); 3r31093. break; 3r31093.}
case sdNegative:
{
if (mKey + mWidth * ???r3r3896. return QCPRange (mKey - mWidth * 0.? mKey + mWidth * 0.5);
else if (mKey 3r3r9696. return QCPRange (mKey - mWidth * 0.? mKey); 3r3y3a3r.394.3an.). .}
Case sdPositive: {
If (mKey - mWidth * 0.5> 0)
Return QCPRange (mKey - mWidth * 0.? mKey + mWidth * 0.5);
Else if (mKey> 0) 3r3r3 QCPRange (mKey, mKey + mWidth * 0.5); 3r31093. Break;
}
}
FoundRange = false; 3r3r931093. Return QCPRange (3r3r???.???).  3r31093. The last error in our review will be the one I liked the most. The code for the problem location is short and simple:
 3r31093. 3r31078.  3r31093.
3r33981. Plane :: Plane (Vec3f & v? Vec3f & v? Vec3f & v3)
: distance (0.0f), sDistance (0.0f)
{
Plane (v? v? v? SPolygon :: CCW); 3r31093.} 3r33987. 3r31078.  3r31093. Noticed something suspicious? Not everyone can :)
 3r31093. 3r31078.  3r31093. 3r33339. PVS-Studio warning: [/b] 3r3990. V603
The object was not used. If you wish to call the constructor, 'this-> Plane :: Plane ()' should be used. Plane.cpp 29
 3r31093. 3r31078.  3r31093. The programmer expected that some of the object's fields would be initialized inside the nested constructor, but it turned out like this: when the constructor is called Plane (Vec3f & v? Vec3f & v? Vec3f & v3) , an unnamed temporary object is created inside it, which is immediately deleted. As a result, the part after the object remains uninitialized. 3r31078.  3r31093. 3r31078.  3r31093. For the code to work properly, you should use the convenient and secure C ++ 11 feature - the delegating constructor:
 3r31093. 3r31078.  3r31093.
3r33981. Plane :: Plane (Vec3f & v? Vec3f & v? Vec3f & v3)
: Plane (v? v? v? SPolygon :: CCW)
{
distance = 0.0f; 3r31093. sDistance = 0.0f; 3r31093.} 3r33987. 3r31078.  3r31093. But if you use the compiler for older versions of the language, you can write this:
 3r31093. 3r31078.  3r31093.
3r33981. Plane :: Plane (Vec3f & v? Vec3f & v? Vec3f & v3)
: distance (0.0f), sDistance (0.0f)
{
this-> Plane :: Plane (v? v? v? SPolygon :: CCW); 3r31093.} 3r33987. 3r31078.  3r31093. Or this:
 3r31093. 3r31078.  3r31093.
3r33981. Plane :: Plane (Vec3f & v? Vec3f & v? Vec3f & v3)
: distance (0.0f), sDistance (0.0f)
{
new (this) Plane (v? v? v? SPolygon :: CCW); 3r31093.} 3r33987. 3r31078.  3r31093. Note that the last two methods are 3r3r990. very dangerous 3r31081. . Therefore, you should be very careful and well understand how such methods work. 3r31078.  3r31093. 3r31078.  3r31093. 3r3996. Conclusion 3r3997. 3r31078.  3r31093. What conclusions can be made about the quality of the Stellarium code? To be honest, there were not very many mistakes. Also in the whole project I did not find a single error in which the code is tied to indefinite behavior. For the opensource project, the quality of the code was high, for which I take off my hat to the developers. You guys are great! It was pleasant and interesting for me to review your project. 3r31078.  3r31093. 3r31078.  3r31093. What about the planetarium itself - I use it often enough. Unfortunately, living in the city, I very rarely enjoy the clear night sky, and Stellarium allows me to be anywhere in the world without getting up from the sofa. It is really comfortable! 3r31078.  3r31093. 3r31078.  3r31093. I especially like the “Constellation art” mode. The view of the huge figures covering the whole sky in a strange dance is breathtaking. 3r31078.  3r31093. 3r31078.  3r31093. 3r31073.
3r31078.  3r31093.
3r3-1020. "Strange dance." View from Stellarium. 3r31021. 3r31022. 3r31078.  3r31093. 3r31078.  3r31093. It is natural for us, earthlings, to err, and there is nothing shameful that these errors leak into the code. For this, code analysis tools such as PVS-Studio are being developed. If you are one of earthlings -
put like
I suggest download and try yourself. . 3r31078.  3r31093. 3r31078.  3r31093. I hope that you were interested in reading my article, and you learned something new and useful for yourself. And I wish the developers to fix the errors found as soon as possible. 3r31078.  3r31093. 3r31078.  3r31093. Subscribe to our channels and follow the news from the world of programming! 3r31078.  3r31093. 3r31078.  3r31093.
 3r31093. 3r31065. VK: 3r3103. @pvsstudio_eng
 3r31093. 3r31065. Telegram: 3r31051. @pvsstudio_eng
 3r31093. 3r31065. Instagram: @pvsstudio_eng
 3r31093. 3r31065. Twitter: @pvsstudio_eng
 3r31093. 3r31065. YouTube: 3r3103 @PVSStudioTool
 3r31093.
3r31078.  3r31093. 3r31073. 3r31080. 3r31075. 3r31081.
3r31078.  3r31093. If you want to share this article with an English-speaking audience, then please use the link to the translation: George Gribkov. 3r31080. Into Space Again: How is the Unicorn Visited Stellarium
3r31093. 3r31093. 3r31093.
3r31093.
3r31093. 3r31093. 3r31093. 3r31093.
+ 0 -

Add comment