Erreurs, bugs, questions - page 2575

 
Vladimir Simakov:

Oh, c'est si compliqué...

Je ne connais pas l'implémentation de la chaîne, je ne peux que deviner, mais à en juger par l'erreur, string out crée un pointeur sur la pile qui est initialisé à 0x0000000000 et vous déréférencez sans risque un pointeur nul dans la dll.

Désolé, je n'ai pas remarqué StringInit (((.
 
Roman:

La mémoire est allouée dans le code mql en tant que

et est passé comme un pointeur à la mémoire allouée, comme string dans mql est wchar_t* dans dll

Creusez dans la dll elle-même, quelque chose s'y trouve très probablement. Dernièrement, j'ai transmis des données de mql à des applications tierces C++/C#, sans aucun problème.

 
Vladimir Simakov:

Creusez dans le dll lui-même, il y a probablement quelque chose là. Dernièrement, j'ai transmis des données de mql à des applications tierces C++/C#, sans aucun problème.

Le dll est très simple, il n'est pas nécessaire pour la clarté, l'idée elle-même est montrée.

wchar_t* out        = L"";
const wchar_t* data = L"";

while(condition)
{
   data = getData();  //getData библиотечная функция возвращает const wchar_t*
   wcscpy(out, data);
}

Sortir les données de résultat sur la console, toutes les lignes de la console sont claires, pas de trous ni d'accrocs.
Je passe le résultat à mql par wcscpy(out, data), mais maintenant j'ai des problèmes.
Mais si je passe une chaîne de contrôle écrite à la main.

wchar_t* out        = L"";
const wchar_t* data = L"";

while(condition)
{
   data = L"{\"p\":\"2000\"}";  //проверочная строка
   wcscpy(out, data);
}

Je n'ai pas de problèmes pour une raison quelconque.

Hm, est-ce que le type string dans mql considère le terminal null wchar_t * ? ?

Dossiers :
 

Suggestion pour étendre un peu la possibilité de l'événement OnTimer()

Au moment où l'événement OnTimer() commence à se produire, la périodicité de l'appel est définie par la fonction EventSetTimer().

Il s'avère que le conseiller expert suivant :

bool timer_set = false;
int OnInit()
{
   return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
   EventKillTimer();
}
//+------------------------------------------------------------------+
void OnTick()
{
   if (!timer_set)
      {
         // -- имитация включения советника в какое-то
         // -- случайное время
         string time = TimeToString(TimeTradeServer(), TIME_DATE | TIME_MINUTES | TIME_SECONDS);
         if (TimeCurrent() >= D'2019.09.24 3:47:40')
            {
               EventSetTimer(600);
               timer_set = true;
            }
      }
}
//+------------------------------------------------------------------+
void OnTimer()
{
//---
   string time = TimeToString(TimeTradeServer(), TIME_DATE | TIME_MINUTES | TIME_SECONDS);
   printf("Current time: %s", time);
}
//+------------------------------------------------------------------+

Les sorties sont approximativement les suivantes :

QJ      0       07:53:10.369    test_timer (GBPUSD_i,D1)        2019.09.24 03:57:41   Current time: 2019.09.24 03:57:41
NF      0       07:53:11.246    test_timer (GBPUSD_i,D1)        2019.09.24 04:07:41   Current time: 2019.09.24 04:07:41

Cependant, il est souvent suffisant de vérifier l'apparition du signal après l'apparition d'une autre barre.

Par exemple, il s'avère que pour PERIOD_M15, la barre apparaît à 00:15:00, mais la vérification par le Conseiller Expert ne peut la vérifier qu'à 00:29:59.

C'est-à-dire pour des résultats plus ou moins stables et égaux, quelle que soit l'heure de démarrage du conseiller expert,

vous devrez définir une minuterie pour un intervalle de temps plus court ou utiliser en plus OnTick().

Comme les expériences l'ont montré, cela ralentit considérablement la vitesse des tests dans le testeur de stratégie.

Suggestion :

Ajouter une fonction qui permettrait de définir le temps initial à partir duquel l'événement OnTimer est compté.

Par exemple, une fonction EventSetTimerFrom(const datetime SinceDT) qui vous permettrait de définir l'appel du minuteur quelques secondes après une nouvelle barre.

 
Roman:

La dll est simple, les trucs superflus ont été enlevés pour plus de clarté, l'idée est montrée.

Je colle le résultat dans la console, toutes les lignes sont correctes, pas de trous, pas de problèmes.
Je passe le résultat à mql par wcscpy(out, data), mais maintenant j'ai des problèmes.
Mais si je passe une chaîne de contrôle écrite à la main.

Je n'ai pas de problèmes pour une raison quelconque.

Hm, est-ce que le type string dans mql considère le terminal null wchar_t * ? ?

Mais cette fonction fonctionne.

wcsncpy(out, data, wcslen(data));

Mais ce n'est pas tout à fait correct, il semble y avoir un mauvais caractère à la fin de la chaîne, une parenthèse supplémentaire } apparaît puis disparaît.
wcslen(données)+1
wcslen(données)+2
n'a pas aidé,
et est analysé sans erreurs, sans fuites.

aucune idée de ce qu'est la longueur ou la taille d'un caractère dans une chaîne de caractères mql-looking
il y a certainement une erreur dans le type de chaîne.

Et dans un article paru il y a longtemps, au paragraphe 3.3 Passing and modifying strings, l'exemple comportait très probablement une erreur.

_DLLAPI void fnReplaceString(wchar_t *text, wchar_t *from, wchar_t *to)
  {
   wchar_t *cp;
    
   //проверка параметров
   if(text==NULL || from==NULL || to==NULL) return;
   if(wcslen(from)!=wcslen(to))             return;
   
   //поищем подстроку
   if((cp=wcsstr(text,from))==NULL)         return;
   
   //заменим
   memcpy(cp,to,wcslen(to)*sizeof(wchar_t));  //в этой строке должен быть указатель sizeof(wchar_t *)
  }

Peut-être que quelque part dans le code du terminal, la conversion des chaînes mql fonctionne de la même manière, sans pointeur.

 
Maksim Emeliashin:

définit le temps initial à partir duquel l'événement OnTimer est décompté.

Vous pouvez le faire vous-même en appelant plusieurs fois EventSetTimer. Notez que dans le compte (et non dans le Testeur), la minuterie flotte et nécessite un ajustement constant.

 
fxsaber:

Vous pouvez le faire vous-même par un appel répété à EventSetTimer. Gardez à l'esprit que sur le compte (et non dans le Testeur), la minuterie flotte et nécessite un ajustement constant.

Merci, c'est utile !

Très étrange, bien sûr, qu'un point aussi simple ne soit pas pris en compte dans le terminal "out of the box".

 
Roman:

Mais cette fonction fonctionne.

Mais cela semble un peu gênant, une parenthèse supplémentaire } apparaît ou disparaît à la fin de la chaîne.
wcslen(données)+1
wcslen(données)+2
n'a pas aidé,
et est analysé sans erreurs, sans fuites.

aucune idée de ce qu'est la longueur ou la taille d'un caractère dans une chaîne de caractères mql-looking
il y a certainement une erreur dans le type de chaîne.

Et dans un article paru il y a longtemps, au paragraphe 3.3 Passing and modifying strings, l'exemple comportait très probablement une erreur.

Peut-être que quelque part dans le code du terminal, la conversion de la chaîne mql fonctionne de la même manière, sans le pointeur.

getData() dig. J'ai le sentiment qu'il y a un problème là-dedans, quelque part.
 
Roman:

Le dll est simple, il a été retiré pour plus de clarté et l'idée est montrée

Vos exemples sont amusants, vous avez tout supprimé, laissé UB (modification des littéraux de chaînes de caractères), et tout le monde doit se téléporter. Si vous espérez obtenir des conseils avisés, donnez un minimum de code fonctionnel (sur les deux côtés), sinon c'est juste de la merde.

 
Vict:

Vos exemples sont amusants, vous avez tout supprimé, vous avez laissé l'UB (modification littérale de la chaîne), et tout le monde doit se téléporter. Si vous espérez obtenir des conseils avisés, donnez un minimum de code fonctionnel (sur les deux côtés), sinon c'est juste de la merde.

L'exemple montre l'endroit qui cause le problème, c'est-à-dire que le problème se situe dans la copie du pointeur wchar_t* vers la chaîne mql.
Le reste du code n'est pas pertinent pour le problème et n'est pas utile, car il vérifie simplement s'il y a des données, puis les lit, etc.
Pourquoi l'écrire dans l'exemple et contaminer l'essence du problème, alors que même avec un code simplifié, de nombreuses personnes ne comprendront pas quel est le problème.
Comprenez,getData() est une fonction réseau qui lit le FrameOpcode, et renvoie les données reçues sous forme de pointeur vers une chaîne de type const wchar_t *.

Tout le monde sait qu'une simple fonctionwcscpy(out, data) copie lachaîne const wchar_t * dansla chaînewchar_t *, et compte automatiquement la longueur des caractères jusqu'au terminal null const wchar_t *.
Ici nous rencontrons une erreur, mql string n'accepte pas correctement une chaînecopiéewchar_t *, alors pourquoi ? Si la fonction détecte automatiquement le terminal null.
Dans l'article de Renat, les chaînes de caractères sont copiées via memcpy avec une erreur de taille d'octet. Peut-être que la même approche est utilisée dans le code du terminal lui-même, pour former une chaîne de type mql.
Vous voyez,
memcpy n'est pas seulement inadapté à la copie de chaînes de caractères, mais aussi avec l'erreur de taille des octets passés, il en résulte des données inégales.
Il existe d'autres fonctions C spéciales pour la copie de chaînes de caractères, telles quewcscpy, wcsncpy, etc.
Et Renat lui-même a écrit dans l'un des fils que bientôt sera complètement retravaillé le travail avec des cordes, apparemment le problème est connu, mais pour une raison quelconque silence en réponse au problème que j'ai indiqué.

Voici une comparaison de la taille en octets du pointeurwchar_t* et du simple typewchar_t

Dossiers :
1.PNG  83 kb