Errori, bug, domande - pagina 2639

 
Aleksey Vyazmikin:

La chiave della modalità portatile è richiesta per caso?

Tutti i terminali si avviano manualmente?

A mano, sì, lo fanno tutti. Alla fine, è così che li ho avviati manualmente.

Il tasto della modalità portatile non cambia nulla in questo senso.

Il fatto è che MT4 lancia una finestra di autorizzazione e l'avvio del programma non è considerato completato.

Devi usare "start" nel file batch.

Tutto sommato, sembra che io abbia capito tutto.

Grazie per la vostra partecipazione!

 
Petros Shatakhtsyan:

Non hai ancora capito di cosa si tratta, probabilmente non leggi attentamente i miei post. Il mio appello è rivolto agli sviluppatori, non a voi. Non ho bisogno dei tuoi consigli da quattro soldi.

Calmati e non preoccuparti così tanto.

Ancora una volta sono convinto che le persone con un basso sviluppo cerebrale di solito hanno poca comprensione della civiltà.

Non riesci nemmeno a capire quello che ti viene detto da persone più competenti, e sei maleducato come un bambino dell'asilo che non ha nemmeno imparato a scrivere correttamente.

 
Sfortunatamente, o forse fortunatamente, non faccio alcuno sviluppo diretto,
Tuttavia, è il lavoro sui progetti che ti permette di valutare le capacità del linguaggio e scoprire i suoi difetti e bug...

In precedenza, quando si lavorava su progetti MQL, l'informazione sui difetti (bug) era fornita nell'ordine della loro individuazione.
Ora abbiamo deciso di provare un nuovo approccio: lavorare fino a un difetto bloccante e poi fornire informazioni su tutti i difetti rilevati.
 
#ifdef __cplusplus
   #include <iostream>
#endif 

#define  PRINT(x) ; Print(#x, ":", string(x))


template<typename T>
class main_wrapper{
public:
   T data;
};

template<typename T>
class external_wrapper{
public:
   T data;
};

template<typename T>
class A{
public:
   class internal_wrapper : public external_wrapper<T> {};
   
   main_wrapper<internal_wrapper> internal_wrapper_0;
   main_wrapper<external_wrapper<T>> external_wrapper_0;
   
   A(){
        main_wrapper<internal_wrapper> internal_wrapper_1;
        main_wrapper<external_wrapper<T>> external_wrapper_1;
   
        #ifdef __MQL5__
            PRINT(__FUNCSIG__);
            PRINT(typename(internal_wrapper_0.data.data));      // (Bug) int  int
            PRINT(typename(external_wrapper_0.data.data));      // (OK)  int  B*
            PRINT(typename(internal_wrapper_1.data.data));      // (Bug) int  int
            PRINT(typename(external_wrapper_1.data.data));      // (OK)  int  B*
        #endif
   }
};

class B{
   char data[10];
};

class C{
   char data[1000];
};


void OnStart()
{ 
   A<int> val_int;
   A<B*> val_ptr;
   
   printf("%d\n", sizeof(main_wrapper<A<B>::internal_wrapper>));  // (Bug) 36  //sizeof(main_wrapper<A<int>::internal_wrapper>) is used
   printf("%d\n", sizeof(main_wrapper<A<C>::internal_wrapper>));  // (Bug) 36  //sizeof(main_wrapper<A<int>::internal_wrapper>) is used
}

int main(){
   OnStart();
   return 1;
}
Bug molto brutto di MT5 (build 2316) che blocca l'ulteriore sviluppo.
Si crea più volte un oggetto complesso avvolto con il tipo interno "C", ma si scopre che è un tipo di dati completamente diverso, forse "B", "int", qualsiasi cosa si voglia...

Mi ci è voluto molto tempo e sforzo per trovare e capire che il problema non è nel codice ma nel compilatore MQL. (C++ online:https://onlinegdb.com/H1R1fR5ML)
Presumibilmente, il problema è nel lavoro della cache della classe template "main_wrapper" durante la generazione del codice al momento della compilazione quando la classe interna "internal_wrapper" dalla classe template "A" viene passata come parametro per diversi tipi di dati (int, B*, B, C).
Quale primo tipo di dati è creato dalla classe template "main_wrapper<A<TEMPLATE_TYPE>::internal_wrapper>, tale tipo di dati sarà ulteriormente usato in tutti gli oggetti del template in futuro.


Un altro bug con la generazione del codice della classe del modello sarà fornito di seguito.
 
class A{
public:
   class B{};
};

template<typename T>
class wrapper{
public:
   T data;
};

template<typename T>
class wrapped_B{
public:
   A::B data;
};
   
void OnStart()
{ 
   A::B a;                // OK
   wrapper<A::B> b0;      // 'B' - unexpected token, probably type is missing?  'data' - semicolon expected     
   
   wrapped_B<A::B> b2;    // OK
   
   class local_B : public A::B{};
   wrapper<local_B> b1;   // OK
}


int main(){
   OnStart();
   return 0;
}

Un altro bug di MT5 (build 2316) con la generazione di codice di classe template quando si usa una classe interna.
C++ online:https://onlinegdb.com/HJkKXAqMU

 
template<typename T>
class type_wrapper{
    T data;
};

template<typename T>
class A{
   class type_wrapper : public :: type_wrapper<T>{}; // '::' - syntax error      
};

void OnStart()
{ 
   A<int> a;
}


int main(){
   OnStart();
   return 0;
}

Un altro difetto diMT5 (build 2316) relativo allaclasse interna è la mancanza di capacità di fare esplicitamente riferimento allo spazio dei nomi globale.
C++ online:https://onlinegdb.com/H14NF05G8

 
Sergey Dzyublik:
Un bug molto brutto che blocca ulteriori sviluppi.
Si crea più volte un oggetto complesso avvolto con il tipo interno "C", ma si scopre che è un tipo di dati completamente diverso, forse "B", "int", qualsiasi cosa si voglia...

Mi ci è voluto molto tempo e sforzo per trovare e capire che il problema non è nel codice ma nel compilatore MQL. (C++ online:https://onlinegdb.com/H1R1fR5ML)
Presumibilmente, il problema è nel lavoro della cache della classe template "main_wrapper" durante la generazione del codice al momento della compilazione quando la classe interna "internal_wrapper" dalla classe template "A" viene passata come parametro per diversi tipi di dati (int, B*, B, C).
Quale primo tipo di dati è creato dalla classe template "main_wrapper<A<TEMPLATE_TYPE>::internal_wrapper>, tale tipo di dati sarà ulteriormente usato in tutti gli oggetti del template in futuro.


Un altro bug con la generazione del codice della classe del modello sarà fornito di seguito.
#ifdef __cplusplus
   #include <iostream>
#endif 

#define  PRINT(x) ; Print(#x, ":", string(x))


template<typename T>
class main_wrapper{
public:
   T data;
};

template<typename T>
class external_wrapper{
public:
   T data;
};

template<typename T>
class A{
public:
   template<typename T1>
   class internal_wrapper : public external_wrapper<T1> {};
   
   main_wrapper<internal_wrapper<T>> internal_wrapper_0;
   main_wrapper<external_wrapper<T>> external_wrapper_0;
   
   A(){
        main_wrapper<internal_wrapper<T>> internal_wrapper_1;
        main_wrapper<external_wrapper<T>> external_wrapper_1;
   
        #ifdef __MQL5__
            PRINT(__FUNCSIG__);
            PRINT(typename(internal_wrapper_0.data.data));      // (Bug) int  int
            PRINT(typename(external_wrapper_0.data.data));      // (OK)  int  B*
            PRINT(typename(internal_wrapper_1.data.data));      // (Bug) int  int
            PRINT(typename(external_wrapper_1.data.data));      // (OK)  int  B*
        #endif
   }
};

class B{
   char data[10];
};

class C{
   char data[1000];
};


void OnStart()
{ 
   A<int> val_int;
   A<B*> val_ptr;
   
   printf("%d\n", sizeof(main_wrapper<A<B>::internal_wrapper<B>>));  // (Bug) 36  //sizeof(main_wrapper<A<int>::internal_wrapper>) is used
   printf("%d\n", sizeof(main_wrapper<A<C>::internal_wrapper<C>>));  // (Bug) 36  //sizeof(main_wrapper<A<int>::internal_wrapper>) is used
}
È corretto?
 
Vladimir Simakov:
È il modo giusto per farlo?

Grazie, in effetti l'introduzione di un parametro template fittizio, nel caso dell'esempio, aggira il problema.
Tuttavia, per quanto riguarda il progetto globale, le cose sono un po' più complicate: laclasse interna è stata usata come alternativa alla funzionalità typedef typename mancante per semplificare sia il processo di sviluppo che l'applicazione della classe contenitore finale.
Potrebbe valere la pena aspettare una correzione da parte degli sviluppatori.
Come ultima risorsa, tutte le dipendenze dovranno essere trascinate verso l'esterno, sperando che non ci sia un'ulteriore compilazione di successo con un comportamento indefinito a runtime.

 

Per riassumere la funzionalità interna della classe,
possiamo chiaramente dire che manca la funzionalità della dichiarazione typedef, almeno la sua forma primitiva, per usarla correttamente...
Quindi, invece di un codice C++ abbastanza compatto e comprensibile:

template <class _Tp, class _Allocator>
class vector
    : private __vector_base<_Tp, _Allocator>
{
private:
    typedef __vector_base<_Tp, _Allocator>           __base;
public:
    typedef vector                                   __self;
    typedef _Tp                                      value_type;
    typedef _Allocator                               allocator_type;
    typedef typename __base::__alloc_traits          __alloc_traits;
    typedef typename __base::reference               reference;
    typedef typename __base::const_reference         const_reference;
    typedef typename __base::size_type               size_type;
..............................


Dobbiamo costruire un recinto con #define e l'ereditarietà attraverso la classe interna:

template<typename _Tp, typename _Allocator>
class __vector_base{
public:
   class allocator_type    : public _Allocator{}; 
   
protected:
   #define  value_type          _Tp
   #define  size_type           DEFAULT_SIZE_TYPE
   #define  difference_type     size_type
   
   struct pointer          : public allocator_type::pointer{};
   struct iterator         : public allocator_type::pointer{};
............................

   #undef  value_type
   #undef  size_type
   #undef  difference_type
};


E qui ci sono molti più problemi di quanto possa sembrare a prima vista.
Si verificano problemi quando si usa #define come dichiarazione typedef:

- non c'è modo di passare il tipo di dati usati al di fuori della classe (non c'è proprio modo di passare tipi di dati semplici);
- è necessario controllare costantemente lo scopo di #define con la corrispondente coppia #undef

Problemi quando si usa una classe interna come dichiarazione typedef:
- è possibile passare il tipo di dati di classe/struttura usato al di fuori della classe (i tipi di dati semplici non possono essere passati affatto);
- l'ereditarietà perde tutti i costruttori, devono essere riscritti manualmente usando le firme della classe base;
- se la classe in cui viene usata la dichiarazione typedef ha una classe base, allora attraverso i namespace sovrapposti non c'è modo di usare lo stesso nome della dichiarazione typedef;
- le classi ereditano dalle classi, le strutture dalle strutture, questo deve essere costantemente controllato;
 
A causa dell'introduzione di operatori di assegnazione predefiniti, è diventato necessario proibire l'esecuzione di assegnazioni casuali per la classe base.
Gli sviluppatori hanno aggiunto "operator= delete" per questo scopo.
Tuttavia, non sembra logico rompere il link di cancellazione/default, perché tutto deve essere scritto di nuovo manualmente.
Forse sto facendo qualcosa di sbagliato?

class Base{
    char base_data[100];
};

template<typename T>
class A : public Base{
   int data_1;
   int data_2;
   int data_3;
   int data_4;
   int data_5;
   int data_6;
   int data_7;
   int data_8;
   int data_9;
   
   char arr_1[];
   char arr_2[];
public:    
   // MQL
   A* operator=(A &obj){
      data_1 = obj.data_1; 
      data_2 = obj.data_2; 
      data_3 = obj.data_3; 
      data_4 = obj.data_4; 
      data_5 = obj.data_5; 
      data_6 = obj.data_6; 
      data_7 = obj.data_7; 
      data_8 = obj.data_8; 
      data_9 = obj.data_9; 
      
      ArrayCopy(arr_1, obj.arr_1);
      ArrayCopy(arr_2, obj.arr_2); 
      
      (Base)this = obj;
      return &this;
   };
   
   // C++
   // A& operator=(A &) = default;
    
   template<typename TT>
   A* operator=(A<TT> &) = delete;
};

void OnStart()
{ 
   A<int> a;
   A<int> b;
   
   A<double> c;
   
   a = b;      
   //a = c;       
}