Skip to main content
Fixed errors in my post.
Source Link
Nick Gammon
  • 38.7k
  • 13
  • 67
  • 125
class bufr 
  {
  public:
    //constructor and deconstructor
    bufr(char* chars, uint8_t len);
    ~bufr();

    //variables
    uint8_t len_;
    char * content_;
  };    // end of class bufr

bufr::bufr(char* chars, uint8_t len) 
  {
  content_ = new char[len];
  memcpy (content_, chars, len);  // copy into allocated memory
  len_ = len;   // remember length
  }   // end of constructor

bufr::~bufr()
{
  delete [] content_;
} // end of destructor

void setup() 
{
  Serial.begin (115200);

  char chars[] = "1234 ";
  bufr buf(chars, sizeof chars);

  Serial.println (buf.content_);
} // end of setup

void loop() 
{
} // end of loop

You misinterpreted that. You either delete pointer or delete [] pointer depending on whether pointer is an array or not. I reworked content to not be an array, thus deletingthus deleting it without the brackets is correct however as it without the brackets is correctallocated using new [] it must be deleted with delete [].

delete [] foo;

You use the brackets on the delete, as you used them with the foonew is not an array so.

If you don'tallocated one char you wouldn't use the brackets. eg.

char * foo;
foo = new char;  // allocate a pointer to one byte
...
delete foo;
class bufr 
  {
  public:
    //constructor and deconstructor
    bufr(char* chars, uint8_t len);
    ~bufr();

    //variables
    uint8_t len_;
    char * content_;
  };    // end of class bufr

bufr::bufr(char* chars, uint8_t len) 
  {
  content_ = new char[len];
  memcpy (content_, chars, len);  // copy into allocated memory
  len_ = len;   // remember length
  }   // end of constructor

bufr::~bufr()
{
  delete content_;
} // end of destructor

void setup() 
{
  Serial.begin (115200);

  char chars[] = "1234 ";
  bufr buf(chars, sizeof chars);

  Serial.println (buf.content_);
} // end of setup

void loop() 
{
} // end of loop

You misinterpreted that. You either delete pointer or delete [] pointer depending on whether pointer is an array or not. I reworked content to not be an array, thus deleting it without the brackets is correct.

delete foo;

foo is not an array so you don't use the brackets.

class bufr 
  {
  public:
    //constructor and deconstructor
    bufr(char* chars, uint8_t len);
    ~bufr();

    //variables
    uint8_t len_;
    char * content_;
  };    // end of class bufr

bufr::bufr(char* chars, uint8_t len) 
  {
  content_ = new char[len];
  memcpy (content_, chars, len);  // copy into allocated memory
  len_ = len;   // remember length
  }   // end of constructor

bufr::~bufr()
{
  delete [] content_;
} // end of destructor

void setup() 
{
  Serial.begin (115200);

  char chars[] = "1234 ";
  bufr buf(chars, sizeof chars);

  Serial.println (buf.content_);
} // end of setup

void loop() 
{
} // end of loop

You misinterpreted that. You either delete pointer or delete [] pointer depending on whether pointer is an array or not. I reworked content to not be an array, thus deleting it without the brackets is correct however as it is allocated using new [] it must be deleted with delete [].

delete [] foo;

You use the brackets on the delete, as you used them with the new.

If you allocated one char you wouldn't use brackets. eg.

char * foo;
foo = new char;  // allocate a pointer to one byte
...
delete foo;
Added more explanations.
Source Link
Nick Gammon
  • 38.7k
  • 13
  • 67
  • 125

ThatThat gives you a pointer to an array of zero length.

This gives you a pointer to an array of char, of zero length. This is not useful.

class bufr 
  {
  public:
    //constructor and deconstructor
    bufr(char* chars, uint8_t len);
    ~bufr();

    //variables
    uint8_t len_;
    char * content_;
  };    // end of class bufr

bufr::bufr(char* chars, uint8_t len) 
  {
  content_ = new char[len];
  memcpy (content_, chars, len);  // copy into allocated memory
  len_ = len;   // remember length
  }   // end of constructor

bufr::~bufr()
{
  delete content_;
} // end of destructor

void setup() 
{
  Serial.begin (115200);

  char chars[] = "1234 ";
  bufr buf(chars, sizeof chars);

  Serial.println (buf.content_);
} // end of setup

void loop() 
{
} // end of loop

Can you explain to me why it was making a new variable content and not using the class variable?

Small example:

char * content;

void loop ()
  {
  char * content = "foo";  // makes a NEW variable
  }

In this example there are two variables named content. The one in the function "shadows" the global one. However the code below only has one variable:

char * content;

void loop ()
  {
  content = "foo";  // uses existing variable
  }

In the destructor, when you delete the pointer to the array, does this free up the memory allocated to the array? It's now free to be assigned again by something else? Or does it sit there still initialized as that array, not being able to be used again?

You aren't deleting the pointer. You are deleting the memory it points to. The pointer is now pointing to freed memory, so using it as a pointer at this stage would be wrong. You can do another new to make it point to something else.


they delete pointer and then delete[] pointer.

You misinterpreted that. You either delete pointer or delete [] pointer depending on whether pointer is an array or not. I reworked content to not be an array, thus deleting it without the brackets is correct.


on the link posted above they say to use delete this way: delete pointer if it was a single element allocated with new or delete [] pointer to release memory allocation for arrays of elements allocated with new and a size in []'s. So in my case I want to use delete [] content_?

No, you don't want to be setting up an array in the first place. Take a look at this small example:

struct   {
  char bar [];
  } foo;

void setup() 
{
Serial.begin (115200);
Serial.println ("Starting");
Serial.println (sizeof (foo));
Serial.println (sizeof (foo.bar));
}

void loop() 
{
}

That prints:

Starting
0
0

The variable bar is a zero-length array. Thus the entire struct foo is also zero length. It isn't even a pointer (that would be two bytes on this platform).

It is wrong to use an array of char like that, when you want to dynamically allocate memory. Look at this:

char foo [4];

That allocates 4 bytes of memory for foo. You can't later on make it longer by doing a new.

What you want is:

char * foo;

Now you have allocated a pointer and can do a new, like this:

foo = new char [10];  // allocate 10 bytes

And then delete it:

delete foo;

foo is not an array so you don't use the brackets.

That gives you a pointer to an array of zero length.

class bufr 
  {
  public:
    //constructor and deconstructor
    bufr(char* chars, uint8_t len);
    ~bufr();

    //variables
    uint8_t len_;
    char * content_;
  };    // end of class bufr

bufr::bufr(char* chars, uint8_t len) 
  {
  content_ = new char[len];
  memcpy (content_, chars, len);  // copy into allocated memory
  len_ = len;   // remember length
  }   // end of constructor

bufr::~bufr()
{
  delete content_;
} // end of destructor

void setup() 
{
  Serial.begin (115200);

  char chars[] = "1234 ";
  bufr buf(chars, sizeof chars);

  Serial.println (buf.content_);
} // end of setup

void loop() 
{
} // end of loop

That gives you a pointer to an array of zero length.

This gives you an array of char, of zero length. This is not useful.

class bufr 
  {
  public:
    //constructor and deconstructor
    bufr(char* chars, uint8_t len);
    ~bufr();

    //variables
    uint8_t len_;
    char * content_;
  };    // end of class bufr

bufr::bufr(char* chars, uint8_t len) 
  {
  content_ = new char[len];
  memcpy (content_, chars, len);  // copy into allocated memory
  len_ = len;   // remember length
  }   // end of constructor

bufr::~bufr()
{
  delete content_;
} // end of destructor

void setup() 
{
  Serial.begin (115200);

  char chars[] = "1234 ";
  bufr buf(chars, sizeof chars);

  Serial.println (buf.content_);
} // end of setup

void loop() 
{
} // end of loop

Can you explain to me why it was making a new variable content and not using the class variable?

Small example:

char * content;

void loop ()
  {
  char * content = "foo";  // makes a NEW variable
  }

In this example there are two variables named content. The one in the function "shadows" the global one. However the code below only has one variable:

char * content;

void loop ()
  {
  content = "foo";  // uses existing variable
  }

In the destructor, when you delete the pointer to the array, does this free up the memory allocated to the array? It's now free to be assigned again by something else? Or does it sit there still initialized as that array, not being able to be used again?

You aren't deleting the pointer. You are deleting the memory it points to. The pointer is now pointing to freed memory, so using it as a pointer at this stage would be wrong. You can do another new to make it point to something else.


they delete pointer and then delete[] pointer.

You misinterpreted that. You either delete pointer or delete [] pointer depending on whether pointer is an array or not. I reworked content to not be an array, thus deleting it without the brackets is correct.


on the link posted above they say to use delete this way: delete pointer if it was a single element allocated with new or delete [] pointer to release memory allocation for arrays of elements allocated with new and a size in []'s. So in my case I want to use delete [] content_?

No, you don't want to be setting up an array in the first place. Take a look at this small example:

struct   {
  char bar [];
  } foo;

void setup() 
{
Serial.begin (115200);
Serial.println ("Starting");
Serial.println (sizeof (foo));
Serial.println (sizeof (foo.bar));
}

void loop() 
{
}

That prints:

Starting
0
0

The variable bar is a zero-length array. Thus the entire struct foo is also zero length. It isn't even a pointer (that would be two bytes on this platform).

It is wrong to use an array of char like that, when you want to dynamically allocate memory. Look at this:

char foo [4];

That allocates 4 bytes of memory for foo. You can't later on make it longer by doing a new.

What you want is:

char * foo;

Now you have allocated a pointer and can do a new, like this:

foo = new char [10];  // allocate 10 bytes

And then delete it:

delete foo;

foo is not an array so you don't use the brackets.

Source Link
Nick Gammon
  • 38.7k
  • 13
  • 67
  • 125

This is wrong on a number of levels. First in the class declaration:

char content[];

That gives you a pointer to an array of zero length.

char* content = new char[_len];
content = _chars;

That does a new into a new variable content - not the class variable. Then you assign (overwrite) the passed pointer into content (discarding the memory you just allocated). That pointer is then discarded when the constructor ends. Perhaps using strcpy would be better.

I made up a small example based on your code which prints the correct result:

class bufr 
  {
  public:
    //constructor and deconstructor
    bufr(char* chars, uint8_t len);
    ~bufr();

    //variables
    uint8_t len_;
    char * content_;
  };    // end of class bufr

bufr::bufr(char* chars, uint8_t len) 
  {
  content_ = new char[len];
  memcpy (content_, chars, len);  // copy into allocated memory
  len_ = len;   // remember length
  }   // end of constructor

bufr::~bufr()
{
  delete content_;
} // end of destructor

void setup() 
{
  Serial.begin (115200);

  char chars[] = "1234 ";
  bufr buf(chars, sizeof chars);

  Serial.println (buf.content_);
} // end of setup

void loop() 
{
} // end of loop