In MQL5 gibt es immer Raum für einen Exploit! ;) - Seite 8

 
du rührst Wasser in einem Eimer um.
Zeiger auf Variablen, auf Funktionen und die Übernahme von Adressen durch Verweise sind allesamt MQL-Einschränkungen.
Es handelt sich nicht einmal um etwas, das in der Syntax nicht vorgesehen ist, sondern um ein Verbot der Speicherbehandlung.
Auch der void*-Zeiger ist kein Zeiger im üblichen C-artigen Sinne.
Es ist ein Objekt, das mit Klassenobjekten arbeitet, um zu verhindern, dass sie kopiert werden.
Die gleiche Referenz & ist keine Adressübernahme, sondern eine Angabe für den Compiler, um ein Objekt zu übergeben, ohne es in den Stack zu kopieren.
Wenn Sie in Syakh schreiben wollen, schreiben Sie in Syakh und importieren Sie dll, das ist in Ordnung.

Wenn es Ihnen wirklich in den Fingern juckt und Sie die dll nicht vorhersehen können, dann ist der Import aus der nativen dll keine große Sünde, und Ihr MQL-Produkt wird dadurch nicht an Wert verlieren.

Um nicht zu viel Aufhebens zu machen, können Sie zum Beispiel nur einen 4-Byte-Zeiger verwenden und memcpy importieren, um mit dem Speicher innerhalb eines Terminalprozesses zu arbeiten.

#import "msvcrt.dll"
int memcpy(short&,short&,int);
int memcpy(int&,int&,int);
int memcpy(double&,double&,int);
int memcpy(string& s,string& int);
#import

eine Art von Wrapper-Klasse:

struktur TPtr
{
int addr;
TPtr():addr(0){}
TPtr(const TPtr& r):addr(r.addr){}
template<typename _T> TPtr operator =(_T& r) {
addr = memcpy(r,r,0);
dies zurückgeben;
}
};


und ein praktisches Beispiel:

string sval = "123";
kurz bval = 123;
int ival = 123;
double dval = 123;

TPtr p = sval;
int ptrs = p.addr;
p = bval;
int ptrb = p.addr;
p = ival;
int ptri = p.addr;
p = dval;
int ptrd = p.addr;

Auf diese Weise können Sie den Speicher nach Belieben manipulieren... Nicht die üblichen C-Zeiger, aber dennoch

Wie kann sie nützlich sein?
Sie können zum Beispiel die Importfunktion GlobalAlloc verwenden, so dass Sie keine globalen Variablen verwenden müssen, um Daten zwischen Modulen zu übertragen.
GlobalAlloc weist dem Prozess Speicher zu, der nicht mit einem Heap oder internen statischen virtuellen für die Arbeit einer Eule oder eines induzierten verbunden ist.
Sie können Arrays beliebiger Größe darin platzieren und memcpy zur Indizierung verwenden.

Beispiel importieren:

#define HANDLE int
#define LPVOID int

#import "kernel32.dll"
HANDLE GlobalAlloc(uint flags, uint cnt);
LPVOID GlobalLock(HANDLE hmem);
int GlobalUnlock(HANDLE hmem);
HANDLE GlobalFree(HANDLE hmem);
#import "ntdll.dll".
// GetLastError existiert bereits in MT, daher von WinAPI verwenden:
int RtlGetLastWin32Error();
#import


Ein Beispiel für die Verwendung:

// owl N1, bereiten Sie Ihr Array von Raten vor

MqlRates rates[123];
// hier füllen wir
HANDLE memid = GlobalAlloc(GMEM_MOVEABLE, 123*sizeof(MqlRates));
LPVOID ptr=GlobalLock(memid);
memcpy(ptr,rates[0].time, 123*sizeof(MqlRates)); // hier sollte man, um zu kompilieren, den Prototyp int memcpy(int&,const datetime&,int)
GlobalUnlock(memid);
// Senden eines Speicherdeskriptors
EventChartCustom(CID, MY_SEND_DATA, memid, 0, "");

// Eule N2
void OnChartEvent(const int id, const long &lparam, const double &dparam, const string &sparam)
{
if( id == CHARTEVENT_CUSTOM+MY_SEND_DATA )
{
LPVOID ptr = GlobalLock((HANDLE)lparam);
MqlRates rates[123];
// Preise erhalten
memcpy(rates[0].time,ptr,123*sizeof(MqlRates)); // hier ist der Prototyp int memcpy(datetime&,const int&,int)
GlobalUnlock(memid);
GlobalFree(memid);
}
}

Das ist alles... keine Pipes, externe Dateien, Import von übrig gebliebenen DLLs.
Ich habe nur eine kleine Probe mit großen Möglichkeiten überstürzt, aber mein Geist kennt keine Grenzen.
Ja, in Bezug auf GlobalAlloc schlage ich immer noch vor, GMEM_MOVEABLE zu verwenden, mit lock und anlock Speicher, um einen Zeiger für eine bestimmte Operation zu erhalten, geben Sie es zurück.
Wenn Sie festen globalen Speicher verwenden, kann es bei einer Anzahl von N offenen Deskriptoren zu einer Fragmentierung kommen...
was immer der Betriebssystem-Kernel je nach Belastung wünscht.
Viel Glück, Hacker )))
 
alexsis78:

Um nicht zu vage zu sein, können Sie zum Beispiel nur einen 4-Byte-Zeiger verwenden und memcpy importieren, um mit dem Speicher innerhalb des Terminalprozesses zu arbeiten
Sie sind ein bisschen auf dem Holzweg.
 

Es gibt ein altes Buch von Henry Warren, "Algorithmische Tricks für Programmierer", das voll von solchen Tricks ist. Die meisten Beispiele funktionieren jedoch nicht in MQL, weil es keine C++-Zeiger gibt.

Ich werde versuchen, etwas Lustiges zu finden.

 
Sie werden die Ähnlichkeit meines Beispiels in C nicht finden ))) Erstens ist es MQL, zweitens ist es ein Workaround für die C-Zeiger-Syntax.

Ein wenig mehr Klarheit für diejenigen, die wissen, plus.

In C:
int var = 0; // deklariere Variable var
int* ptr = &var; // erhalte Zeiger auf Variable var
int var2 = *ptr; // kopiere Wert durch Zeiger auf var in var2

In MQL:
#import "msvcrt.dll"
uint memcpy(int& destination, const int& source, int cnt); // Prototyp von memcpy, um die Adresse der Variablen destination zu erhalten
uint memcpy(int& destination, uint ptr, int cnt); // der memcpy-Prototyp zum Kopieren von der Adresse ptr
// der Compiler ersetzt einen der beiden Prototypen durch den Typunterschied des zweiten Arguments
// Nehmen wir einen Zeigertyp, z.B. uint
#import

int var = 0;
uint ptr = memcpy(var,var,0); // erhält einen Zeiger ptr auf die Variable var (hier kopiert memcpy nichts, sondern liefert die Adresse var)
int var2
memcpy(var2, ptr, 4); // kopiere 4 Bytes oder sizeof(int) vom Zeiger ptr in die Variable var2 (der zweite Prototyp von memcpy funktioniert)

Ich hoffe, Sie finden die Methode nützlich )))
 
alexsis78:
Sie werden die Ähnlichkeit meines Beispiels in C))) nicht finden. Erstens ist es MQL, zweitens die Umgehung der C-Zeiger-Syntax.
Ich hoffe, Sie finden es nützlich ))))

Leute, schreibt nicht nur um des Schreibens willen.

Alle diese Varianten mit memcpy sind schon vor einigen Jahren durchgekaut worden und eignen sich nicht für dieses Thema.

 
o_O:

Leute, schreibt nicht um des Schreibens willen.

Alle diese memcpy-Optionen wurden vor Jahren wiedergekäut und sind für dieses Thema nicht geeignet.

Ich stimme zu, außerdem wurde die Variante ohne Zeigerarithmetik beschrieben, d.h. fehlerhaft. Sie werden in C# nicht wirklich benötigt, es gibt keine Zeiger. Es ist unsicher, aber es ist nur für den persönlichen Gebrauch und es wird eine Menge von Einschränkungen wie Verbot der Installation über das Netzwerk und so weiter sein.
 

Ich wollte es in die Codebasis aufnehmen, aber dann habe ich meine Meinung geändert:

Verwendung von MQL5 bei Kaggle, Ziffernerkennungsaufgabe

Digit Recognizer | Kaggle
  • www.kaggle.com
Kaggle is your home for data science. Learn new skills, build your career, collaborate with other data scientists, and compete in world-class machine learning challenges.
Dateien:
sampleMNIST.mq5  25 kb
 
o_O:

Leute, schreibt nicht nur um des Schreibens willen.

Alle diese memcpy-Optionen sind seit Jahren durchgekaut worden und eignen sich nicht für dieses Thema.

Warum ist es "unangemessen"?

Ich habe schon vergessen, wo es war und konnte es nicht mehr finden...

Übrigens, einen Zeiger auf ein Array zu speichern, ohne externe DLLs aufzurufen, würde ich als Kunststück bezeichnen. Ich möchte nicht jedes Mal, wenn ich Indikatoren starte, bestätigen müssen, dass ich mit dem Import von Funktionen aus der DLL einverstanden bin.

 
George Merts:

Warum ist sie "nicht geeignet"?

Ich habe schon vergessen, wo es war und konnte es nicht mehr finden...

Übrigens würde ich es als Kunststück betrachten, einen Zeiger auf ein Array zu speichern, ohne externe DLLs einzubeziehen. Ich möchte nicht jedes Mal, wenn ich Indikatoren starte, bestätigen müssen, dass ich mit dem Import von Funktionen aus einer DLL einverstanden bin.

Verpacken Sie das Array in eine Klasse, können Sie MQL-Pseudo-Zeiger darauf mit new
 
Alexey Volchanskiy:
Wickeln Sie das Array in eine Klasse ein und Sie können MQL-Pseudo-Zeiger darauf mit new

Alexey, du solltest mir auch sagen, wie man Arrays, die von der Funktion OnCalculate() ausgegeben werden, in eine Klasse einpackt - in diesem Fall geht es nicht ohne das Kopieren von Zeigern.

Im Moment kopiere ich nur Daten in mein Klassenarray, und dann ziehe ich einen Zeiger auf dieses Objekt. Aber das würde zu zusätzlichen Kopiervorgängen führen, die, wie ich sehe, bei häufigen Ticks und einer großen Anzahl von Diagrammen zu einer spürbaren "Schwerfälligkeit" führen. Ich möchte dieses Kopieren loswerden. Aber außer einer Krücke über eine DLL (Standard oder selbst geschrieben), gibt es nichts, was ich vorschlagen kann.

Im Service Desk werde ich immer wieder mit der Aussage "das Objekt kann gelöscht werden" zurückgewiesen. Aber das sind ihre eigenen Arrays! Wenn ich sage, dass ich ein Objekt erstellen und es dann entfernen kann und der Zeiger ungültig wird, antworten sie, dass "ich dafür verantwortlich sein werde". Hier ist eine "doppelte Moral" am Werk.

Ich kümmere mich nicht um die DLL - aber solche Indikatoren erfordern eine ständige Bestätigung, wenn sie laufen - was für ein Ärgernis...