Cómo se verificó PVS-Studio ELKI en enero

Si le parece que el Año Nuevo llegó ayer y no se dio cuenta de cuánto más de la mitad de enero ha pasado, entonces todo este tiempo ha estado ocupado buscando sutiles errores en el código que mantiene. También significa que nuestro artículo es solo para ti. Nosotros, PVS-Studio, verificamos el proyecto de código abierto ELKI para mostrarle qué errores se pueden encontrar en el código, cuán hábilmente se pueden esconder allí y cómo puede lidiar con ellos.







0111_ELKI_ru / image1.png







ELKI - ¿Qué es esta biblioteca?



ELKI Environment for Developing KDD-Applications Supported by Index-Structures. Java . – , , -. , . . .







, , , , . , ELKI, . , . , .







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 . ifbreak, 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);
      
      





, , Java. ' '. , , , .









, . — , – . – , . – , . , .







– . , review , unit . , , .









, , , . . , ?







, , . , , , , . , . . , .







, , , :







  1. Trans-Proteomic Pipeline (TPP).
  2. - .
  3. ?
  4. ROOT — .
  5. NCBI Genome Workbench: .



All Articles