Addio robot - ciao marasma - pagina 7

 
Renat:
...

Test di questo esempio:

  • MQL4/MQL5 - dà avvisi su potenziali errori

  • Visual Studio 2012, compresa l'analisi del codice - niente, la qualità dell'analisi per i potenziali errori è zero. Non si preoccupano perché non ci sono concorrenti per molto tempo.

  • PVS Studio - riporta correttamente.

  • Lint - riporta la stessa cosa, ma la 'x' si nasconde...

    ...

Pavlick:

Penso che anche i messaggi siano assolutamente inutili. Non sono un programmatore professionista, ma questo tipo di assurdità in µl mi stressa. Mi chiedo se i riferimenti ad a e b sono costanti, PVS Studio genererà un avviso (non c'è modo di controllarlo da solo)?

Tuttavia, non è male entrare prima nel succo dell'avvertimento e poi darlo come argomento. PVS Studio vi avvertirà non perché la variabile globale è nascosta, ma perché a e b sono passati da un riferimento non costante ma non sono modificati. In questo caso, credono che a e b debbano essere passati da un riferimento costante. Per esempio, i seguenti esempi non fanno lamentare questo analizzatore:

int a=1,b=2;
int sum(const int& a, const int& b){
        return(a+b);
}

int main(){
        return sum(a,b);
}

//-------------------------------------------------
int a=1,b=2;
int sum(int& a, int& b){
        ++a; ++b;
        return(a+b);
}

int main(){
        return sum(a,b);
}
 

Sono ben consapevole di ciò che PVS ci rimprovera.

Ancora una volta, non abbiamo il peso della responsabilità di compilare miliardi di linee di vecchio codice C/C++. Sta ai loro compilatori non rovinare i loro affari generando avvertimenti. Noi, d'altra parte, abbiamo la responsabilità della sicurezza e del controllo degli errori del nostro linguaggio applicativo, che lavora con il denaro.

Solo pochi per cento degli autori di codice MQL4/5 sono programmatori professionisti (nel vero senso della parola). Tutti gli altri sono solo autodidatti e non hanno idea di quanto male scrivano il codice.

Per esempio, dopo la migrazione all'MQL4 aggiornato, abbiamo dovuto arrovellare manualmente migliaia di fonti nel kodobase e correggere un numero incredibile di errori nel loro vecchio codice. Molti errori sono stati trovati e mostrati dal compilatore, anche senza eseguire i programmi.

Questo è il motivo per cui non dovremmo fare affermazioni sull'emissione di avvertimenti, ma correggere il nostro codice.

 
Renat:

Sono ben consapevole di ciò che PVS ci rimprovera.

Ancora una volta, non abbiamo il peso della responsabilità di compilare miliardi di linee di vecchio codice C/C++. Sta ai loro compilatori non rovinare i loro affari generando avvertimenti. Noi, d'altra parte, abbiamo la responsabilità della sicurezza e del controllo degli errori del nostro linguaggio applicativo, che lavora con il denaro.

Solo pochi per cento degli autori di codice MQL4/5 sono programmatori professionisti (nel vero senso della parola). Tutti gli altri sono solo autodidatti e non hanno idea di quanto male scrivano il codice.

Per esempio, dopo la migrazione all'aggiornato MQL4, abbiamo dovuto arrovellare manualmente migliaia di fonti nel kodobase e correggere un numero incredibile di errori nel loro vecchio codice. Molti errori sono stati trovati e mostrati dal compilatore, anche senza eseguire i programmi.

Ecco perché non dovreste lamentarvi degli avvertimenti emessi, ma correggere il vostro codice.


Se l'array permette di perdere il suo range, sarebbe molto sciocco prendere sforzi paragonabili a quelli della scrittura dell'indicatore quando si scrive l'indicatore stesso, ma solo per il calcolo dell'inizio del calcolo.

Non c'è bisogno di scavare in questo codice, metà di esso non è fissato, è rotto. Avresti potuto semplicemente fare una proprietà aggiuntiva per distinguere tra vecchi mql4, nuovi mql4 o nuovi mql4 con strict. Che dimensioni ha il vecchio compilatore? Non lo so, ma probabilmente meno di un megabyte, nessun problema a portarselo dietro nell'era dei gigabyte. Ma qui abbiamo una sorta di atto eroico - la distruzione della codebase.

* * *

Attenzione

La dichiarazione di 'a' nasconde la dichiarazione globale alla linea X

Questo è un avvertimento idiota. Se qualcuno là fuori, nel mondo "superiore", ha problemi con esso, non significa che altri possano avere tali problemi. C'è uno scopo per le variabili, quello che qualcuno chiama variabili è una questione privata.

 
Integer:


Se si permette a una matrice di scivolare oltre il suo intervallo, sarebbe molto sciocco quando si scrive l'indicatore fare sforzi paragonabili a quelli della scrittura dell'indicatore stesso, ma solo per calcolare l'inizio del calcolo.

Avresti potuto evitare di scavare in questo codice, la metà non è fissata ma rotta. Avrebbe potuto semplicemente fare una proprietà extra per distinguere tra vecchi mql4, nuovi o nuovi con strict. Che dimensioni ha il vecchio compilatore? Non lo so, ma probabilmente meno di un megabyte, nessun problema a portarselo dietro nell'era dei gigabyte. Ma ecco una sorta di lavoro eroico fatto - per distruggere il codebase.

Esattamente fissato, non rotto.

Se un errore è scivolato dopo le modifiche, è del tutto possibile - qualsiasi modifica porta inevitabilmente a tali errori. Ma questo non significa che si possono appendere singoli errori su una bandiera e scalare una montagna di quelli corretti.


La 'a' nasconde la dichiarazione globale alla linea X

Questo è un avvertimento idiota. Se qualcuno nel mondo "superiore" ha problemi con esso, non significa che altri possano avere tali problemi. C'è un'area di visibilità delle variabili, quello che qualcuno chiama variabili è una questione privata.

Persone incredibili che lottano per il diritto all'autoscatto. È particolarmente gratificante che una persona scriva "lascia stare il vecchio compilatore" in tutta serietà.
 
simpleton:

Un errore potenziale è un errore potenziale perché non è necessariamente un errore.

Non lo so, non lo so. Avevamo una regola empirica per mettere i mandati di livello 4 o 5 sul rilascio e spuntare la casella per contare i mandati come errori.

Ci siamo liberati di avvertimenti davvero stupidi con i pragmi, ma ci siamo comunque liberati di loro.

 
Andrei01:

Questa osservazione non ha senso e non fornisce alcuna informazione utile al programmatore in linea di principio, perché non c'è alcun occultamento della variabile "a", come sostenuto.

1.cpp(3): remark #3280: declaration hides variable "a" (declared at line 1)
  int sum(int& a, int& b){        

Se il programmatore usa deliberatamente l'occultamento, allora sì, questa osservazione non ha senso e non fornisce alcuna informazione utile. Se, invece, l'occultamento è stato fatto accidentalmente per negligenza, l'osservazione permette di rilevare l'errore in una fase iniziale.

Andrei01:

L'occultamento avviene solo quando viene creata una copia locale della variabile, che è anche un'azione perfettamente legittima. Anche se un errore si verifica improvvisamente nel codice a causa di questo nascondimento, viene facilmente trovato proprio perché la ricerca trova immediatamente lo stesso nome. Se cominciamo a cambiare e alterare i nomi in un modello di funzione, che è una "soluzione" a questa regola da parte della logica del compilatore, la situazione di ricerca degli errori diventerà molto più complicata e la confusione abbonderà nella comprensione del codice. Sembra ovvio.

Levariabili locali e i parametri sono in uno scope, quindi non importa se un parametro ha questo nome o una variabile locale, ma in ogni caso questo nome nasconde un nome nello scope esterno.

Nascondere non ha niente a che fare con le copie delle variabili, ha a che fare con i nomi delle entità. Sì, anche se è legato a nomi di entità come i tipi:

class A { };

void f(int a) {
        A x;
}

compila:

$ icpc -c 1.cpp
$ 

E questo:

class A { };

void f(int A) {
        A x;
}

Non è così:

$ icpc -c 1.cpp
1.cpp(4): error: expected a ";"
        A x;
          ^

compilation aborted for 1.cpp (code 2)
$ 

Perché il nome A all'interno di una funzione non è più un nome di tipo, ma un nome di parametro variabile. Il nome del tipo dichiarato nell'ambito esterno è ora nascosto dal nome della variabile-parametro. Si può avere un'idea indiretta di questo scoprendo che questo codice

class A { };

void f(int A) {
        A++;
}

compila bene:

$ icpc -c 1.cpp
$ 

In MQL4++ questo non compila già allo stadio di nascondere il nome del tipo con il nome del parametro variabile, cioè anche con un corpo della funzione vuoto:

#property strict

class A { };
void f(int A) { }
void OnStart() { }

risultato:

'A' - structure identifier cannot be used       3.mq4   4       12
'A' - structure identifier cannot be used       3.mq4   4       12

Non so perché, ma non sono affatto sorpreso.

Per il C++, d'altra parte, non c'è alcun problema con tale codice:

class A { };
void f(int A) { }

risultato di un tentativo di compilazione:

$ icpc -c 1.cpp
$ 

Questo esempio mostra che l'occultamento è legato ai nomi delle entità e non ad altro.

Se l'osservazione non è commutabile, dobbiamo inventare ogni sorta di cose, come l'aliasing. Ma se è trasformabile, come nel compilatore Intel, non si hanno questi problemi.

Il problema in MQL4++ non è con la funzionalità del compilatore in sé riguardante il rilevamento di nomi nascosti in scopes annidati, ma con la fondamentale immutabilità di questa funzionalità.

 
Renat:

Quindi non si dovrebbero fare affermazioni sugli avvertimenti, ma correggere il proprio codice.

La lamentela sulle avvertenze/osservazioni in discussione, penso, può essere una sola - sulla loro non escludibilità in linea di principio.

E, naturalmente, non si può dire al programmatore cosa fare all'interno del linguaggio e cosa non fare.

 

Tali messaggi (nascondendo le variabili globali) non hanno senso in C++ (mql è stato dichiarato come c++, giusto?). Per esempio, ecco perché:

struct S1{
    int val;
};

struct S2{};

template<typename _T>
struct SS : _T{
    int f() {int val; return val;}
};

int main(){
    SS<S1> q1; q1.f();
    SS<S2> q2; q2.f();
}
 
Pavlick:

Tali messaggi (nascondendo le variabili globali) non hanno senso in C++ (mql è stato dichiarato come c++, giusto?). Per esempio, ecco perché:

struct S1{
    int val;
};

struct S2{};

template<typename _T>
struct SS : _T{
    int f() {int val; return val;}
};

int main(){
    SS<S1> q1; q1.f();
    SS<S2> q2; q2.f();
}

C++ è stato preso qui perché MQL4++ non ha modelli di struttura/classe - solo modelli di funzione?

Non sono sicuro che gli sviluppatori ne siano consapevoli, ma i modelli di classe sono possibili anche in MQL4++, anche se con limitazioni significative. In particolare, questo esempio può essere trasposto in MQL4++ nel modo seguente (anche un parametro è usato al posto di una variabile locale in un metodo):

#property strict

struct S1 { };
struct S2 { int val; };

template <typename T>
void f(T &t) {
  struct SS: public T {
    int f(int val) { return val; }
  } ss = {0}; // Переменная типа SS
}

void OnStart() {
  S1 s1; f(s1);
  S2 s2; f(s2);
}

Un singolo avvertimento sul fatto di nascondere il nome apparirà alla compilazione:

'3.mq4' 3.mq4   1       1
struct has no members, size assigned to 1 byte  3.mq4   3       8
struct has no members, size assigned to 1 byte  3.mq4   8       10
declaration of 'val' hides member declaration at line 4 3.mq4   9       15
0 error(s), 3 warning(s)                1       4

Se l'ultima linea significativa in OnStart() viene commentata, l'avvertimento sul nascondere il nome scompare.

 
simpleton:

C++ è stato preso qui perché non ci sono modelli di struttura/classe in MQL4++ - solo modelli di funzione?

...

In generale, sì, ma si possono usare anche i µl:

struct S1{
    int val;
};

struct S2{};

#define INSTANTIATE(_Name, _T)          \
    struct _Name : _T                   \
    {                                   \
        int f() {int val; return val;}; \
    }

INSTANTIATE(SS1, S1);
INSTANTIATE(SS2, S2);

void start(){
    SS1 q1; q1.f();
    SS2 q2; q2.f();
}