0

This problem also appears in normal C++ code, but it's not a problem there because in normal C++ I can use "new" instead of "malloc".

What I want to do is make a linked list of objects that have the same interface but different functions and member variables, and was hoping to do this using members of a virtual class.

But I'm getting segmentation fault. I made the following simple example code (based on this), first in Arduino C++:

class CPolygon {
  protected:
    int width, height;
  public:
    void set_values (int a, int b)
      { width=a; height=b; }
    virtual int area (void) =0;
    void printarea (void)
      { Serial.println( this->area() ); }
  };

class CRectangle: public CPolygon {
  public:
    int area (void)
      { return (width * height); }
  };


void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
}

void loop() {
  CRectangle rect;
  CPolygon * ppoly1 = ▭
  ppoly1->set_values (4,5);
  ppoly1->printarea();
  delay(1000);
}

I also made it in normal C++, hoping to find the error (it just gives me a segmentation fault):

#include <iostream>
#include <stdlib.h>
using namespace std;

class CPolygon {
  protected:
    int width, height;
  public:
    void set_values (int a, int b)
      { width=a; height=b; }
    virtual int area (void) =0;
    void printarea (void)
      { cout << this->area() << endl; }
  };

class CRectangle: public CPolygon {
  public:
    int area (void)
      { return (width * height); }
  };


int main () {
  CRectangle * rect;
  rect = (CRectangle*) malloc(sizeof(CRectangle));
  * rect = CRectangle();
  CPolygon * ppoly1 = rect;
  ppoly1->set_values (4,5);
  ppoly1->printarea();
  return 0;
}

Like I said, I tried this using new:

int main () {
  CRectangle * rect;
  rect = new CRectangle;
  CPolygon * ppoly1 = rect;
  ppoly1->set_values (4,5);
  ppoly1->printarea();
  return 0;
}

and that works fine.

I'm not really sure where to go from here in my debugging process. Am I doing something wrong, or is this an inherent limitation of malloc(), and thus of arv-g++?

  • What exactly do you mean with _'normal C++'_?? If you have a C++ compiler and you have a stdlib implementation that supports `malloc()`, `new` should work just fine in C++ code. What happens if you are using `new` with your arduino cross toolchain? – πάντα ῥεῖ Sep 12 '13 at 21:24
  • `malloc()` would never work for this BTW, because besides the memory allocation you need properly constructed (initialized) class instances. – πάντα ῥεῖ Sep 12 '13 at 21:28
  • I'm programming for the arduino, so I need to use the arv-g++ compiler. I read somewhere that the that compiler doesn't support new and delete, only malloc and the associated functions, so I never thought to try. Apparantly the arduino guys added support in their libraries, and I never thought to try... – Bart de Waal Sep 12 '13 at 22:06
  • Usually it's boiling down to provide an appropriate stdc++ library stub. GCC (which sounds to be the base for this toolchain) uses newlib and it's stdc++ library implementation on top of this. Some of the newlib stubs need to be customized for the actual OS environment. – πάντα ῥεῖ Sep 12 '13 at 22:17
  • I have been using new and delete for arduino (with the standard arduino IDE) with no problems at all. It works exactly like in visual studio, xcode, etc. – Arno Duvenhage Sep 13 '13 at 06:16
  • Be careful using complex C++ constructs on the Arduino. They can introduce unexpected memory usage and execution overhead. – Craig Sep 13 '13 at 15:24

3 Answers3

3

To use the space that you reserved with malloc, you could do the following:

new(rect) CRectangle();

instead of

* rect = CRectangle();

When I find a reference that use that syntax, I'll write it down here.

1

I agree the C++ version with new works fine. That is because new allocates the memory for the instance of the class and then calls the constructor(s). malloc does not do that it just allocates memory and so the class is never properly formed which is why the malloc version crashes. Always use new and delete for classes.

David Elliman
  • 1,379
  • 8
  • 15
0

I'm not really sure where to go from here in my debugging process. Am I doing something wrong, or is this an inherent limitation of malloc(), and thus of arv-g++?

Yes this limitation is inherent to malloc() (which is C not C++ BTW). To instantiate C++ class objects, it's necessary that one of their constructor methods is called to initialize the allocated memory properly, which malloc() doesn't serve.

I'm not experienced with arduino, but if the OS supports malloc() already for dynamic memory allocation, new should be supported as well. At least you're able to use 'placement new' syntax as Martin Lavoie proposed (see also here).

Community
  • 1
  • 1
πάντα ῥεῖ
  • 1
  • 13
  • 116
  • 190
  • new and delete are [not supported by avr-libc.](http://www.nongnu.org/avr-libc/user-manual/FAQ.html#faq_cplusplus) – Craig Sep 13 '13 at 15:18