Wenn es Ihnen so scheint, als ob das neue Jahr erst gestern gekommen ist und Sie nicht bemerkt haben, wie viel mehr als die Hälfte des Januar vergangen ist, dann waren Sie die ganze Zeit damit beschäftigt, nach subtilen Fehlern im Code zu suchen, den Sie pflegen. Es bedeutet auch, dass unser Artikel nur für Sie ist. Wir, PVS-Studio, haben das ELKI-Open-Source-Projekt überprüft, um Ihnen zu zeigen, welche Fehler im Code gefunden werden können, wie geschickt sie sich dort verstecken können und wie Sie damit umgehen können.

ELKI - was ist das für eine Bibliothek?
ELKI Environment for Developing KDD-Applications Supported by Index-Structures. Java . – , , -. , . . .
AGPL , , . . . .
ELKI 2 630 java, 186 444 , . open source .
. , . ! 10 , , , .
V6001 There are identical sub-expressions 'bounds[j + 1]' to the left and to the right of the '!=' operator. CLIQUEUnit.java(252)
private boolean checkDimensions(CLIQUEUnit other, int e) {
for(int i = 0, j = 0; i < e; i++, j += 2) {
if (dims[i] != other.dims[i]
|| bounds[j] != other.bounds[j]
|| bounds[j + 1] != bounds[j + 1]) {
return false;
}
}
return true;
}
if checkDimensions bounds[j + 1] . , , . checkDimensions true , .
if :
bounds[j + 1] != other.bounds[j + 1]
V6022 Parameter 'updates' is not used inside constructor body. DataStoreEvent.java(60)
V6022 Parameter 'removals' is not used inside constructor body. DataStoreEvent.java(60)
public DataStoreEvent(DBIDs inserts, DBIDs removals, DBIDs updates) {
super();
this.inserts = inserts;
this.removals = inserts;
this.updates = inserts;
}
. DataStoreEvent , . , , , .
, DataStoreEvent , , .
public static DataStoreEvent insertionEvent(DBIDs inserts) {
return new DataStoreEvent(inserts, DBIDUtil.EMPTYDBIDS, DBIDUtil.EMPTYDBIDS);
}
public static DataStoreEvent removalEvent(DBIDs removals) {
return new DataStoreEvent(DBIDUtil.EMPTYDBIDS, removals, DBIDUtil.EMPTYDBIDS);
}
public static DataStoreEvent updateEvent(DBIDs updates) {
return new DataStoreEvent(DBIDUtil.EMPTYDBIDS, DBIDUtil.EMPTYDBIDS, updates);
}
- .
:
this.inserts = inserts;
this.removals = removals;
this.updates = updates;
V6012 The '?:' operator, regardless of its conditional expression, always returns one and the same value '0.5'. ClusterHullVisualization.java(173), ClusterHullVisualization.java(173)
public void fullRedraw() {
....
boolean flat = (clusters.size() == topc.size());
// Heuristic value for transparency:
double baseopacity = flat ? 0.5 : 0.5;
....
}
baseopacity 0.5 , flat. , , - .
. , , . , 90 – . , .
V6025 Index '1' is out of bounds. GeneratorStatic.java(104)
@Override
public double[] computeMean() {
// Not supported except for singletons.
return points.size() == 1 ? points.get(1) : null;
}
computeMean , points , , , … 1. , IndexOutOfBoundsException .
:
return points.size() == 1 ? points.get(0) : null;
?
V6020 Divide by zero. The range of the 'referenceSetSize' denominator values includes zero. PreDeConNeighborPredicate.java(138)
protected PreDeConModel computeLocalModel(DoubleDBIDList neighbors, ....) {
final int referenceSetSize = neighbors.size();
....
// Shouldn't happen:
if(referenceSetSize < 0) {
LOG.warning("Empty reference set –
should at least include the query point!");
return new PreDeConModel(Integer.MAX_VALUE, DBIDUtil.EMPTYDBIDS);
}
....
for(int d = 0; d < dim; d++) {
s[d] /= referenceSetSize;
mvVar.put(s[d]);
}
....
}
, . . . .
neighbors, computeLocalModel. neighbors if, , . .. referenceSetSize < 0 , set – . , referenceSetSize == 0.
neighbors, for . , .
V6062 Possible infinite recursion inside the 'setInitialMeans' method. Predefined.java(65), Predefined.java(66)
public void setInitialMeans(List<double[]> initialMeans) {
this.setInitialMeans(initialMeans);
}
. , . , - :
this.setInitialMeans(initialMeans.toArray(new double[0][0]));
, , , , - . , , :
public void setInitialMeans(double[][] initialMeans) {
double[][] vecs = initialMeans.clone(); // TODO: deep copy?
this.initialMeans = vecs;
}
V6094 The expression was implicitly cast from 'int' type to 'double' type. Consider utilizing an explicit type cast to avoid the loss of a fractional part. An example: double A = (double)(X) / Y;. ProbabilityWeightedMoments.java(130)
public static <A> double[] alphaBetaPWM(...., final int nmom) {
final int n = adapter.size(data);
final double[] xmom = new double[nmom << 1];
double aweight = 1. / n, bweight = aweight;
for(int i = 0; i < n; i++) {
....
for(int j = 1, k = 2; j < nmom; j++, k += 2) {
xmom[k + 1] += val * (aweight *= (n - i - j + 1) / (n - j + 1));
xmom[k + 1] += val * (bweight *= (i - j + 1) / (n - j + 1));
}
}
return xmom;
}
for (n — i — j + 1) / (n — j + 1) int double. : , . , , , xmom double. , , (n – i – j + 1) / (n – j + 1). , n – j + 1 x. : (x – i) / x. 0 , . . . n , , .
, , double:
xmom[k + 1] += val * (aweight *= (double) (n - i - j + 1) / (n - j + 1));
xmom[k + 1] += val * (bweight *= (double) (i - j + 1) / (n - j + 1));
V6079 Value of the 'splitpoint' variable is checked after use. Potential logical error is present. KernelDensityFittingTest.java(97), KernelDensityFittingTest.java(97)
public final void testFitDoubleArray() throws IOException {
....
int splitpoint = 0;
while(fulldata[splitpoint] < splitval && splitpoint < fulldata.length) {
splitpoint++;
}
....
}
while fulldata splitpoint splitval, , splitpoint , . while , .
V6019 Unreachable code detected. It is possible that an error is present. Tokenizer.java(172)
V6007 Expression 'c != '\n'' is always true. Tokenizer.java(169)
public String getStrippedSubstring() {
int sstart = start, ssend = end;
while(sstart < ssend) {
char c = input.charAt(sstart);
if(c != ' ' || c != '\n' || c != '\r' || c != '\t') {
break;
}
++sstart;
}
....
}
, . V6019 : ++sstart, V6007 if, .
if ? . : c != ' ', c != '\n', c != '\r', c != '\t'. - . false, true, - || () if . if – break, while, sstart . V6019 .
, - :
if(c != ' ' && c != '\n' && c != '\r' && c != '\t')
,
V6009 Function 'equals' receives an odd argument. An object 'other.similarityFunction' is used as an argument to its own method. AbstractSimilarityAdapter.java(91)
@Override
public boolean equals(Object obj) {
if(obj == null) {
return false;
}
if(!this.getClass().equals(obj.getClass())) {
return false;
}
AbstractSimilarityAdapter<?> other = (AbstractSimilarityAdapter<?>) obj;
return other.similarityFunction.equals(other.similarityFunction);
}
equals AbstractSimilarityAdapter. , , , equals . , , equals . .
:
return this.similarityFunction.equals(other.similarityFunction);
, . — , – . – , . – , . , .
, , , . . , ?
, , . , , , , . , . . , .
, , , :