오류, 버그, 질문 - 페이지 2471

 
Igor Makanu :

CChartObjectLabel을 생성할 때 다음 코드에서 초기화 해제 중에 표시기의 개체가 삭제되지 않는 이유를 설명합니다.

TF를 전환할 때 로그 항목이 표시됩니다. 2019.05.23 09:49:02.044 tstlabel EURUSD,M30: CChartObjectLabel 유형의 객체 2개 남음

OnInit()에서 텍스트 레이블 생성( CCartObjectLabel )의 주석을 제거하면 모든 것이 올바르게 작동합니다.

CreateLabel() 함수에 대한 포인터를 전달한 다음 어떤 이유로 OnDeinit()에서 삭제할 수 없습니다.

새로운 객체 l이 생성됩니다. 그리고 그는 제거되지 않습니다.
 
Artyom Trishkin :
새로운 객체 l이 생성됩니다. 그리고 그는 제거되지 않습니다.

논리적

그러나 변수의 범위 CChartObjectLabel *LabelUP,*LabelDN; 나는 글로벌이 있습니까?

코드의 어느 부분에서나 변수를 수정할 수 있습니까?

CreateLabel() 함수에 대한 포인터를 전달했는데 새 복사본을 만드는 이유는 무엇입니까?

IMHO, 이것은 제대로 작동하지 않습니다.

추신: OnInit()에서 개체를 만든 다음 CreateLabel()에서 작업하면(즉, 개체를 별도로 만들고 포인터로 작업) 모든 것이 올바르게 작동하지만 사례는 기억나지 않습니다. 다른 컴파일러에서는 f-tion에서 포인터를 전송하기 위해 새 개체를 만들었습니다. 포인터는 그것과 아프리카에서는 포인터입니다!

 
Igor Makanu :

논리적

하지만 내 변수의 범위 는 전역입니까? - 코드의 어느 부분에서나 변수를 수정할 수 있습니까?

CreateLabel() 함수에 대한 포인터를 전달했는데 새 복사본을 만드는 이유는 무엇입니까?

IMHO, 이것은 제대로 작동하지 않습니다.

새 객체에 대한 포인터를 재할당함으로써 재할당된 포인터가 가리키는 이전 객체를 잃게 됩니다.
 
Igor Makanu :

논리적

그러나 변수의 범위 CChartObjectLabel *LabelUP,*LabelDN; 나는 글로벌이 있습니까?

코드의 어느 부분에서나 변수를 수정할 수 있습니까?

CreateLabel() 함수에 대한 포인터를 전달했는데 새 복사본을 만드는 이유는 무엇입니까?

IMHO, 이것은 제대로 작동하지 않습니다.

새로 제거해야 합니다. 개체가 이미 있고 개체에 대한 포인터가 있습니다.
 
Artyom Trishkin :
새 객체에 대한 포인터를 재할당함으로써 재할당된 포인터가 가리키는 이전 객체를 잃게 됩니다.

아니요, 포인터는 포인터입니다. MQL에서는 디스크립터이며 요점이 아닙니다. 그러나 객체의 새 복사본을 만드는 것은 올바르지 않습니다. 이것이 현재 작동하는 방식입니다.

 //+------------------------------------------------------------------+
//|                                                         test.mq4 |
//|                        Copyright 2018, MetaQuotes Software Corp. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2018, MetaQuotes Software Corp."
#property link        "https://www.mql5.com/ru/users/igorm"
#property version    "1.00"
#property strict
#property indicator_separate_window
#include <ChartObjects\ChartObjectsTxtControls.mqh>
CChartObjectLabel *LabelUP,*LabelDN;
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit ()
  {
   LabelUP= new CChartObjectLabel;
   LabelDN= new CChartObjectLabel;
   SetLabel(LabelUP, "LabelUP" , 0 );
   SetLabel(LabelDN, "LabelDN" , 25 );
//---
   return ( INIT_SUCCEEDED );
  }
//+------------------------------------------------------------------+
//| Custom indicator deinitialization function                       |
//+------------------------------------------------------------------+
void OnDeinit ( const int reason)
  {
   delete LabelUP;
   delete LabelDN;
  }
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int OnCalculate ( const int rates_total,
                 const int prev_calculated,
                 const datetime &time[],
                 const double &open[],
                 const double &high[],
                 const double &low[],
                 const double &close[],
                 const long &tick_volume[],
                 const long &volume[],
                 const int &spread[])
  {
   return (rates_total);

  }
//+------------------------------------------------------------------+
void SetLabel(CChartObjectLabel *l, string name, int y)
  {
   l.Create( 0 ,name, ChartWindowFind (), 0 ,y);
   l.Color( clrYellow );
   l.FontSize( 14 );
   l.Description(name);
  }
//+------------------------------------------------------------------+

그러나 논리를 따르면 이 코드에서 l 개체의 복사본이 SetLabel() 함수 에서 생성됩니다. 링크가 아니라 포인터를 전달했습니다.


Artyom Trishkin :
새로 제거해야 합니다. 개체가 이미 있고 개체에 대한 포인터가 있습니다.

문제는 문제를 해결하는 방법이 아니라 변수 CChartObjectLabel *LabelUP,*LabelDN전역 범위를 사용하는 이유입니다. - 포인터를 잃어버렸습니다!

 
Igor Makanu :

아니요, 포인터는 포인터입니다. MQL에서는 디스크립터이며 요점이 아닙니다. 그러나 객체의 새 복사본을 만드는 것은 올바르지 않습니다. 이것이 현재 작동하는 방식입니다.

그러나 논리를 따르면 이 코드에서 l 개체의 복사본이 SetLabel() 함수 에서 생성됩니다. 링크가 아니라 포인터를 전달했습니다.

아니요. 여기서 l은 필요한 포인터를 전달하는 메서드의 매개변수입니다. 여기 모든 것이 좋습니다. 여기에서 포인터는 이전에 만든 개체 에 남아 있습니다. 새 개체를 만들고 이전 개체를 손실하여 해당 개체에 대한 포인터를 다시 할당하지 않습니다.
 
Artyom Trishkin :
아니요. 여기서 l은 필요한 포인터를 전달하는 메서드의 매개변수입니다. 여기 모든 것이 좋습니다. 여기에서 포인터는 이전에 만든 개체 에 남아 있습니다. 새 개체를 만들고 이전 개체를 손실하여 해당 개체에 대한 포인터를 다시 할당하지 않습니다.

여전히 제대로 작동하지 않습니다

MQL의 이러한 "포인터"는 클래스 범위에서 작동하도록 설계되었습니다. 클래스를 생성하고 싶지 않습니다. 전역 가시성에서 포인터를 가져와 선언한 다음 이를 모든 함수에 전달합니다. 이 함수는 객체 디스크립터를 생성하는데 함수의 로컬 가시성을 떠날 때 객체를 파괴할 이유가 없습니다

지금은 조금 바쁘지만 그래픽 없이 테스트 케이스를 만들어야 합니다. 동일한 문제가 발생할 것이라고 생각합니다. POINTER_INVALID 값을 가진 포인터로 함수를 입력하면 동일한 POINTER_INVALID로 종료됩니다. 예, 모든 것이 올바르게 작동하지만 참조로 POINTER_INVALID가 있는 포인터를 전달할 수 없는 것처럼 - 포인터에 액세스하는 동안 오류가 발생합니다.

 
Igor Makanu :

여전히 제대로 작동하지 않습니다

MQL의 이러한 "포인터"는 클래스 범위에서 작동하도록 설계되었습니다. 저는 클래스를 생성하고 전역 가시성에서 포인터를 드릴 및 선언한 다음 이를 모든 함수에 전달하고 싶지 않습니다. 객체 디스크립터는 함수의 로컬 가시성을 떠날 때 객체를 파괴할 이유가 없습니다

지금은 조금 바쁘지만 그래픽 없이 테스트 케이스를 만들어야 합니다. 동일한 문제가 발생할 것이라고 생각합니다. POINTER_INVALID 값을 가진 포인터로 함수를 입력하면 동일한 POINTER_INVALID로 종료됩니다. 예, 모든 것이 올바르게 작동하지만 참조로 POINTER_INVALID가 있는 포인터를 전달할 수 없는 것처럼 - 포인터에 액세스하는 동안 오류가 발생합니다.

개체만 파괴되지 않습니다. 메서드 내부에 새 개체를 만든 직후에는 이미 두 개의 개체가 있습니다. 그리고 하나의 포인터만 있습니다. 형식 매개변수 로 메서드에 전달되었습니다. 따라서 객체 중 하나에 대한 포인터를 잃게 됩니다.
 

템플릿 함수에 대한 포인터로 typedef를 선언할 수 있다는 사실에 놀랐습니다.
그러나 행복은 오래 가지 않았습니다.

 template < typename T>
typedef bool (* callback)(T &);

template < typename T>
bool ff(T &){
   return true ;
}

bool ff( int &){
   return true ;
}


void OnStart (){
   int a;
   ff(a);
   
   callback< int > f_ptr_0 = ff;     //'<' - unexpected token     
   callback f_ptr_1 = ff;           //'ff' - function must have a body   
   callback f_ptr_2 = ff< int >;     //'ff<int>' - cannot resolve function address  //'ff<int>' - type mismatch   
}


템플릿 함수에 대한 포인터가 있는 typedef는 계획된 기능입니까?

 
typedef 정원의 또 다른 버그:
 typedef void (* callback)( int &);

template < typename T>
void ff(T &){}


void OnStart (){
   int a = 0 ;
   //ff(a);                     //  если раскомментировать, то работает
   
   callback f_ptr = ff< int >;     //  'ff<int>' - function must have a body
   f_ptr(a);
}

typedef로 작업할 때 명시적 특수화와 함께 템플릿 함수를 사용하면 템플릿 함수가 생성되지 않습니다.