Has anyone seen "Indicator buffer #0 detached" error?

 

 When detaching the indicator from a chart, following error message shows up in the experts tab. It is probably due to the object holding the buffer gets destroyed in the deinit(). Any idea how to suppress the error message display?

08:20:34 P35-indicator GOLD,M10: uninit reason 1
08:20:34 Indicator buffer #0 detached
08:20:34 Indicator buffer #1 detached
08:20:34 Indicator buffer #2 detached
08:20:34 Indicator buffer #3 detached
08:20:34 Custom indicator P35-indicator GOLD,M10: removed
 

Why do you think this is an error? 

In the first line it says "uninit reason 1" . Here is snippet from help:

  

REASON_REMOVE

1

Program has been deleted from the chart

 

That looks to me like regular log messages.  

Do you have source code for the indicator? 

 
drazen64:

Why do you think this is an error? 

In the first line it says "uninit reason 1" . Here is snippet from help:

  

REASON_REMOVE

1

Program has been deleted from the chart

 

That looks to me like regular log messages.  

Do you have source code for the indicator? 


Sure I have the source code, it is my source. But I cannot display entire framework, just the relevant part.

The line in the Expert log tab is marked with the exclamation mark, like errors are. No conventional indicators show it. There is no harm caused by the error message, just it may raise  "bug reports" from customers, so I would like to get rid of it by some way.

class P35Indicator : public MT4DrawingIndicator {
private:
// 4 buffers, red line, blue line, red dot, blue dot. No need to destoy buffers, the got destryed in MT4DrawingIndicator.

MT4DrawingBuffer* blueline;
MT4DrawingBuffer* redline;
MT4DrawingBuffer* bueDot;
MT4DrawingBuffer* redDot;

   
public:
   /**
    *  Constructor.
    */
   P35Indicator(MT4IndicatorScope* aScope) : MT4DrawingIndicator(aScope){
      
      blueline = addDrawingBuffer("Blue line").setType(DRAW_LINE).setColor(clrLightBlue).setStyle(STYLE_SOLID).setWidth(5);      
      redline = addDrawingBuffer("Red line").setType(DRAW_LINE).setColor(clrRed).setStyle(STYLE_SOLID).setWidth(5);      
      bueDot = addDrawingBuffer("Blue dot").setType(DRAW_LINE).setColor(clrLightBlue).setStyle(STYLE_SOLID).setWidth(5);      
      redDot = addDrawingBuffer("Red dot").setType(DRAW_LINE).setColor(clrRed).setStyle(STYLE_SOLID).setWidth(5);     
   }
.........


/**
 *  A wrapper for an indicator buffer array. Array can be accessed either directly (a member) or with accessors.
 *  Number of buffers 
 */
class MT4DrawingBuffer : public MT4Object {
protected:
   /**
    *  Buffer assignment number. The buffer number used by iCustom().
    */
   int index;
   /**
    * Chart display type.
    */
   int drawType;
   /**
    *  Name of the buffer appearing in the Data window.
    */
   string label;
public:
   /**
    *  Constructor.
    *  
    *  @param [in] aIndex Buffer assignment number. The buffer number used by iCustom().
    *  @param [in] aLabel Name of the buffer appearing in the Data window. If empty, _ValueN_ is used.
    *  @return 
    */
   MT4DrawingBuffer(int aIndex, string aLabel="") : index(aIndex), drawType(DRAW_NONE), label(aLabel){
      if(""==label) label="Value " + IntegerToString(index);
       
       SetIndexLabel(index, label);
   }
   
   /**
    *  Wrapped indicator buffer.
    */
   double value[];
   
   /**
    *  Buffer accessor.
    *  
    *  @param [in] aIndex 
    *  @param [in] aValue 
    *  @return self, to assign multiple values with a single chain.
    */
   MT4DrawingBuffer* set(int aIndex, double aValue) {
      value[aIndex]=aValue;
      return GetPointer(this);
   }
   
   /**
    *  Buffer accessor.
    *  
    *  @param [in] aIndex 
    *  @return value of the buffer
    */
   double get(int aIndex) {
      return value[aIndex];
   }
   
   /**
    *  Drawing property setter.
    */
   MT4DrawingBuffer* setType(int type) {        // line type
      drawType = type;
      SetIndexStyle(index,drawType);
      return GetPointer(this);
   }

   /**
    *  Drawing property setter.
    */
   MT4DrawingBuffer* setWidth( int width) { // line width
      SetIndexStyle(index,drawType,EMPTY,width);
      return GetPointer(this);
   }

   /**
    *  Drawing property setter.
    */
   MT4DrawingBuffer* setColor( color clr=clrNONE) {  // line color
      SetIndexStyle(index,drawType,EMPTY,EMPTY,clr);
      return GetPointer(this);
   }

   /**
    *  Drawing property setter.
    */
   MT4DrawingBuffer* setStyle( int style) { // line style
      SetIndexStyle(index,drawType,style);
      return GetPointer(this);
   }   
   
};

/**
 *  Indicator with support for drawing buffers.
 */
class MT4DrawingIndicator : public MT4Indicator {
private:
   int indicatorCountedBars;
   MT4Set* allBuffers;
protected:
   /**
    *  Working scope.
    */
   MT4Scope* scope;
public:
   /**
    *  Constructor.
    *  
    *  @param [in] aScope Definition for the indicator scope.
    */
   MT4DrawingIndicator(MT4Scope* aScope) : scope(aScope){
      allBuffers = new MT4Set(true);
      indicatorCountedBars=0;
   }
   ~MT4DrawingIndicator() {
      delete allBuffers;
   }

protected:   
   
   /**
    *  Direct replacement of the original command, intended for better use in offline charts. 
    *  Can be called only once during a tick otherwise it the next call returns bars-1.
    *  
    *  @return number of previously calculated bars minus one
    */
   int IndicatorCounted() {
      int recentBars = indicatorCountedBars;
      indicatorCountedBars = iBars(scope.getSymbol().name(), scope.getTimeframe());
      return max(recentBars-1,-1);
   }

   /**
    *  Alternative to IndicatorCounted, returning complement to bars count.
    *  Can be called only once during a tick otherwise the next call returns 1.
    *  
    *  @return number of bars that need to be recalculated.
    */
   int indicatorAdded() {
      int recentBars = indicatorCountedBars;
      indicatorCountedBars = iBars(scope.getSymbol().name(), scope.getTimeframe());
      int diff = indicatorCountedBars-recentBars;
      return min(diff + 1, indicatorCountedBars);
   }

   /**
    *  Appends correctly a drawing buffer to the indicator.
    *  
    *  @param [in] label 
    *  @return 
    */
   MT4DrawingBuffer* addDrawingBuffer(string label="") {
      MT4DrawingBuffer* buff = new MT4DrawingBuffer(bufferCount++,label);
      allBuffers.add(buff);
      IndicatorBuffers(bufferCount);
      SetIndexBuffer(bufferCount-1, buff.value);
      return buff;
   }

   /**
    * Total number of buffers in the script scope. 
    */
   static int bufferCount;
   
};
/** external declaration */
int MT4DrawingIndicator::bufferCount = 0;
 
DeepThought: When detaching the indicator from a chart, following error message shows up in the experts tab. It is probably due to the object holding the buffer gets destroyed in the deinit(). Any idea how to suppress the error message display?
class P35Indicator : public MT4DrawingIndicator {
// 4 buffers, red line, blue line, red dot, blue dot. No need to destoy buffers, the got destryed in MT4DrawingIndicator.
:
MT4DrawingBuffer* blueline;
:      
      blueline = addDrawingBuffer("Blue line").setType(DRAW_LINE).setColor(clrLightBlue).setStyle(STYLE_SOLID).setWidth(5);
Where is P35's dtor, that deletes the four lines? AddDrawingBuffer creates them with new, they're not destroyed.
 
WHRoeder:
Where is P35's dtor, that deletes the four lines? AddDrawingBuffer creates them with new, they're not destroyed.

They get destroyed in a destructor of the MT4Set. There was no memory leak anyway.

It is quite difficult to track behaviour from a small code snippet. The framework is completely different from the standard "included" support files, so do not focus on it much. I placed the snippet only to show,that the indicator buffer is wrapped in an object, while the standard construction expects the buffer array to be defined at global level. When the indicator unloads and the wrapper object gets destroyed, the buffer is released prematurely. It is not a problem, because the indicator is unloading, but the error message is annoying. 

 

Ah, I see

You create indicator buffers inside the object, and object gets destroyed in OnDeinit of an indicator thus killing buffers, while indicator probably expects them to be released after OnDeinit finishes.

You should ask Service desk to see if they expected these kind of usage. To be sure that this error will not mess something inside Metatrader. 

 
drazen64:

Ah, I see

You create indicator buffers inside the object, and object gets destroyed in OnDeinit of an indicator thus killing buffers, while indicator probably expects them to be released after OnDeinit finishes.

You should ask Service desk to see if they expected these kind of usage. To be sure that this error will not mess something inside Metatrader. 


Yes, you have the same view. I am not going to ask them, I did a few times, but they tend to fix it the other way round I would expect.
 

I think I found acceptable solution. When the declaration of the object holding the buffer wrappers is moved to the global scope then the error is suppressed. Not quite elegant, but better than a bunch of errors.

Reason: