Erreurs, bugs, questions - page 2499

 
Igor Makanu:

apparemment, cela est fait pour tenir compte de l'utilisation interne de sizeof() , c'est-à-dire quesizeof() ne prend pas en compte la mémoire physique, il se contente d'additionner chaque type en octets.

Ce n'est pas le cas.

struct A pack(4)
{
  short j;
  char i;
};

void OnStart()
{
  Print(sizeof(A)); // 4
}
 
fxsaber:

Ce n'est pas le cas.

alors votre exemple vérifiait que sizeof() comptait correctement le "poids" de la structure en octets,

la seule chose qui reste à vérifier est la mémoire physique, mais à mon avis cela ne fonctionnera que lors de l'appel de la dll, pas le fait que les développeurs n'aient pas sur-optimisé le stockage des données en mémoire ;) - c'est-à-dire que si pack(4) n'est pas utilisé comme prévu dans le code, il peut être ignoré dans le code exécutable

 
Igor Makanu:

alors votre exemple vérifie que sizeof() compte correctement le "poids" de la structure en octets

C'est pourquoi la question se pose : comment fonctionne réellement l'alignement ? La documentation et Habr n'ont pas divulgué l'algorithme avec leurs exemples.

Igor Makanu:

La seule chose qui reste à vérifier est la mémoire physique, mais à mon avis cela ne fonctionnera que lors de l'appel de la dll, pas le fait que les développeurs n'aient pas sur-optimisé le stockage des données en mémoire ;) - c'est-à-dire que si pack(4) n'est pas utilisé comme prévu dans le code, il peut être ignoré dans le code exécutable

La mémoire physique est similaire.
struct A pack(4)
{
  short j;
  char i;
};

void OnStart()
{
  Print(sizeof(A)); // 4
  
  const int handle = FileOpen(__FILE__, FILE_WRITE | FILE_BIN);
  
  if (handle != INVALID_HANDLE)
  {
    A a = {0};
    
    FileWriteStruct(handle, a);
    Print(FileTell(handle)); // 4
    
    FileClose(handle);
  }
}
 
fxsaber:

On peut donc se demander comment fonctionne réellement l'alignement. La documentation et hubr n'ont pas divulgué l'algorithme avec leurs exemples.

cela dépend du compilateur spécifique, peut-être que dans MQL vous pouvez essayer union pour voir comment les données ont été sauvegardées en utilisantpack(4)

 
Igor Makanu:

cela dépend du compilateur spécifique, vous pouvez probablement essayer de regarder dans union en MQL pour voir comment les données ont été sauvegardées en utilisant pack(4)

Il existe des compensations et d'autres moyens de le faire.


HH Il s'avère que le fait de fixer un alignement sert à le rendre non ambigu. Mais pas pour un usage personnel. On voit clairement que l'ordre des champs affecte la consommation de mémoire et, apparemment, les performances.

 
fxsaber:

HH Il s'avère que le paramètre d'alignement sert à le rendre sans ambiguïté. Mais pas pour un usage personnel.

et ceci est"tout dépend du compilateur spécifique" - les développeurs cherchent souvent des astuces pour améliorer les performances de leurs développements par rapport à d'autres, il n'y a pas de directives de compilateur dans MQL - comme la désactivation de l'optimisation du code source, etc. - vous ne pouvez pas voir la différence de performance ou d'utilisation de la RAM du code natif


SZZ : Je ne suis pas sûr que l'exemple avec l'écriture dans un fichier fonctionne toujours correctement, quelqu'un a récemment écrit que MQL utilise l'API Win lors de l'écriture dans un fichier, il se peut que certaines hypothèses soient faites pour la compatibilité avec les fonctions de l'API - mais ce n'est que ma supposition, je ne suis pas un développeur de compilateur ((()

 
fxsaber:

Il existe d'autres façons de procéder.


Il s'avère que le fait de définir un alignement sert à le rendre non ambigu. Mais pas pour un usage personnel. Et vous pouvez voir que l'ordre des champs affecte la consommation de mémoire.

Vous vous trompez, l'alignement n'est pas du tout nécessaire pour vous, il est nécessaire pour le processeur pour ne pas avoir un int sur deux lignes de cache. L'endroit où la récupération sera effectuée n'est pas réglementé et dépend du compilateur. Vous ne pouvez donc pas compter sur pack() lors du transfert vers le monde extérieur, mais uniquement sur la récupération manuelle.

 
Vict:

Vous vous trompez, l'alignement n'est pas du tout nécessaire pour vous, il est nécessaire pour le processeur de ne pas avoir d'int sur deux lignes de cache. L'endroit où l'ajout est fait n'est pas réglementé et dépend du compilateur, donc vous ne pouvez pas compter sur pack() lors du transfert vers le monde extérieur, seulement sur l'ajout manuel.

C'est devenu clair, merci à tous.

 
fxsaber:

Je veux aller au fond des choses.

Qu'est-ce qu'il y a à comprendre si la documentation dit clairement

Le nom de la structure ne peut pas être utilisé comme identifiant (un nom de variable ou de fonction). Veuillez noter que dans MQL5, les éléments d'une structure se suivent directement , sans alignement. En C++, cette indication est faite au compilateur à l'aide de la fonction

#pragma  pack(1)

Et ainsi de suite...

Ainsi, il n'y a pas du tout d'alignement dans MQL5.

Документация по MQL5: Основы языка / Типы данных / Структуры, классы и интерфейсы
Документация по MQL5: Основы языка / Типы данных / Структуры, классы и интерфейсы
  • www.mql5.com
Структура является набором элементов произвольного типа (кроме типа void). Таким образом, структура объединяет логически связанные данные разных типов. Объявление структуры Имя структуры нельзя использовать в качестве идентификатора (имени переменной или функции). Следует иметь ввиду, что в MQL5 элементы структуры следуют непосредственно друг...
 
Vict:

Vous creusez quelque part au mauvais endroit. Vous n'avez pas besoin d'alignement du tout, le processeur en a besoin pour ne pas avoir un int sur deux lignes de cache.

non, le cache du processeur n'est pas du tout chargé avec la préextraction des données, et les différents niveaux de cache sont chargés avec les prédictions de transition, pack() ne peut pas du tout y arriver (dans le cache), touteopération arithmétique (addition de 2 int) au lieu d'être exécutée sur 1 ou 3 cycles d'horloge (hypothétique) entraînera une analyse de l'alignement des données, etc.

Au niveau physique, cela devrait fonctionner comme suit : le compilateur a créé un code exécutable dans lequel oui, il y aurapack(), mais lors du chargement des données à partir de la RAM, il ne lira que des données int et le pointeur du segment de données sera immédiatement déplacé vers l'octet pack() (et non int byte).


bien que je puisse me tromper, maintenant tous les processus (y compris le processeur lui-même) sont virtualisés et optimisés - c'est mon raisonnement, puisque j'ai lu le livre sur le Pentium-1 quand j'ai étudié -.... c'était tellement cher à l'époque ))))

Raison: