Stopniowe zapycanie RAMu

0

Witam

mam małą prośbę nie znam C++ :) pisze w C#
czy któryś z kolegów mógłby zerknąć na ten artykuł i sprawdzić czy w kodzie C++ jest coś co nie zwalnia pamięci ??

http://www.codeguru.com/csharp/.net/cpp_managed/windowsservices/article.php/c14735

napisałem dllki na podstawie tego artykułu i która później wywołuje co 100ms ale mam taki problem ze stopniowo zwiększa się użycie RAMu :(

z góry dziękuje za pomoc

0
byte[] whole = new byte[name.Length + helloPart.Length];
// ...
return whole;

// ...


char*  char8UnmanArr = new char[char8ManArr->Length + 1];
//
return char8UnmanArr;

czy c# ma jakies delete, free, czy cokolwiek w ten desen?

0

hmmm

w c# dla testów jest troche zmienione i wylada to tak :

public static byte[] Read(byte[] name)
{
string Name = Encoding.ASCII.GetString(name);
string Status = "ok";
if (Name=="start") Status ="ok2";
byte[] status = Encoding.ASCII.GetBytes(Status);
return status;
}

pzdr Andrzej

0

__declspec(dllexport) char* __stdcall Hello(char* name)
Wygląda że:
pamięć którą przydzieli ta funkcja musisz zwolnić "ręcznie" - przez wskaźnik który zwraca.
Spróbuj najwyżej się wywali na ryja ... [green]
Event , to co zwraca funkcja przekopiować bezpiecznie do obiektu zarządzanego
i wtedy zwolnić delete , bo jakoś to dziwnie wygląda że pamięć może być zwalniana
automatycznie , albo nie w zależności co zrobisz ze zwróconym wskaźnikiem.
W skrócie - czy pamięć przydzielona przez new będzie zwalniana przez C# po utworzeniu
obiektu managed na podstawie tego wskaźnika .. ? Mi się wydaje że nie ..

0

hmmm... dzieki za opdpowiedz
ale powiem sczerze nie owijajac w bawelne nic a nic nie rozumie :(

jakbys mogl mi to wytlumaczyc tak jak sie tlumaczy poczatkujacemu :) bo takim wlasnie jestem

dziekuje i pozdrawiam Andrzej

0

No ,nic nie ważne .. chcesz to podpiąć do MT4 i MQL4 ?
Właśnie grzebię w tym i nie sądzę aby pamięc przydzielona dynamicznie przez
.dll była potem zwalniana przez MQL4 ponieważ w MQL fun z dll C wywołuje się
z prototypem fun(string ) i nie widzę aby była jakaś róznica między LPCSTR , char* itp ..
np z user32.dll :

#import "user32.dll"
   //---- messages
   int      SendMessageA(int hWnd, int Msg, int wParam, int lParam);
   int      SendNotifyMessageA(int hWnd, int Msg, int wParam, int lParam);
   int      PostMessageA(int hWnd, int Msg, int wParam, int lParam);
   void     keybd_event(int bVk, int bScan, int dwFlags, int dwExtraInfo);
   void     mouse_event(int dwFlags, int dx, int dy, int dwData, int dwExtraInfo);
   //---- windows

   int      FindWindowA(string lpClassName, string lpWindowName);//<<======= :-(

   int      SetWindowTextA(int hWnd, string lpString); //<<++++++ :-(

   int      GetWindowTextA(int hWnd, string lpString, int nMaxCount);

więc trzeba to sprawdzić jak zachowuje się MQL . na razie piszę wymianę danych przez .dll
od Meta Tradera do własnej aplikacji, tyle że dll piszę w C/C++ .Nad stringami jeszcze nie myślałem
ale sądząc po tych deklaracjach jestem na 99% pewien że pamieć wycieka bokiem
jeśli użyjesz sposobu przedstawionego w linku który podałeś ...

0

tak pod MT4 i w MQL4

mql4 jest dosc ubogim kodem to takie z tego co sie orientuje uproszczone C

dziekuje za zaangazowanie :)

pzdr Andrzej

0

Halo ,jesteś tam jeszcze ?
Z ciekawości zapytam jak chcesz uzyskać dane od MT4.

Ja przyjąłem coś takiego .
Rezerwuje w systemie wspólny blok pamięci (do odczytu i zapisu) dla
biblioteki .dll i Aplikacji odbierającej .

Wskaźnik albo Strategia MT4 wywołuje funkcje z .dll
która zapisuje do tego bloku ,a klient.exe "nasłuchuje" czy są w pamięci jakieś
dane do odebrania . Możliwa jest też komunikacja od Klienta.exe do .dll
przez fnkcje Dde_CallBack() która zprawdza znacznik zapisywany przez Klienta.
Wten sposób można przez switcha wywoływać różne funkcje napisane w MQL4
zawarte w Wskaźniku lub Strategii .
Takie Coś:

#import "mt4server.dll"

 int  Dde_InitData(string NameSrv);
 int  Dde_FreeData();
 int  Dde_CallBack();
void  Dde_WriteInt(int);
void  Dde_WriteString(string);

#import

//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+

string SrvName = "mt4ddefileserver";
string RetData ;
int IsInit ;

 // ten blok w switch sie  wykona
#define Request_AccountCompany  1 
// gdy Dde_CallBack() zwróci 1
 

int init()
  {
//---- indicators

   IsInit = Dde_InitData(SrvName); // zrób współdzielony
//----                             // blok pamięci o nazwie w 
                                   // SrvName
   return(0);
  }
//+------------------------------------------------------------------+
//| Custom indicator deinitialization function                       |
//+------------------------------------------------------------------+
int deinit()
  {
//----
     Dde_FreeData();
//----
   return(0);
  }
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int start()
  {

//----

   if(IsInit!=0)
   {
     switch(Dde_CallBack())       // Czy wysłać coś?
     {
      case Request_AccountCompany :
 
       RetData = AccountCompany();// FunMQL dane brokera
 
       Dde_WriteString(RetData);  // wysłanie danych do klienta

      break;
      
      default:
      break;
     }
   }

//----
   return(0);
  }   

Tylko ciekawi mnie czy można zapętlić funkcje Start wskaźnika , wszystko to działa
różnie , czasami ślamazarnie z tego względu że Start jest wywoływany dopiero przy
aktualizacji Kursów .
Czasami więc klient będzie musiał czekać na dane zwrotne.
Nie bardzo mi sie to podoba i mam ochotę wrzucić gdzieś pętlę ,nie wiem tylko
czy nie będzie miało to wpływu na MT4 .

0

jestem jestem :)

ja korzystam z przekazy po UDP

a co do petli to w Indicatorze tego nie zrobisz bo zwiesi sie platforma :)

petle mozna spokojnie zrobic w ExpertAdvisor

void start()
{
while(IsExpertEnabled())// petla pracuje gdy włączony jest przycisk "Włącz Strategie"
{
RefreshRate();
//tutaj kod
Sleep(100);
}
}

pzdr Andrzej

0

Acha,dzięki .
Co do tych stringów , myślę że pomiędzy funkcjami .dll i MQL zachodzi jedynie
kopiowanie danych , bo to jest bezpieczne - bez grzebania w pamięci która
należy do biblioteki więc myślę że kod należy przepisać podany w linku na coś takiego :
aby biblioteka kontrolowała pamięć przydzieloną przez new[] .
Po zakończeniu pracy powinna pamięć oddać przez wywołanie funkcji zwalniającej bufor.

char * wsk = NULL ; // wskaźnik globalny w DLL

char * __FunkcjaDLLC/C++( char*s)  // funkcja w DLL
{
   if(wsk)
   {
       delete [] wsk ;  // !!zwolnienie pamięci jeśli funkcja była już kiedyś wywołana
   } 

   // TUTAJ KOD

      wsk = new char[iles_danych];
 // jakieś tam operacje na wsk
      return wsk;
}
//-----------------------------------------------------
// wywołane w int deinit() MQL4
void __FunkcjaDLLZwalniającaBufor(void)
{
     if(wsk)        // podobno wywołanie delete z NULL jest bezpieczne ,ale niech będzie :-)
     {
        delete [] wsk ;
        wsk = NULL ;         // !!!!!!
     }
}
0

hmmm
zrobilem tak :

// Read2.cpp : Defines the exported functions for the DLL application.
//

#include "stdafx.h"
#ifdef _MANAGED
#pragma managed(push, off)
#endif

#ifdef _MANAGED
#pragma managed(pop)
#endif
char*  char8UnmanArr1 = NULL ;
char*  char8UnmanArr2 = NULL ;
char*  char8UnmanArr3 = NULL ;
#using "Read1.dll"
using namespace Read1;
__declspec(dllexport) char* __stdcall Init(char* ip, char* port)
{
	// IP
   int i = 0;
   while (*ip != '\0')
   {
      i++;
      ip++;
   }
   array<unsigned char>^ Ip = gcnew array<unsigned char>(i);
   ip -= i;
   i = 0;
   while (*ip != '\0')
   {
      Ip[i] = *ip;
      ip++;
      i++;
   }
	// PORT
   int j = 0;
   while (*port != '\0')
   {
      j++;
      port++;
   }
   array<unsigned char>^ Port = gcnew array<unsigned char>(j);
   port -= j;
   j = 0;
   while (*port != '\0')
   {
      Port[j] = *port;
      port++;
      j++;
   }
   array<unsigned char>^ char8ManArr =
      Class1::Init(Ip,Port);
    if(char8UnmanArr1)
   {
       delete [] char8UnmanArr1 ;  // !!zwolnienie pamięci jeśli funkcja była już kiedyś wywołana
   }
   char8UnmanArr1 = new char[char8ManArr->Length + 1];
   for (int i = 0; i < char8ManArr->Length; i++)
   {
      char8UnmanArr1[i] = char8ManArr[i];
   }
   char8UnmanArr1[char8ManArr->Length] = '\0';
   return char8UnmanArr1;
}



__declspec(dllexport) char* __stdcall Deinit(char* port)
{
	// PORT
   int j = 0;
   while (*port != '\0')
   {
      j++;
      port++;
   }
   array<unsigned char>^ Port = gcnew array<unsigned char>(j);
   port -= j;
   j = 0;
   while (*port != '\0')
   {
      Port[j] = *port;
      port++;
      j++;
   }
   array<unsigned char>^ char8ManArr =
      Class1::Deinit(Port);
   if(char8UnmanArr2)
   {
       delete [] char8UnmanArr2 ;  // !!zwolnienie pamięci jeśli funkcja była już kiedyś wywołana
   }
   char8UnmanArr2 = new char[char8ManArr->Length + 1];
   for (int i = 0; i < char8ManArr->Length; i++)
   {
      char8UnmanArr2[i] = char8ManArr[i];
   }
   char8UnmanArr2[char8ManArr->Length] = '\0';
   return char8UnmanArr2;
}

__declspec(dllexport) char* __stdcall Read(char* name, char* port)
{
	// NAME
   int i = 0;
   while (*name != '\0')
   {
      i++;
      name++;
   }
   array<unsigned char>^ Name = gcnew array<unsigned char>(i);
   name -= i;
   i = 0;
   while (*name != '\0')
   {
      Name[i] = *name;
      name++;
      i++;
   }
	// PORT
   int j = 0;
   while (*port != '\0')
   {
      j++;
      port++;
   }
   array<unsigned char>^ Port = gcnew array<unsigned char>(j);
   port -= j;
   j = 0;
   while (*port != '\0')
   {
      Port[j] = *port;
      port++;
      j++;
   }
   array<unsigned char>^ char8ManArr =
      Class1::Read(Name,Port);
   if(char8UnmanArr3)
   {
       delete [] char8UnmanArr3 ;  // !!zwolnienie pamięci jeśli funkcja była już kiedyś wywołana
   }
   char8UnmanArr3 = new char[char8ManArr->Length + 1];
   for (int i = 0; i < char8ManArr->Length; i++)
   {
      char8UnmanArr3[i] = char8ManArr[i];
   }
   char8UnmanArr3[char8ManArr->Length] = '\0';
   return char8UnmanArr3;
}


i Od razu po uruchomieniu wywalilo mi Terminal :( (blad krytyczny)
Crash

moze cos zle zrobilem ??

pzdr Andrzej

0

A bez tych modyfikacji delete[] toto chodzi ?

0

tak ... ale dane odbierane przez Terminal sa niekompletne .

np z innego terminala przesylam

1.12345
to jak jest wskaznik ustawiony jako lokalny to odbiera ok

ale jak dam go jako globalny to jest np 0.12345 ?? lub calkiem co innego :)

a Ram dalej zapycha

pzdr Andrzej

EDIT

z dllki korzysta kilka wykresow
i jest tak ze jak char* ustawiony jet globalnie to odbiera czasami ni swoje dane tylko innego wykresu

0

? .
Chym.
Te funkcje np:
__declspec(dllexport) char* __stdcall Read(char* name, char* port)
wywołujesz w kodzie Strategii MQL4 ?
A nie można tego napisać bez użycia unmanaged i wyeksportować ?
Tyle wiem że pisząc funkcje zawarte w bibliotece DLL musiałem użyc dodatkowo
CALLBACK dla funkcji eksportowanych bo inaczej też mi wywalało terminal ,
ale nie wiem jak w tym przypadku .
Prototypy fun wyglądają np tak :
int __declspec(dllexport) CALLBACK Dde_InitData(LPCSTR);
Ale jak ma się to do C#.dll to nie mam pojęcia ..

z dllki korzysta kilka wykresow

Za daleko , namiesza się .
Najpierw testuj na jednej .

a Ram dalej zapycha

Może to jest wina kodu zarządzanego a nie new ...

0

wiec tak
Init() jest wywolywane w init()mql // uruchamia serwer UDP
Deinit() w deinit() mql // wylacza serwer UDP

Read jest w funkcji start()mql zapetlonej co 100ms

i odczytuje w zaleznosci co potrzebuje i na jakim porcie

.....

nawet ja wyrzucilem wszystko c# to dalej Ram stopniowo sie zwieksza
wiec wydaje mi sie ze to po stronie c++
pzdr Andrzej

0

Wiesz co ,w..l to wszystko .
Zacznij od małego kroku .
Zrób bibliotekę testową z jedną funkcją ,jak zachowuje się zwalnianie pamięci bo mi to ładnie
chodzi i na kilku wykresach jako Strategia:
kod DLL

char * wsk = NULL ; // wskaźnik globalny w DLL
/*

PROTOTYP DLA MGL :
       string Read(string);
*/
/* tu mam właściwie 
extern "C" char * __declspec(dllexport) __stdcall Read( char*s);
*/ 
char * __declspec(dllexport) __stdcall Read( char*s);

char * __stdcall Read( char*s)  // funkcja w DLL
{
   if(wsk)
   {
     delete [] wsk ;  // !!zwolnienie pamięci jeśli funkcja była już kiedyś wywołana
     wsk = NULL ;
   }

   // TUTAJ KOD

      Beep(0x300,0x20);
      wsk = new char[10240];
      lstrcpy(wsk,s);
      return wsk;
}
//-----------------------------------------------------

Funkcja Read przydziela spore bloki pamięci , bez delete (jak sie usunie) zażera Pamięć
z delete jest wszystko OK .
A w MQL jakiś kod z użyciem Read(string) byle co , aby tylko wywołac fun Read np:

string temp ;
string RetData ;
int start()
  {

//----
 while(IsExpertEnabled())
 {
   if(IsInit!=0)
   {

       RetData = AccountCompany();
       temp = Read(RetData); 

   }
       Sleep(100);
   }
//----
   return(0);
  }

U mnie to śmiga bez zająknięcia ....
Najważniejsze jest tu Beep(0x300,0x20); słychać że działa ...
Uwaga!
Tylko trzeba się jescze przyjrzeć czy kolejne uruchomione wykresy nie działają
na tych samych wskażnikach - bo będzie Error na max w docelowym zastosowaniu ..
Edit:
Mi wychodzi że jest Ok . Czyli każdy wykres dostaje oddzielną bibliotekę .

0

przez chwile pochodzilo :D ale pozniej wywalilo Criticala czytalem jakies howto w sieci
i zwalnianie bylo bez [] wiec

zamiast

 if(char8UnmanArr1)
   {
       delete [] char8UnmanArr1 ;  // !!zwolnienie pamięci jeśli funkcja była już kiedyś wywołana
   }

dałem

 if(char8UnmanArr1)
   {
       delete char8UnmanArr1 ;  // !!zwolnienie pamięci jeśli funkcja była już kiedyś wywołana
   }

jednak jest problem oktorym wspomniales po slowie UAGA :)
i pewnie dlatego wywalilo Criticala

pzdr Andrzej

EDIT ale co jest wazne RAMu nie zwieksza :) problem teraz jak zrobic zeby moglo korzystac na kilku wykresach

0

A to ciekawe bo u mnie nie ma .
Musi być zwalniane przez delete [] char8UnmanArr1
przez delete char8UnmanArr1 zwolnisz chyba tylko i bajt ?

Nie ma związku z tym że biblioteka przcuje na kilku wykresach .
U mnie to chodzi bardzo dobrze , jeśli było by cos nie wporządku to by padło
na starcie . Dane nie są nadpisywane przez poszczególne skrypty MQL
czyli następuje utworzenie oddzielnych bloków dla każdej .dll
Może coś jest nie tak z tworzoną .dll w tym C# .
Może napisz ją w C/C++ ...
No bo co skoro to działa u mnie bez problemu ...

Mogę Ci podrzucić gotowego .dll z klientem który odbiera napisy wysyłane ze skryptów
i funkcją z .dll to zobaczysz .. :-/
Problem jest tylko jak Usuwam działającą strategię na kilku wykresach
przez Usuń (wywala terminal ) - ale to pewnie wina czegoś innego
Jak zakończyć bezpiecznie wykonywanie strategi uzywającej .dll ?
Chociaż sam już nie wiem , coś jest nie tak z tym usuwaniem ..

0

tego co mam w C# nie napiszem w C++ z prostej przyczyny nie znam tego jezyka :)

prawdopodobnie przyczyna jest to ze usuwasz w trakcie dzialania poniewaz pracuje w petli .

najpierw wylacz przycisk Wlacz STrategie a pozniej usun Experta

jezeli mozesz to podrzyc mi dll :)

[email protected]

pzdr Andrzej

EDIT
masz racje z [] tez dziala
nio ale ten moj kod dziala tylko na jednym wykresie :( przy kilku wywala sie terminal :(

pzdr

0

Hym jednak jest gdzieś jakaś lipa ..
No nic zaraz dołączę link tylko troche to uporządkuję , 30 min - 1h ... :|
muszę to trochę naprostować ..

0

ok :) super

jeszcze raz thx za zaangazowanie :)

pzdr A

0

W folderze Strategie jest plik z z #import:
Tu- mt4server.rar
Ps:
Marnie mi idzie na tej giełdzie ... [rotfl]
Ps:
Wywalanie jest raczej związane z fun piszącą do klienta , ta stringowa wydaje się być Ok.
Ale nie :
Tu jest lipa:

int deinit()
  {
//----
    // Dde_FreeData(); // zamknięcie połączenia - pliku << to trzeba usunąc
//----
   return(0);
  }

Znalazłem , problem jest u mnie ze zwalnianiem zasobów - Inny temat :
Wykomentuj Funkcję Dde_FreeData(); ze Skryptu i jest ok, można usuwać przy
działającej Strategii...

0

na tej dll'ce z delete wywala terminal na kilku wykresach :(

czyli to samo co u mnie :(

na tej drugiej dziala ale leci po RAMie

z innej beczki :

myslalem zeby zrobic kilka wskaznikow char* (np 10)
i zrobic kilka funkcji read

tzn w glownej Read tylko sprawdza z jakiego wykresu jest odczyt i zwraca wartosc funkcji read1......read10 w zaleznosci jaki wykres korzysysta

jednak wystapil mi taki blad :(


__declspec(dllexport) char* __stdcall Read(char* name, char* port)
{
	return read1(name,port);
}


char* read1(char* name, char* port)
{
	// NAME
   int i = 0;
   while (*name != '\0')
   {
      i++;
      name++;
   }
   array<unsigned char>^ Name = gcnew array<unsigned char>(i);
   name -= i;
   i = 0;
   while (*name != '\0')
   {
      Name[i] = *name;
      name++;
      i++;
   }
	// PORT
   int j = 0;
   while (*port != '\0')
   {
      j++;
      port++;
   }
   array<unsigned char>^ Port = gcnew array<unsigned char>(j);
   port -= j;
   j = 0;
   while (*port != '\0')
   {
      Port[j] = *port;
      port++;
      j++;
   }
   array<unsigned char>^ char8ManArr =
      Class1::Read(Name,Port);
   char*  char8UnmanArr = new char[char8ManArr->Length + 1];
   for (int i = 0; i < char8ManArr->Length; i++)
   {
      char8UnmanArr[i] = char8ManArr[i];
   }
   char8UnmanArr[char8ManArr->Length] = '\0';
   return char8UnmanArr;
}

wtedy delete bylo by tylko dla jednego wykresu
ma to swoje minusy ale moze by sie sprawdzilo :)nio ale moge sie mylic

Error 1 error C3861: 'read1': identifier not found

pzdr A

0

'read1' zamień w kodzie na 'readl' ..

Znalazłem , problem jest u mnie ze zwalnianiem zasobów - Inny temat :
Wykomentuj Funkcję Dde_FreeData(); ze Skryptu i jest ok, można usuwać przy
działającej Strategii...

myslalem zeby zrobic kilka wskaznikow char* (np 10)
i zrobic kilka funkcji read

Nie , dane nie są wspóldzielone przez wykresy bo by u mnie to nie chodziło ...
I byłoby nie logiczne - nie może tak być ze względów praktycznych , nie można by wtedy
uruchamiać Skryptów używających .dll na różnych wykresach ze względu na nadpisywanie
wzajemne danych ..

0

ale z MT4 tak wlasnie jest :).....ze jezeli jest w dllce jakas zmienna to wywloujac ja na dwóch wykresach badzie sie nadpisywac
bo nie wywoluje ja wykres tylko aplikacja MetaTradera

dlatego wywala terminal przy kilku wykresach
jeden czyta a drugi w tym samym czasie ja kasuje :D
albo ja juz sie pogubilem :D

pzdrAndrzej

0

Nie, to ja zgłupiałem ,,, muszę to jeszcze raz sprawdzić , bo właśnie zauważyłem
że jest tak jak piszesz ,tylko jak to ugryźć? , w takim razie jest duży problem ............ [???]
// Edit
I faktycznie tak ,,, jest - zmienne globalne z biblioteki są wspódzielone ...
czyli na razie nie widzę , jak zwolnić tą pamięć ..
.. hym tyle dobrego że teraz jestem pewien :-(

0

hmmmm

moze liczyc polaczenia , uzyc tablicy , i dla kazdego polaczenia uzyc innego char* ?? tylko nie wiem czy sie tak da :)

po prostu zrobic cos na zasadzie handle

pzdr A

0

dalo by sie z tego kawalka zrobic tablice dwuwymiarowa ??

 char*  char8UnmanArr = NULL;
..........

if(char8UnmanArr)
   {
       delete [] char8UnmanArr; 
}
char8UnmanArr = new char[char8ManArr->Length + 1];
   for (int i = 0; i < char8ManArr->Length; i++)
   {
      char8UnmanArr[i] = char8ManArr[i];
   }
   char8UnmanArr[char8ManArr->Length] = '\0';
   return char8UnmanArr;

wtedy bym przekazywal w zaleznosci z jakiego wykresu idzie z ktorej tablicy ma korzystac
np jezeli wykres "EURUSD" to 1 jezeli wykres GBPUSD to 2

pzdr

0

Tak, ale to kolejny stopień do problemów ..
Można w tym kodzie używać STL np. vector<char*> ze Standardowej C++?
Wygodniej od tablic ..
Może by wymysleć jakiś sposób na zarządzanie tą pamięcią , nie podoba
mi sie to ale ,, jak się nie da inaczej .. masssakra..
na razie to mam dosyć .. trochę przerwy .. spróbuję coś wymodzić . :|
Wystarczy tablica wskaźnikow np:

char*tabwsk[4] ;

i przypisujesz do kolejnych elementów zaalokowne wskaźniki ..

Ale to nie jest chyba dobre , trzeba wszystko sprawdzić jak zachowują się zmienne
przy zamknięciu poszczególnych Strategi ,
bo znowu będzie kicha jak się cos rozjedzie .

jezeli wykres GBPUSD to 2

A jak zmienisz walutę na wykresie to X - bumm ..
Czyli czeka napisanie kolejnej dll do testów ..

0

nio cza odpoczac :)

dzieki za pomoc :)

pzdr A

1 użytkowników online, w tym zalogowanych: 0, gości: 1