Developers Archive

List Statistics

  • Total Threads: 675
  • Total Posts: 2049
  #1  
03-01-2011 09:44 PM
Developers member admin is online now
User
 

That breaking of String, does it only occur with the SDM version?

If not, did you find any way to break it? Maybe any of the old faults
related to memory?


I actually have no time to check this myself right now, so I opted to just
ask you.

On Mon, Jan 3, 2011 at 10:35 PM, Tom Igoe <> wrote:

> Thanks, Alexander, and sorry for the delay.
>
> A few tests:
>
> For code that doesn't change the strings much, there's not a big
> difference, a couple dozen bytes' difference in code size. However, when
> you start to do dynamic things, it does add up. For example, the
> StringAppendOperator example is 4910 bytes in 0022, and 5148 bytes with the
> StaticDynamicMemory version. So it does start to take its toll, memory-wise.
>
> On some sketches it actually takes less memory. For example, the one below
> is 3738 bytes using the StaticDynamicMemory version, and 3986 bytes in 0022.
> However, it fails entirely on upload. When the value of (analog 0)/4 is
> high (0xFF), it never gets out of the setup(). So there's still a pretty
> easy way to break String, even with these improvements.
>
>
> void setup() {
> Serial.begin(9600);
> Serial.println("Beginning");
> }
>
> void loop() {
>
> String webColor = "#";
>
> int red = analogRead(A0)/4;
> webColor += String(red, HEX);
> int green = analogRead(A1)/4;
> webColor += String(green, HEX);
> int blue = analogRead(A2)/4;
>
> webColor += String(blue, HEX);
> Serial.println(webColor);
> }
>
>
>
>
>
> On Dec 16, 2010, at 1:27 AM, Alexander Brevig wrote:
>
> > Attached is a zip containing WString.h and .cpp plus
> StaticDynamicMemory.h.
> > Take a backup of the original WString files, and extract this zip into
> the hardware/arduino/cores/arduino folder.
> >
> > Now you're ready to test the modified String library, that does not
> fragment the heap.
> >
> >
> > In the WString header there is a #define called STRING_BUFFER which is
> set to 100 for now, change this to suit your test needs.
> >
> >
> > No error handling is implemented, what do you think we need?
> >
> > I plan to add an availableMemory():int method to the SDM library, and
> maybe some error flags and checks like hasError():int error
> >
> > I also suspect that this library is a bit slower performance wise, but I
> think that's just a cost we'll have to pay to being able to play with
> dynamic strings.
> >
> >
> > Hope to get feedback from someone!
> >
> > On Thu, Dec 16, 2010 at 1:11 AM, Alan Burlison <>
> wrote:
> > On 15/12/2010 16:19, David A. Mellis wrote:
> >
> > I think you're right, but I also don't think that telling people to
> > use the standard C library functions is a solution either. Trying out
> > this String class seems like one way of pushing forwards towards a
> > compromise that provides both an easy-to-use API and a robust
> > implementation. For example, perhaps the buffer sizes need to be
> > specified or provided when the String is instantiated. Or we need an
> > alternative implementation that does more reliable memory allocation
> > (since we're not assuming that the internal buffer is continuous).
> > Other ideas welcome.
> >
> > I think the problem is that the failure modes are not benign. I haven't
> been through all the use cases so this might not work, but perhaps using a
> statically-allocated string ("NOMEM" ?) as a sentinel value instead of null
> when malloc fails might be one way? Also, there might be some benefit in
> making String immutable a la Java - overloaded operators in C++ have a
> tendency to generate anonymous temporaries, which is going to lead to heap
> fragmentation as well.
> >
> > --
> > Alan Burlison
> > --
> >
> > _______________________________________________
___________________________________________________

Posted on the Developers mailing list. Go to http://arduino.cc/mailman/listinfo/developers_arduino.cc to subscribe.

  #2  
04-01-2011 02:35 AM
Developers member admin is online now
User
 

That breaking of String, does it only occur with the SDM version?

If not, did you find any way to break it? Maybe any of the old faults
related to memory?


I actually have no time to check this myself right now, so I opted to just
ask you.

On Mon, Jan 3, 2011 at 10:35 PM, Tom Igoe <> wrote:

> Thanks, Alexander, and sorry for the delay.
>
> A few tests:
>
> For code that doesn't change the strings much, there's not a big
> difference, a couple dozen bytes' difference in code size. However, when
> you start to do dynamic things, it does add up. For example, the
> StringAppendOperator example is 4910 bytes in 0022, and 5148 bytes with the
> StaticDynamicMemory version. So it does start to take its toll, memory-wise.
>
> On some sketches it actually takes less memory. For example, the one below
> is 3738 bytes using the StaticDynamicMemory version, and 3986 bytes in 0022.
> However, it fails entirely on upload. When the value of (analog 0)/4 is
> high (0xFF), it never gets out of the setup(). So there's still a pretty
> easy way to break String, even with these improvements.
>
>
> void setup() {
> Serial.begin(9600);
> Serial.println("Beginning");
> }
>
> void loop() {
>
> String webColor = "#";
>
> int red = analogRead(A0)/4;
> webColor += String(red, HEX);
> int green = analogRead(A1)/4;
> webColor += String(green, HEX);
> int blue = analogRead(A2)/4;
>
> webColor += String(blue, HEX);
> Serial.println(webColor);
> }
>
>
>
>
>
> On Dec 16, 2010, at 1:27 AM, Alexander Brevig wrote:
>
> > Attached is a zip containing WString.h and .cpp plus
> StaticDynamicMemory.h.
> > Take a backup of the original WString files, and extract this zip into
> the hardware/arduino/cores/arduino folder.
> >
> > Now you're ready to test the modified String library, that does not
> fragment the heap.
> >
> >
> > In the WString header there is a #define called STRING_BUFFER which is
> set to 100 for now, change this to suit your test needs.
> >
> >
> > No error handling is implemented, what do you think we need?
> >
> > I plan to add an availableMemory():int method to the SDM library, and
> maybe some error flags and checks like hasError():int error
> >
> > I also suspect that this library is a bit slower performance wise, but I
> think that's just a cost we'll have to pay to being able to play with
> dynamic strings.
> >
> >
> > Hope to get feedback from someone!
> >
> > On Thu, Dec 16, 2010 at 1:11 AM, Alan Burlison <>
> wrote:
> > On 15/12/2010 16:19, David A. Mellis wrote:
> >
> > I think you're right, but I also don't think that telling people to
> > use the standard C library functions is a solution either. Trying out
> > this String class seems like one way of pushing forwards towards a
> > compromise that provides both an easy-to-use API and a robust
> > implementation. For example, perhaps the buffer sizes need to be
> > specified or provided when the String is instantiated. Or we need an
> > alternative implementation that does more reliable memory allocation
> > (since we're not assuming that the internal buffer is continuous).
> > Other ideas welcome.
> >
> > I think the problem is that the failure modes are not benign. I haven't
> been through all the use cases so this might not work, but perhaps using a
> statically-allocated string ("NOMEM" ?) as a sentinel value instead of null
> when malloc fails might be one way? Also, there might be some benefit in
> making String immutable a la Java - overloaded operators in C++ have a
> tendency to generate anonymous temporaries, which is going to lead to heap
> fragmentation as well.
> >
> > --
> > Alan Burlison
> > --
> >
> > _______________________________________________
___________________________________________________

Posted on the Developers mailing list. Go to http://arduino.cc/mailman/listinfo/developers_arduino.cc to subscribe. It broke in the non-SDM version too, but it took longer to break. In the SDM version it breaks immediately. So it looks like whatever you did highlights the faults sooner, which is good. It also points to a need for an error response of some sort, in answer to your question last mail.

t.

On Jan 3, 2011, at 4:44 PM, Alexander Brevig wrote:

> That breaking of String, does it only occur with the SDM version?
>
> If not, did you find any way to break it? Maybe any of the old faults related to memory?
>
>
> I actually have no time to check this myself right now, so I opted to just ask you.
>
> On Mon, Jan 3, 2011 at 10:35 PM, Tom Igoe <> wrote:
> Thanks, Alexander, and sorry for the delay.
>
> A few tests:
>
> For code that doesn't change the strings much, there's not a big difference, a couple dozen bytes' difference in code size. However, when you start to do dynamic things, it does add up. For example, the StringAppendOperator example is 4910 bytes in 0022, and 5148 bytes with the StaticDynamicMemory version. So it does start to take its toll, memory-wise.
>
> On some sketches it actually takes less memory. For example, the one below is 3738 bytes using the StaticDynamicMemory version, and 3986 bytes in 0022. However, it fails entirely on upload. When the value of (analog 0)/4 is high (0xFF), it never gets out of the setup(). So there's still a pretty easy way to break String, even with these improvements.
>
>
> void setup() {
> Serial.begin(9600);
> Serial.println("Beginning");
> }
>
> void loop() {
>
> String webColor = "#";
>
> int red = analogRead(A0)/4;
> webColor += String(red, HEX);
> int green = analogRead(A1)/4;
> webColor += String(green, HEX);
> int blue = analogRead(A2)/4;
>
> webColor += String(blue, HEX);
> Serial.println(webColor);
> }
>
>
>
>
>
> On Dec 16, 2010, at 1:27 AM, Alexander Brevig wrote:
>
> > Attached is a zip containing WString.h and .cpp plus StaticDynamicMemory.h.
> > Take a backup of the original WString files, and extract this zip into the hardware/arduino/cores/arduino folder.
> >
> > Now you're ready to test the modified String library, that does not fragment the heap.
> >
> >
> > In the WString header there is a #define called STRING_BUFFER which is set to 100 for now, change this to suit your test needs.
> >
> >
> > No error handling is implemented, what do you think we need?
> >
> > I plan to add an availableMemory():int method to the SDM library, and maybe some error flags and checks like hasError():int error
> >
> > I also suspect that this library is a bit slower performance wise, but I think that's just a cost we'll have to pay to being able to play with dynamic strings.
> >
> >
> > Hope to get feedback from someone!
> >
> > On Thu, Dec 16, 2010 at 1:11 AM, Alan Burlison <> wrote:
> > On 15/12/2010 16:19, David A. Mellis wrote:
> >
> > I think you're right, but I also don't think that telling people to
> > use the standard C library functions is a solution either. Trying out
> > this String class seems like one way of pushing forwards towards a
> > compromise that provides both an easy-to-use API and a robust
> > implementation. For example, perhaps the buffer sizes need to be
> > specified or provided when the String is instantiated. Or we need an
> > alternative implementation that does more reliable memory allocation
> > (since we're not assuming that the internal buffer is continuous).
> > Other ideas welcome.
> >
> > I think the problem is that the failure modes are not benign. I haven't been through all the use cases so this might not work, but perhaps using a statically-allocated string ("NOMEM" ?) as a sentinel value instead of null when malloc fails might be one way? Also, there might be some benefit in making String immutable a la Java - overloaded operators in C++ have a tendency to generate anonymous temporaries, which is going to lead to heap fragmentation as well.
> >
> > --
> > Alan Burlison
> > --
> >
> > _______________________________________________
___________________________________________________

Posted on the Developers mailing list. Go to http://arduino.cc/mailman/listinfo/developers_arduino.cc to subscribe.

  #3  
04-01-2011 06:29 PM
Developers member admin is online now
User
 

That breaking of String, does it only occur with the SDM version?

If not, did you find any way to break it? Maybe any of the old faults
related to memory?


I actually have no time to check this myself right now, so I opted to just
ask you.

On Mon, Jan 3, 2011 at 10:35 PM, Tom Igoe <> wrote:

> Thanks, Alexander, and sorry for the delay.
>
> A few tests:
>
> For code that doesn't change the strings much, there's not a big
> difference, a couple dozen bytes' difference in code size. However, when
> you start to do dynamic things, it does add up. For example, the
> StringAppendOperator example is 4910 bytes in 0022, and 5148 bytes with the
> StaticDynamicMemory version. So it does start to take its toll, memory-wise.
>
> On some sketches it actually takes less memory. For example, the one below
> is 3738 bytes using the StaticDynamicMemory version, and 3986 bytes in 0022.
> However, it fails entirely on upload. When the value of (analog 0)/4 is
> high (0xFF), it never gets out of the setup(). So there's still a pretty
> easy way to break String, even with these improvements.
>
>
> void setup() {
> Serial.begin(9600);
> Serial.println("Beginning");
> }
>
> void loop() {
>
> String webColor = "#";
>
> int red = analogRead(A0)/4;
> webColor += String(red, HEX);
> int green = analogRead(A1)/4;
> webColor += String(green, HEX);
> int blue = analogRead(A2)/4;
>
> webColor += String(blue, HEX);
> Serial.println(webColor);
> }
>
>
>
>
>
> On Dec 16, 2010, at 1:27 AM, Alexander Brevig wrote:
>
> > Attached is a zip containing WString.h and .cpp plus
> StaticDynamicMemory.h.
> > Take a backup of the original WString files, and extract this zip into
> the hardware/arduino/cores/arduino folder.
> >
> > Now you're ready to test the modified String library, that does not
> fragment the heap.
> >
> >
> > In the WString header there is a #define called STRING_BUFFER which is
> set to 100 for now, change this to suit your test needs.
> >
> >
> > No error handling is implemented, what do you think we need?
> >
> > I plan to add an availableMemory():int method to the SDM library, and
> maybe some error flags and checks like hasError():int error
> >
> > I also suspect that this library is a bit slower performance wise, but I
> think that's just a cost we'll have to pay to being able to play with
> dynamic strings.
> >
> >
> > Hope to get feedback from someone!
> >
> > On Thu, Dec 16, 2010 at 1:11 AM, Alan Burlison <>
> wrote:
> > On 15/12/2010 16:19, David A. Mellis wrote:
> >
> > I think you're right, but I also don't think that telling people to
> > use the standard C library functions is a solution either. Trying out
> > this String class seems like one way of pushing forwards towards a
> > compromise that provides both an easy-to-use API and a robust
> > implementation. For example, perhaps the buffer sizes need to be
> > specified or provided when the String is instantiated. Or we need an
> > alternative implementation that does more reliable memory allocation
> > (since we're not assuming that the internal buffer is continuous).
> > Other ideas welcome.
> >
> > I think the problem is that the failure modes are not benign. I haven't
> been through all the use cases so this might not work, but perhaps using a
> statically-allocated string ("NOMEM" ?) as a sentinel value instead of null
> when malloc fails might be one way? Also, there might be some benefit in
> making String immutable a la Java - overloaded operators in C++ have a
> tendency to generate anonymous temporaries, which is going to lead to heap
> fragmentation as well.
> >
> > --
> > Alan Burlison
> > --
> >
> > _______________________________________________
___________________________________________________

Posted on the Developers mailing list. Go to http://arduino.cc/mailman/listinfo/developers_arduino.cc to subscribe. It broke in the non-SDM version too, but it took longer to break. In the SDM version it breaks immediately. So it looks like whatever you did highlights the faults sooner, which is good. It also points to a need for an error response of some sort, in answer to your question last mail.

t.

On Jan 3, 2011, at 4:44 PM, Alexander Brevig wrote:

> That breaking of String, does it only occur with the SDM version?
>
> If not, did you find any way to break it? Maybe any of the old faults related to memory?
>
>
> I actually have no time to check this myself right now, so I opted to just ask you.
>
> On Mon, Jan 3, 2011 at 10:35 PM, Tom Igoe <> wrote:
> Thanks, Alexander, and sorry for the delay.
>
> A few tests:
>
> For code that doesn't change the strings much, there's not a big difference, a couple dozen bytes' difference in code size. However, when you start to do dynamic things, it does add up. For example, the StringAppendOperator example is 4910 bytes in 0022, and 5148 bytes with the StaticDynamicMemory version. So it does start to take its toll, memory-wise.
>
> On some sketches it actually takes less memory. For example, the one below is 3738 bytes using the StaticDynamicMemory version, and 3986 bytes in 0022. However, it fails entirely on upload. When the value of (analog 0)/4 is high (0xFF), it never gets out of the setup(). So there's still a pretty easy way to break String, even with these improvements.
>
>
> void setup() {
> Serial.begin(9600);
> Serial.println("Beginning");
> }
>
> void loop() {
>
> String webColor = "#";
>
> int red = analogRead(A0)/4;
> webColor += String(red, HEX);
> int green = analogRead(A1)/4;
> webColor += String(green, HEX);
> int blue = analogRead(A2)/4;
>
> webColor += String(blue, HEX);
> Serial.println(webColor);
> }
>
>
>
>
>
> On Dec 16, 2010, at 1:27 AM, Alexander Brevig wrote:
>
> > Attached is a zip containing WString.h and .cpp plus StaticDynamicMemory.h.
> > Take a backup of the original WString files, and extract this zip into the hardware/arduino/cores/arduino folder.
> >
> > Now you're ready to test the modified String library, that does not fragment the heap.
> >
> >
> > In the WString header there is a #define called STRING_BUFFER which is set to 100 for now, change this to suit your test needs.
> >
> >
> > No error handling is implemented, what do you think we need?
> >
> > I plan to add an availableMemory():int method to the SDM library, and maybe some error flags and checks like hasError():int error
> >
> > I also suspect that this library is a bit slower performance wise, but I think that's just a cost we'll have to pay to being able to play with dynamic strings.
> >
> >
> > Hope to get feedback from someone!
> >
> > On Thu, Dec 16, 2010 at 1:11 AM, Alan Burlison <> wrote:
> > On 15/12/2010 16:19, David A. Mellis wrote:
> >
> > I think you're right, but I also don't think that telling people to
> > use the standard C library functions is a solution either. Trying out
> > this String class seems like one way of pushing forwards towards a
> > compromise that provides both an easy-to-use API and a robust
> > implementation. For example, perhaps the buffer sizes need to be
> > specified or provided when the String is instantiated. Or we need an
> > alternative implementation that does more reliable memory allocation
> > (since we're not assuming that the internal buffer is continuous).
> > Other ideas welcome.
> >
> > I think the problem is that the failure modes are not benign. I haven't been through all the use cases so this might not work, but perhaps using a statically-allocated string ("NOMEM" ?) as a sentinel value instead of null when malloc fails might be one way? Also, there might be some benefit in making String immutable a la Java - overloaded operators in C++ have a tendency to generate anonymous temporaries, which is going to lead to heap fragmentation as well.
> >
> > --
> > Alan Burlison
> > --
> >
> > _______________________________________________
___________________________________________________

Posted on the Developers mailing list. Go to http://arduino.cc/mailman/listinfo/developers_arduino.cc to subscribe. There seems to be a bug with the assignment operator, I'm on it and I'll get
back to you as soon as I get something done.

Thank you for your tests and feedback.


I'll do some tests on my own before I repost it here.

On Tue, Jan 4, 2011 at 6:53 PM, Rick Anderson
<>wrote:

> I just created a test and unpacked and tested it. I also created a
> test based on Tom's code. Not sure I caught the maximum value error
> for 0xFF.
>
> I also ran the tests for bug 411. All the tests compile, but there is
> still memory loss.
>
> I'm attaching the Arduino Test suite, and the test code so you can run
> them as you debug. Let me know if this was helpful.
>
> --Rick
>
> Test run results:
> Example: ATS_StringAssignmentTest.pde
> info.MANUFACTURER = Arduino
> info.CPU-NAME = ATmega328P
> info.GCC-Version = 4.3.2
> info.AVR-LibC-Ver = 1.6.4
> info.Compiled-date = Jan 4 2011
> info.Test-Suite-Name = ATS_StringAssignmentTest
> info.Free-memory = 1110 bytes
> Memory Usage (lost 59 bytes) ... FAIL
> --------------------------
> Ran 1 tests in 1.378s
>
> FAILED (failures=1)
>
>
> Example: ATS_StringMemoryTestPassByReference.pde
>
> info.MANUFACTURER = Arduino
> info.CPU-NAME = ATmega328P
> info.GCC-Version = 4.3.2
> info.AVR-LibC-Ver = 1.6.4
> info.Compiled-date = Jan 4 2011
> info.Test-Suite-Name = ATS_StringMemoryTestPassByReference
> info.Free-memory = 1120 bytes
> Memory Usage (lost 59 bytes) ... FAIL
> --------------------------
> Ran 1 tests in 1.389s
>
> FAILED (failures=1)
>
>
> Example: Tom Igoe Memory Test
> info.MANUFACTURER = Arduino
> info.CPU-NAME = ATmega328P
> info.GCC-Version = 4.3.2
> info.AVR-LibC-Ver = 1.6.4
> info.Compiled-date = Jan 4 2011
> info.Test-Suite-Name = Tom Igoe Memory Test
> info.Free-memory = 1328 bytes
> Memory Usage (lost 9 bytes) ... FAIL
> --------------------------
> Ran 1 tests in 1.374s
>
> FAILED (failures=1)
>
>
>
> --Rick
>
> Tom, rewrote your example as a test.
>
> //************************************************************************
> //* Arduino Tom Igoe Memory Test
> //* (C) 2010 by Rick Anderson
> //* Open source as per standard Arduino code
> //*
> //************************************************************************
> //* Jan 4, 2011 Started on Tom Igoe Memory Test
> //************************************************************************
>
> #include "WProgram.h"
> #include "HardwareSerial.h"
> #include
>
> //************************************************************************
> void setup()
> {
> int startMemoryUsage;
> /*
> * Create variable for the tests.
> */
>
> String webColor = "#000000";
>
> int red = 1023/4;
> int blue = 512/4;
> int green = 128/4;
>
> /*
> * initiate the test run
> */
> //Record starting memory amount
> startMemoryUsage = ATS_GetFreeMemory();
> //Begin test run
> ATS_begin("Arduino", "Tom Igoe Memory Test");
>
> webColor = "#";
> webColor += String(red, HEX);
> webColor += String(green, HEX);
> webColor += String(blue, HEX);
>
> ATS_ReportMemoryUsage(startMemoryUsage);
>
> /*
> * Test complete
> */
>
> ATS_end();
> }
>
>
> //************************************************************************
> void loop()
> {
>
>
> }
>
>
>
>
> On Mon, Jan 3, 2011 at 9:35 PM, Tom Igoe <> wrote:
> > It broke in the non-SDM version too, but it took longer to break. In the
> SDM version it breaks immediately. So it looks like whatever you did
> highlights the faults sooner, which is good. It also points to a need for an
> error response of some sort, in answer to your question last mail.
> >
> > t.
> >
> > On Jan 3, 2011, at 4:44 PM, Alexander Brevig wrote:
> >
> >> That breaking of String, does it only occur with the SDM version?
> >>
> >> If not, did you find any way to break it? Maybe any of the old faults
> related to memory?
> >>
> >>
> >> I actually have no time to check this myself right now, so I opted to
> just ask you.
> >>
> >> On Mon, Jan 3, 2011 at 10:35 PM, Tom Igoe <> wrote:
> >> Thanks, Alexander, and sorry for the delay.
> >>
> >> A few tests:
> >>
> >> For code that doesn't change the strings much, there's not a big
> difference, a couple dozen bytes' difference in code size. However, when
> you start to do dynamic things, it does add up. For example, the
> StringAppendOperator example is 4910 bytes in 0022, and 5148 bytes with the
> StaticDynamicMemory version. So it does start to take its toll, memory-wise.
> >>
> >> On some sketches it actually takes less memory. For example, the one
> below is 3738 bytes using the StaticDynamicMemory version, and 3986 bytes in
> 0022. However, it fails entirely on upload. When the value of (analog 0)/4
> is high (0xFF), it never gets out of the setup(). So there's still a pretty
> easy way to break String, even with these improvements.
> >>
> >>
> >> void setup() {
> >> Serial.begin(9600);
> >> Serial.println("Beginning");
> >> }
> >>
> >> void loop() {
> >>
> >> String webColor = "#";
> >>
> >> int red = analogRead(A0)/4;
> >> webColor += String(red, HEX);
> >> int green = analogRead(A1)/4;
> >> webColor += String(green, HEX);
> >> int blue = analogRead(A2)/4;
> >>
> >> webColor += String(blue, HEX);
> >> Serial.println(webColor);
> >> }
> >>
> >>
> >>
> >>
> >>
> >> On Dec 16, 2010, at 1:27 AM, Alexander Brevig wrote:
> >>
> >> > Attached is a zip containing WString.h and .cpp plus
> StaticDynamicMemory.h.
> >> > Take a backup of the original WString files, and extract this zip into
> the hardware/arduino/cores/arduino folder.
> >> >
> >> > Now you're ready to test the modified String library, that does not
> fragment the heap.
> >> >
> >> >
> >> > In the WString header there is a #define called STRING_BUFFER which is
> set to 100 for now, change this to suit your test needs.
> >> >
> >> >
> >> > No error handling is implemented, what do you think we need?
> >> >
> >> > I plan to add an availableMemory():int method to the SDM library, and
> maybe some error flags and checks like hasError():int error
> >> >
> >> > I also suspect that this library is a bit slower performance wise, but
> I think that's just a cost we'll have to pay to being able to play with
> dynamic strings.
> >> >
> >> >
> >> > Hope to get feedback from someone!
> >> >
> >> > On Thu, Dec 16, 2010 at 1:11 AM, Alan Burlison <
> > wrote:
> >> > On 15/12/2010 16:19, David A. Mellis wrote:
> >> >
> >> > I think you're right, but I also don't think that telling people to
> >> > use the standard C library functions is a solution either. Trying out
> >> > this String class seems like one way of pushing forwards towards a
> >> > compromise that provides both an easy-to-use API and a robust
> >> > implementation. For example, perhaps the buffer sizes need to be
> >> > specified or provided when the String is instantiated. Or we need an
> >> > alternative implementation that does more reliable memory allocation
> >> > (since we're not assuming that the internal buffer is continuous).
> >> > Other ideas welcome.
> >> >
> >> > I think the problem is that the failure modes are not benign. I
> haven't been through all the use cases so this might not work, but perhaps
> using a statically-allocated string ("NOMEM" ?) as a sentinel value instead
> of null when malloc fails might be one way? Also, there might be some
> benefit in making String immutable a la Java - overloaded operators in C++
> have a tendency to generate anonymous temporaries, which is going to lead to
> heap fragmentation as well.
> >> >
> >> > --
> >> > Alan Burlison
> >> > --
> >> >
> >> > _______________________________________________
___________________________________________________

Posted on the Developers mailing list. Go to http://arduino.cc/mailman/listinfo/developers_arduino.cc to subscribe.

  #4  
05-01-2011 02:01 AM
Developers member admin is online now
User
 

That breaking of String, does it only occur with the SDM version?

If not, did you find any way to break it? Maybe any of the old faults
related to memory?


I actually have no time to check this myself right now, so I opted to just
ask you.

On Mon, Jan 3, 2011 at 10:35 PM, Tom Igoe <> wrote:

> Thanks, Alexander, and sorry for the delay.
>
> A few tests:
>
> For code that doesn't change the strings much, there's not a big
> difference, a couple dozen bytes' difference in code size. However, when
> you start to do dynamic things, it does add up. For example, the
> StringAppendOperator example is 4910 bytes in 0022, and 5148 bytes with the
> StaticDynamicMemory version. So it does start to take its toll, memory-wise.
>
> On some sketches it actually takes less memory. For example, the one below
> is 3738 bytes using the StaticDynamicMemory version, and 3986 bytes in 0022.
> However, it fails entirely on upload. When the value of (analog 0)/4 is
> high (0xFF), it never gets out of the setup(). So there's still a pretty
> easy way to break String, even with these improvements.
>
>
> void setup() {
> Serial.begin(9600);
> Serial.println("Beginning");
> }
>
> void loop() {
>
> String webColor = "#";
>
> int red = analogRead(A0)/4;
> webColor += String(red, HEX);
> int green = analogRead(A1)/4;
> webColor += String(green, HEX);
> int blue = analogRead(A2)/4;
>
> webColor += String(blue, HEX);
> Serial.println(webColor);
> }
>
>
>
>
>
> On Dec 16, 2010, at 1:27 AM, Alexander Brevig wrote:
>
> > Attached is a zip containing WString.h and .cpp plus
> StaticDynamicMemory.h.
> > Take a backup of the original WString files, and extract this zip into
> the hardware/arduino/cores/arduino folder.
> >
> > Now you're ready to test the modified String library, that does not
> fragment the heap.
> >
> >
> > In the WString header there is a #define called STRING_BUFFER which is
> set to 100 for now, change this to suit your test needs.
> >
> >
> > No error handling is implemented, what do you think we need?
> >
> > I plan to add an availableMemory():int method to the SDM library, and
> maybe some error flags and checks like hasError():int error
> >
> > I also suspect that this library is a bit slower performance wise, but I
> think that's just a cost we'll have to pay to being able to play with
> dynamic strings.
> >
> >
> > Hope to get feedback from someone!
> >
> > On Thu, Dec 16, 2010 at 1:11 AM, Alan Burlison <>
> wrote:
> > On 15/12/2010 16:19, David A. Mellis wrote:
> >
> > I think you're right, but I also don't think that telling people to
> > use the standard C library functions is a solution either. Trying out
> > this String class seems like one way of pushing forwards towards a
> > compromise that provides both an easy-to-use API and a robust
> > implementation. For example, perhaps the buffer sizes need to be
> > specified or provided when the String is instantiated. Or we need an
> > alternative implementation that does more reliable memory allocation
> > (since we're not assuming that the internal buffer is continuous).
> > Other ideas welcome.
> >
> > I think the problem is that the failure modes are not benign. I haven't
> been through all the use cases so this might not work, but perhaps using a
> statically-allocated string ("NOMEM" ?) as a sentinel value instead of null
> when malloc fails might be one way? Also, there might be some benefit in
> making String immutable a la Java - overloaded operators in C++ have a
> tendency to generate anonymous temporaries, which is going to lead to heap
> fragmentation as well.
> >
> > --
> > Alan Burlison
> > --
> >
> > _______________________________________________
___________________________________________________

Posted on the Developers mailing list. Go to http://arduino.cc/mailman/listinfo/developers_arduino.cc to subscribe. It broke in the non-SDM version too, but it took longer to break. In the SDM version it breaks immediately. So it looks like whatever you did highlights the faults sooner, which is good. It also points to a need for an error response of some sort, in answer to your question last mail.

t.

On Jan 3, 2011, at 4:44 PM, Alexander Brevig wrote:

> That breaking of String, does it only occur with the SDM version?
>
> If not, did you find any way to break it? Maybe any of the old faults related to memory?
>
>
> I actually have no time to check this myself right now, so I opted to just ask you.
>
> On Mon, Jan 3, 2011 at 10:35 PM, Tom Igoe <> wrote:
> Thanks, Alexander, and sorry for the delay.
>
> A few tests:
>
> For code that doesn't change the strings much, there's not a big difference, a couple dozen bytes' difference in code size. However, when you start to do dynamic things, it does add up. For example, the StringAppendOperator example is 4910 bytes in 0022, and 5148 bytes with the StaticDynamicMemory version. So it does start to take its toll, memory-wise.
>
> On some sketches it actually takes less memory. For example, the one below is 3738 bytes using the StaticDynamicMemory version, and 3986 bytes in 0022. However, it fails entirely on upload. When the value of (analog 0)/4 is high (0xFF), it never gets out of the setup(). So there's still a pretty easy way to break String, even with these improvements.
>
>
> void setup() {
> Serial.begin(9600);
> Serial.println("Beginning");
> }
>
> void loop() {
>
> String webColor = "#";
>
> int red = analogRead(A0)/4;
> webColor += String(red, HEX);
> int green = analogRead(A1)/4;
> webColor += String(green, HEX);
> int blue = analogRead(A2)/4;
>
> webColor += String(blue, HEX);
> Serial.println(webColor);
> }
>
>
>
>
>
> On Dec 16, 2010, at 1:27 AM, Alexander Brevig wrote:
>
> > Attached is a zip containing WString.h and .cpp plus StaticDynamicMemory.h.
> > Take a backup of the original WString files, and extract this zip into the hardware/arduino/cores/arduino folder.
> >
> > Now you're ready to test the modified String library, that does not fragment the heap.
> >
> >
> > In the WString header there is a #define called STRING_BUFFER which is set to 100 for now, change this to suit your test needs.
> >
> >
> > No error handling is implemented, what do you think we need?
> >
> > I plan to add an availableMemory():int method to the SDM library, and maybe some error flags and checks like hasError():int error
> >
> > I also suspect that this library is a bit slower performance wise, but I think that's just a cost we'll have to pay to being able to play with dynamic strings.
> >
> >
> > Hope to get feedback from someone!
> >
> > On Thu, Dec 16, 2010 at 1:11 AM, Alan Burlison <> wrote:
> > On 15/12/2010 16:19, David A. Mellis wrote:
> >
> > I think you're right, but I also don't think that telling people to
> > use the standard C library functions is a solution either. Trying out
> > this String class seems like one way of pushing forwards towards a
> > compromise that provides both an easy-to-use API and a robust
> > implementation. For example, perhaps the buffer sizes need to be
> > specified or provided when the String is instantiated. Or we need an
> > alternative implementation that does more reliable memory allocation
> > (since we're not assuming that the internal buffer is continuous).
> > Other ideas welcome.
> >
> > I think the problem is that the failure modes are not benign. I haven't been through all the use cases so this might not work, but perhaps using a statically-allocated string ("NOMEM" ?) as a sentinel value instead of null when malloc fails might be one way? Also, there might be some benefit in making String immutable a la Java - overloaded operators in C++ have a tendency to generate anonymous temporaries, which is going to lead to heap fragmentation as well.
> >
> > --
> > Alan Burlison
> > --
> >
> > _______________________________________________
___________________________________________________

Posted on the Developers mailing list. Go to http://arduino.cc/mailman/listinfo/developers_arduino.cc to subscribe. There seems to be a bug with the assignment operator, I'm on it and I'll get
back to you as soon as I get something done.

Thank you for your tests and feedback.


I'll do some tests on my own before I repost it here.

On Tue, Jan 4, 2011 at 6:53 PM, Rick Anderson
<>wrote:

> I just created a test and unpacked and tested it. I also created a
> test based on Tom's code. Not sure I caught the maximum value error
> for 0xFF.
>
> I also ran the tests for bug 411. All the tests compile, but there is
> still memory loss.
>
> I'm attaching the Arduino Test suite, and the test code so you can run
> them as you debug. Let me know if this was helpful.
>
> --Rick
>
> Test run results:
> Example: ATS_StringAssignmentTest.pde
> info.MANUFACTURER = Arduino
> info.CPU-NAME = ATmega328P
> info.GCC-Version = 4.3.2
> info.AVR-LibC-Ver = 1.6.4
> info.Compiled-date = Jan 4 2011
> info.Test-Suite-Name = ATS_StringAssignmentTest
> info.Free-memory = 1110 bytes
> Memory Usage (lost 59 bytes) ... FAIL
> --------------------------
> Ran 1 tests in 1.378s
>
> FAILED (failures=1)
>
>
> Example: ATS_StringMemoryTestPassByReference.pde
>
> info.MANUFACTURER = Arduino
> info.CPU-NAME = ATmega328P
> info.GCC-Version = 4.3.2
> info.AVR-LibC-Ver = 1.6.4
> info.Compiled-date = Jan 4 2011
> info.Test-Suite-Name = ATS_StringMemoryTestPassByReference
> info.Free-memory = 1120 bytes
> Memory Usage (lost 59 bytes) ... FAIL
> --------------------------
> Ran 1 tests in 1.389s
>
> FAILED (failures=1)
>
>
> Example: Tom Igoe Memory Test
> info.MANUFACTURER = Arduino
> info.CPU-NAME = ATmega328P
> info.GCC-Version = 4.3.2
> info.AVR-LibC-Ver = 1.6.4
> info.Compiled-date = Jan 4 2011
> info.Test-Suite-Name = Tom Igoe Memory Test
> info.Free-memory = 1328 bytes
> Memory Usage (lost 9 bytes) ... FAIL
> --------------------------
> Ran 1 tests in 1.374s
>
> FAILED (failures=1)
>
>
>
> --Rick
>
> Tom, rewrote your example as a test.
>
> //************************************************************************
> //* Arduino Tom Igoe Memory Test
> //* (C) 2010 by Rick Anderson
> //* Open source as per standard Arduino code
> //*
> //************************************************************************
> //* Jan 4, 2011 Started on Tom Igoe Memory Test
> //************************************************************************
>
> #include "WProgram.h"
> #include "HardwareSerial.h"
> #include
>
> //************************************************************************
> void setup()
> {
> int startMemoryUsage;
> /*
> * Create variable for the tests.
> */
>
> String webColor = "#000000";
>
> int red = 1023/4;
> int blue = 512/4;
> int green = 128/4;
>
> /*
> * initiate the test run
> */
> //Record starting memory amount
> startMemoryUsage = ATS_GetFreeMemory();
> //Begin test run
> ATS_begin("Arduino", "Tom Igoe Memory Test");
>
> webColor = "#";
> webColor += String(red, HEX);
> webColor += String(green, HEX);
> webColor += String(blue, HEX);
>
> ATS_ReportMemoryUsage(startMemoryUsage);
>
> /*
> * Test complete
> */
>
> ATS_end();
> }
>
>
> //************************************************************************
> void loop()
> {
>
>
> }
>
>
>
>
> On Mon, Jan 3, 2011 at 9:35 PM, Tom Igoe <> wrote:
> > It broke in the non-SDM version too, but it took longer to break. In the
> SDM version it breaks immediately. So it looks like whatever you did
> highlights the faults sooner, which is good. It also points to a need for an
> error response of some sort, in answer to your question last mail.
> >
> > t.
> >
> > On Jan 3, 2011, at 4:44 PM, Alexander Brevig wrote:
> >
> >> That breaking of String, does it only occur with the SDM version?
> >>
> >> If not, did you find any way to break it? Maybe any of the old faults
> related to memory?
> >>
> >>
> >> I actually have no time to check this myself right now, so I opted to
> just ask you.
> >>
> >> On Mon, Jan 3, 2011 at 10:35 PM, Tom Igoe <> wrote:
> >> Thanks, Alexander, and sorry for the delay.
> >>
> >> A few tests:
> >>
> >> For code that doesn't change the strings much, there's not a big
> difference, a couple dozen bytes' difference in code size. However, when
> you start to do dynamic things, it does add up. For example, the
> StringAppendOperator example is 4910 bytes in 0022, and 5148 bytes with the
> StaticDynamicMemory version. So it does start to take its toll, memory-wise.
> >>
> >> On some sketches it actually takes less memory. For example, the one
> below is 3738 bytes using the StaticDynamicMemory version, and 3986 bytes in
> 0022. However, it fails entirely on upload. When the value of (analog 0)/4
> is high (0xFF), it never gets out of the setup(). So there's still a pretty
> easy way to break String, even with these improvements.
> >>
> >>
> >> void setup() {
> >> Serial.begin(9600);
> >> Serial.println("Beginning");
> >> }
> >>
> >> void loop() {
> >>
> >> String webColor = "#";
> >>
> >> int red = analogRead(A0)/4;
> >> webColor += String(red, HEX);
> >> int green = analogRead(A1)/4;
> >> webColor += String(green, HEX);
> >> int blue = analogRead(A2)/4;
> >>
> >> webColor += String(blue, HEX);
> >> Serial.println(webColor);
> >> }
> >>
> >>
> >>
> >>
> >>
> >> On Dec 16, 2010, at 1:27 AM, Alexander Brevig wrote:
> >>
> >> > Attached is a zip containing WString.h and .cpp plus
> StaticDynamicMemory.h.
> >> > Take a backup of the original WString files, and extract this zip into
> the hardware/arduino/cores/arduino folder.
> >> >
> >> > Now you're ready to test the modified String library, that does not
> fragment the heap.
> >> >
> >> >
> >> > In the WString header there is a #define called STRING_BUFFER which is
> set to 100 for now, change this to suit your test needs.
> >> >
> >> >
> >> > No error handling is implemented, what do you think we need?
> >> >
> >> > I plan to add an availableMemory():int method to the SDM library, and
> maybe some error flags and checks like hasError():int error
> >> >
> >> > I also suspect that this library is a bit slower performance wise, but
> I think that's just a cost we'll have to pay to being able to play with
> dynamic strings.
> >> >
> >> >
> >> > Hope to get feedback from someone!
> >> >
> >> > On Thu, Dec 16, 2010 at 1:11 AM, Alan Burlison <
> > wrote:
> >> > On 15/12/2010 16:19, David A. Mellis wrote:
> >> >
> >> > I think you're right, but I also don't think that telling people to
> >> > use the standard C library functions is a solution either. Trying out
> >> > this String class seems like one way of pushing forwards towards a
> >> > compromise that provides both an easy-to-use API and a robust
> >> > implementation. For example, perhaps the buffer sizes need to be
> >> > specified or provided when the String is instantiated. Or we need an
> >> > alternative implementation that does more reliable memory allocation
> >> > (since we're not assuming that the internal buffer is continuous).
> >> > Other ideas welcome.
> >> >
> >> > I think the problem is that the failure modes are not benign. I
> haven't been through all the use cases so this might not work, but perhaps
> using a statically-allocated string ("NOMEM" ?) as a sentinel value instead
> of null when malloc fails might be one way? Also, there might be some
> benefit in making String immutable a la Java - overloaded operators in C++
> have a tendency to generate anonymous temporaries, which is going to lead to
> heap fragmentation as well.
> >> >
> >> > --
> >> > Alan Burlison
> >> > --
> >> >
> >> > _______________________________________________
___________________________________________________

Posted on the Developers mailing list. Go to http://arduino.cc/mailman/listinfo/developers_arduino.cc to subscribe. Is this test suite any different than the one in the github repo?

t.

On Jan 4, 2011, at 12:53 PM, Rick Anderson wrote:

> I just created a test and unpacked and tested it. I also created a
> test based on Tom's code. Not sure I caught the maximum value error
> for 0xFF.
>
> I also ran the tests for bug 411. All the tests compile, but there is
> still memory loss.
>
> I'm attaching the Arduino Test suite, and the test code so you can run
> them as you debug. Let me know if this was helpful.
>
> --Rick
>
> Test run results:
> Example: ATS_StringAssignmentTest.pde
> info.MANUFACTURER = Arduino
> info.CPU-NAME = ATmega328P
> info.GCC-Version = 4.3.2
> info.AVR-LibC-Ver = 1.6.4
> info.Compiled-date = Jan 4 2011
> info.Test-Suite-Name = ATS_StringAssignmentTest
> info.Free-memory = 1110 bytes
> Memory Usage (lost 59 bytes) ... FAIL
> --------------------------
> Ran 1 tests in 1.378s
>
> FAILED (failures=1)
>
>
> Example: ATS_StringMemoryTestPassByReference.pde
>
> info.MANUFACTURER = Arduino
> info.CPU-NAME = ATmega328P
> info.GCC-Version = 4.3.2
> info.AVR-LibC-Ver = 1.6.4
> info.Compiled-date = Jan 4 2011
> info.Test-Suite-Name = ATS_StringMemoryTestPassByReference
> info.Free-memory = 1120 bytes
> Memory Usage (lost 59 bytes) ... FAIL
> --------------------------
> Ran 1 tests in 1.389s
>
> FAILED (failures=1)
>
>
> Example: Tom Igoe Memory Test
> info.MANUFACTURER = Arduino
> info.CPU-NAME = ATmega328P
> info.GCC-Version = 4.3.2
> info.AVR-LibC-Ver = 1.6.4
> info.Compiled-date = Jan 4 2011
> info.Test-Suite-Name = Tom Igoe Memory Test
> info.Free-memory = 1328 bytes
> Memory Usage (lost 9 bytes) ... FAIL
> --------------------------
> Ran 1 tests in 1.374s
>
> FAILED (failures=1)
>
>
>
> --Rick
>
> Tom, rewrote your example as a test.
>
> //************************************************************************
> //* Arduino Tom Igoe Memory Test
> //* (C) 2010 by Rick Anderson
> //* Open source as per standard Arduino code
> //*
> //************************************************************************
> //* Jan 4, 2011 Started on Tom Igoe Memory Test
> //************************************************************************
>
> #include "WProgram.h"
> #include "HardwareSerial.h"
> #include
>
> //************************************************************************
> void setup()
> {
> int startMemoryUsage;
> /*
> * Create variable for the tests.
> */
>
> String webColor = "#000000";
>
> int red = 1023/4;
> int blue = 512/4;
> int green = 128/4;
>
> /*
> * initiate the test run
> */
> //Record starting memory amount
> startMemoryUsage = ATS_GetFreeMemory();
> //Begin test run
> ATS_begin("Arduino", "Tom Igoe Memory Test");
>
> webColor = "#";
> webColor += String(red, HEX);
> webColor += String(green, HEX);
> webColor += String(blue, HEX);
>
> ATS_ReportMemoryUsage(startMemoryUsage);
>
> /*
> * Test complete
> */
>
> ATS_end();
> }
>
>
> //************************************************************************
> void loop()
> {
>
>
> }
>
>
>
>
> On Mon, Jan 3, 2011 at 9:35 PM, Tom Igoe <> wrote:
>> It broke in the non-SDM version too, but it took longer to break. In the SDM version it breaks immediately. So it looks like whatever you did highlights the faults sooner, which is good. It also points to a need for an error response of some sort, in answer to your question last mail.
>>
>> t.
>>
>> On Jan 3, 2011, at 4:44 PM, Alexander Brevig wrote:
>>
>>> That breaking of String, does it only occur with the SDM version?
>>>
>>> If not, did you find any way to break it? Maybe any of the old faults related to memory?
>>>
>>>
>>> I actually have no time to check this myself right now, so I opted to just ask you.
>>>
>>> On Mon, Jan 3, 2011 at 10:35 PM, Tom Igoe <> wrote:
>>> Thanks, Alexander, and sorry for the delay.
>>>
>>> A few tests:
>>>
>>> For code that doesn't change the strings much, there's not a big difference, a couple dozen bytes' difference in code size. However, when you start to do dynamic things, it does add up. For example, the StringAppendOperator example is 4910 bytes in 0022, and 5148 bytes with the StaticDynamicMemory version. So it does start to take its toll, memory-wise.
>>>
>>> On some sketches it actually takes less memory. For example, the one below is 3738 bytes using the StaticDynamicMemory version, and 3986 bytes in 0022. However, it fails entirely on upload. When the value of (analog 0)/4 is high (0xFF), it never gets out of the setup(). So there's still a pretty easy way to break String, even with these improvements.
>>>
>>>
>>> void setup() {
>>> Serial.begin(9600);
>>> Serial.println("Beginning");
>>> }
>>>
>>> void loop() {
>>>
>>> String webColor = "#";
>>>
>>> int red = analogRead(A0)/4;
>>> webColor += String(red, HEX);
>>> int green = analogRead(A1)/4;
>>> webColor += String(green, HEX);
>>> int blue = analogRead(A2)/4;
>>>
>>> webColor += String(blue, HEX);
>>> Serial.println(webColor);
>>> }
>>>
>>>
>>>
>>>
>>>
>>> On Dec 16, 2010, at 1:27 AM, Alexander Brevig wrote:
>>>
>>>> Attached is a zip containing WString.h and .cpp plus StaticDynamicMemory.h.
>>>> Take a backup of the original WString files, and extract this zip into the hardware/arduino/cores/arduino folder.
>>>>
>>>> Now you're ready to test the modified String library, that does not fragment the heap.
>>>>
>>>>
>>>> In the WString header there is a #define called STRING_BUFFER which is set to 100 for now, change this to suit your test needs.
>>>>
>>>>
>>>> No error handling is implemented, what do you think we need?
>>>>
>>>> I plan to add an availableMemory():int method to the SDM library, and maybe some error flags and checks like hasError():int error
>>>>
>>>> I also suspect that this library is a bit slower performance wise, but I think that's just a cost we'll have to pay to being able to play with dynamic strings.
>>>>
>>>>
>>>> Hope to get feedback from someone!
>>>>
>>>> On Thu, Dec 16, 2010 at 1:11 AM, Alan Burlison <> wrote:
>>>> On 15/12/2010 16:19, David A. Mellis wrote:
>>>>
>>>> I think you're right, but I also don't think that telling people to
>>>> use the standard C library functions is a solution either. Trying out
>>>> this String class seems like one way of pushing forwards towards a
>>>> compromise that provides both an easy-to-use API and a robust
>>>> implementation. For example, perhaps the buffer sizes need to be
>>>> specified or provided when the String is instantiated. Or we need an
>>>> alternative implementation that does more reliable memory allocation
>>>> (since we're not assuming that the internal buffer is continuous).
>>>> Other ideas welcome.
>>>>
>>>> I think the problem is that the failure modes are not benign. I haven't been through all the use cases so this might not work, but perhaps using a statically-allocated string ("NOMEM" ?) as a sentinel value instead of null when malloc fails might be one way? Also, there might be some benefit in making String immutable a la Java - overloaded operators in C++ have a tendency to generate anonymous temporaries, which is going to lead to heap fragmentation as well.
>>>>
>>>> --
>>>> Alan Burlison
>>>> --
>>>>
>>>> _______________________________________________
___________________________________________________

Posted on the Developers mailing list. Go to http://arduino.cc/mailman/listinfo/developers_arduino.cc to subscribe.

  #5  
05-01-2011 02:02 AM
Developers member admin is online now
User
 

That breaking of String, does it only occur with the SDM version?

If not, did you find any way to break it? Maybe any of the old faults
related to memory?


I actually have no time to check this myself right now, so I opted to just
ask you.

On Mon, Jan 3, 2011 at 10:35 PM, Tom Igoe <> wrote:

> Thanks, Alexander, and sorry for the delay.
>
> A few tests:
>
> For code that doesn't change the strings much, there's not a big
> difference, a couple dozen bytes' difference in code size. However, when
> you start to do dynamic things, it does add up. For example, the
> StringAppendOperator example is 4910 bytes in 0022, and 5148 bytes with the
> StaticDynamicMemory version. So it does start to take its toll, memory-wise.
>
> On some sketches it actually takes less memory. For example, the one below
> is 3738 bytes using the StaticDynamicMemory version, and 3986 bytes in 0022.
> However, it fails entirely on upload. When the value of (analog 0)/4 is
> high (0xFF), it never gets out of the setup(). So there's still a pretty
> easy way to break String, even with these improvements.
>
>
> void setup() {
> Serial.begin(9600);
> Serial.println("Beginning");
> }
>
> void loop() {
>
> String webColor = "#";
>
> int red = analogRead(A0)/4;
> webColor += String(red, HEX);
> int green = analogRead(A1)/4;
> webColor += String(green, HEX);
> int blue = analogRead(A2)/4;
>
> webColor += String(blue, HEX);
> Serial.println(webColor);
> }
>
>
>
>
>
> On Dec 16, 2010, at 1:27 AM, Alexander Brevig wrote:
>
> > Attached is a zip containing WString.h and .cpp plus
> StaticDynamicMemory.h.
> > Take a backup of the original WString files, and extract this zip into
> the hardware/arduino/cores/arduino folder.
> >
> > Now you're ready to test the modified String library, that does not
> fragment the heap.
> >
> >
> > In the WString header there is a #define called STRING_BUFFER which is
> set to 100 for now, change this to suit your test needs.
> >
> >
> > No error handling is implemented, what do you think we need?
> >
> > I plan to add an availableMemory():int method to the SDM library, and
> maybe some error flags and checks like hasError():int error
> >
> > I also suspect that this library is a bit slower performance wise, but I
> think that's just a cost we'll have to pay to being able to play with
> dynamic strings.
> >
> >
> > Hope to get feedback from someone!
> >
> > On Thu, Dec 16, 2010 at 1:11 AM, Alan Burlison <>
> wrote:
> > On 15/12/2010 16:19, David A. Mellis wrote:
> >
> > I think you're right, but I also don't think that telling people to
> > use the standard C library functions is a solution either. Trying out
> > this String class seems like one way of pushing forwards towards a
> > compromise that provides both an easy-to-use API and a robust
> > implementation. For example, perhaps the buffer sizes need to be
> > specified or provided when the String is instantiated. Or we need an
> > alternative implementation that does more reliable memory allocation
> > (since we're not assuming that the internal buffer is continuous).
> > Other ideas welcome.
> >
> > I think the problem is that the failure modes are not benign. I haven't
> been through all the use cases so this might not work, but perhaps using a
> statically-allocated string ("NOMEM" ?) as a sentinel value instead of null
> when malloc fails might be one way? Also, there might be some benefit in
> making String immutable a la Java - overloaded operators in C++ have a
> tendency to generate anonymous temporaries, which is going to lead to heap
> fragmentation as well.
> >
> > --
> > Alan Burlison
> > --
> >
> > _______________________________________________
___________________________________________________

Posted on the Developers mailing list. Go to http://arduino.cc/mailman/listinfo/developers_arduino.cc to subscribe. It broke in the non-SDM version too, but it took longer to break. In the SDM version it breaks immediately. So it looks like whatever you did highlights the faults sooner, which is good. It also points to a need for an error response of some sort, in answer to your question last mail.

t.

On Jan 3, 2011, at 4:44 PM, Alexander Brevig wrote:

> That breaking of String, does it only occur with the SDM version?
>
> If not, did you find any way to break it? Maybe any of the old faults related to memory?
>
>
> I actually have no time to check this myself right now, so I opted to just ask you.
>
> On Mon, Jan 3, 2011 at 10:35 PM, Tom Igoe <> wrote:
> Thanks, Alexander, and sorry for the delay.
>
> A few tests:
>
> For code that doesn't change the strings much, there's not a big difference, a couple dozen bytes' difference in code size. However, when you start to do dynamic things, it does add up. For example, the StringAppendOperator example is 4910 bytes in 0022, and 5148 bytes with the StaticDynamicMemory version. So it does start to take its toll, memory-wise.
>
> On some sketches it actually takes less memory. For example, the one below is 3738 bytes using the StaticDynamicMemory version, and 3986 bytes in 0022. However, it fails entirely on upload. When the value of (analog 0)/4 is high (0xFF), it never gets out of the setup(). So there's still a pretty easy way to break String, even with these improvements.
>
>
> void setup() {
> Serial.begin(9600);
> Serial.println("Beginning");
> }
>
> void loop() {
>
> String webColor = "#";
>
> int red = analogRead(A0)/4;
> webColor += String(red, HEX);
> int green = analogRead(A1)/4;
> webColor += String(green, HEX);
> int blue = analogRead(A2)/4;
>
> webColor += String(blue, HEX);
> Serial.println(webColor);
> }
>
>
>
>
>
> On Dec 16, 2010, at 1:27 AM, Alexander Brevig wrote:
>
> > Attached is a zip containing WString.h and .cpp plus StaticDynamicMemory.h.
> > Take a backup of the original WString files, and extract this zip into the hardware/arduino/cores/arduino folder.
> >
> > Now you're ready to test the modified String library, that does not fragment the heap.
> >
> >
> > In the WString header there is a #define called STRING_BUFFER which is set to 100 for now, change this to suit your test needs.
> >
> >
> > No error handling is implemented, what do you think we need?
> >
> > I plan to add an availableMemory():int method to the SDM library, and maybe some error flags and checks like hasError():int error
> >
> > I also suspect that this library is a bit slower performance wise, but I think that's just a cost we'll have to pay to being able to play with dynamic strings.
> >
> >
> > Hope to get feedback from someone!
> >
> > On Thu, Dec 16, 2010 at 1:11 AM, Alan Burlison <> wrote:
> > On 15/12/2010 16:19, David A. Mellis wrote:
> >
> > I think you're right, but I also don't think that telling people to
> > use the standard C library functions is a solution either. Trying out
> > this String class seems like one way of pushing forwards towards a
> > compromise that provides both an easy-to-use API and a robust
> > implementation. For example, perhaps the buffer sizes need to be
> > specified or provided when the String is instantiated. Or we need an
> > alternative implementation that does more reliable memory allocation
> > (since we're not assuming that the internal buffer is continuous).
> > Other ideas welcome.
> >
> > I think the problem is that the failure modes are not benign. I haven't been through all the use cases so this might not work, but perhaps using a statically-allocated string ("NOMEM" ?) as a sentinel value instead of null when malloc fails might be one way? Also, there might be some benefit in making String immutable a la Java - overloaded operators in C++ have a tendency to generate anonymous temporaries, which is going to lead to heap fragmentation as well.
> >
> > --
> > Alan Burlison
> > --
> >
> > _______________________________________________
___________________________________________________

Posted on the Developers mailing list. Go to http://arduino.cc/mailman/listinfo/developers_arduino.cc to subscribe. There seems to be a bug with the assignment operator, I'm on it and I'll get
back to you as soon as I get something done.

Thank you for your tests and feedback.


I'll do some tests on my own before I repost it here.

On Tue, Jan 4, 2011 at 6:53 PM, Rick Anderson
<>wrote:

> I just created a test and unpacked and tested it. I also created a
> test based on Tom's code. Not sure I caught the maximum value error
> for 0xFF.
>
> I also ran the tests for bug 411. All the tests compile, but there is
> still memory loss.
>
> I'm attaching the Arduino Test suite, and the test code so you can run
> them as you debug. Let me know if this was helpful.
>
> --Rick
>
> Test run results:
> Example: ATS_StringAssignmentTest.pde
> info.MANUFACTURER = Arduino
> info.CPU-NAME = ATmega328P
> info.GCC-Version = 4.3.2
> info.AVR-LibC-Ver = 1.6.4
> info.Compiled-date = Jan 4 2011
> info.Test-Suite-Name = ATS_StringAssignmentTest
> info.Free-memory = 1110 bytes
> Memory Usage (lost 59 bytes) ... FAIL
> --------------------------
> Ran 1 tests in 1.378s
>
> FAILED (failures=1)
>
>
> Example: ATS_StringMemoryTestPassByReference.pde
>
> info.MANUFACTURER = Arduino
> info.CPU-NAME = ATmega328P
> info.GCC-Version = 4.3.2
> info.AVR-LibC-Ver = 1.6.4
> info.Compiled-date = Jan 4 2011
> info.Test-Suite-Name = ATS_StringMemoryTestPassByReference
> info.Free-memory = 1120 bytes
> Memory Usage (lost 59 bytes) ... FAIL
> --------------------------
> Ran 1 tests in 1.389s
>
> FAILED (failures=1)
>
>
> Example: Tom Igoe Memory Test
> info.MANUFACTURER = Arduino
> info.CPU-NAME = ATmega328P
> info.GCC-Version = 4.3.2
> info.AVR-LibC-Ver = 1.6.4
> info.Compiled-date = Jan 4 2011
> info.Test-Suite-Name = Tom Igoe Memory Test
> info.Free-memory = 1328 bytes
> Memory Usage (lost 9 bytes) ... FAIL
> --------------------------
> Ran 1 tests in 1.374s
>
> FAILED (failures=1)
>
>
>
> --Rick
>
> Tom, rewrote your example as a test.
>
> //************************************************************************
> //* Arduino Tom Igoe Memory Test
> //* (C) 2010 by Rick Anderson
> //* Open source as per standard Arduino code
> //*
> //************************************************************************
> //* Jan 4, 2011 Started on Tom Igoe Memory Test
> //************************************************************************
>
> #include "WProgram.h"
> #include "HardwareSerial.h"
> #include
>
> //************************************************************************
> void setup()
> {
> int startMemoryUsage;
> /*
> * Create variable for the tests.
> */
>
> String webColor = "#000000";
>
> int red = 1023/4;
> int blue = 512/4;
> int green = 128/4;
>
> /*
> * initiate the test run
> */
> //Record starting memory amount
> startMemoryUsage = ATS_GetFreeMemory();
> //Begin test run
> ATS_begin("Arduino", "Tom Igoe Memory Test");
>
> webColor = "#";
> webColor += String(red, HEX);
> webColor += String(green, HEX);
> webColor += String(blue, HEX);
>
> ATS_ReportMemoryUsage(startMemoryUsage);
>
> /*
> * Test complete
> */
>
> ATS_end();
> }
>
>
> //************************************************************************
> void loop()
> {
>
>
> }
>
>
>
>
> On Mon, Jan 3, 2011 at 9:35 PM, Tom Igoe <> wrote:
> > It broke in the non-SDM version too, but it took longer to break. In the
> SDM version it breaks immediately. So it looks like whatever you did
> highlights the faults sooner, which is good. It also points to a need for an
> error response of some sort, in answer to your question last mail.
> >
> > t.
> >
> > On Jan 3, 2011, at 4:44 PM, Alexander Brevig wrote:
> >
> >> That breaking of String, does it only occur with the SDM version?
> >>
> >> If not, did you find any way to break it? Maybe any of the old faults
> related to memory?
> >>
> >>
> >> I actually have no time to check this myself right now, so I opted to
> just ask you.
> >>
> >> On Mon, Jan 3, 2011 at 10:35 PM, Tom Igoe <> wrote:
> >> Thanks, Alexander, and sorry for the delay.
> >>
> >> A few tests:
> >>
> >> For code that doesn't change the strings much, there's not a big
> difference, a couple dozen bytes' difference in code size. However, when
> you start to do dynamic things, it does add up. For example, the
> StringAppendOperator example is 4910 bytes in 0022, and 5148 bytes with the
> StaticDynamicMemory version. So it does start to take its toll, memory-wise.
> >>
> >> On some sketches it actually takes less memory. For example, the one
> below is 3738 bytes using the StaticDynamicMemory version, and 3986 bytes in
> 0022. However, it fails entirely on upload. When the value of (analog 0)/4
> is high (0xFF), it never gets out of the setup(). So there's still a pretty
> easy way to break String, even with these improvements.
> >>
> >>
> >> void setup() {
> >> Serial.begin(9600);
> >> Serial.println("Beginning");
> >> }
> >>
> >> void loop() {
> >>
> >> String webColor = "#";
> >>
> >> int red = analogRead(A0)/4;
> >> webColor += String(red, HEX);
> >> int green = analogRead(A1)/4;
> >> webColor += String(green, HEX);
> >> int blue = analogRead(A2)/4;
> >>
> >> webColor += String(blue, HEX);
> >> Serial.println(webColor);
> >> }
> >>
> >>
> >>
> >>
> >>
> >> On Dec 16, 2010, at 1:27 AM, Alexander Brevig wrote:
> >>
> >> > Attached is a zip containing WString.h and .cpp plus
> StaticDynamicMemory.h.
> >> > Take a backup of the original WString files, and extract this zip into
> the hardware/arduino/cores/arduino folder.
> >> >
> >> > Now you're ready to test the modified String library, that does not
> fragment the heap.
> >> >
> >> >
> >> > In the WString header there is a #define called STRING_BUFFER which is
> set to 100 for now, change this to suit your test needs.
> >> >
> >> >
> >> > No error handling is implemented, what do you think we need?
> >> >
> >> > I plan to add an availableMemory():int method to the SDM library, and
> maybe some error flags and checks like hasError():int error
> >> >
> >> > I also suspect that this library is a bit slower performance wise, but
> I think that's just a cost we'll have to pay to being able to play with
> dynamic strings.
> >> >
> >> >
> >> > Hope to get feedback from someone!
> >> >
> >> > On Thu, Dec 16, 2010 at 1:11 AM, Alan Burlison <
> > wrote:
> >> > On 15/12/2010 16:19, David A. Mellis wrote:
> >> >
> >> > I think you're right, but I also don't think that telling people to
> >> > use the standard C library functions is a solution either. Trying out
> >> > this String class seems like one way of pushing forwards towards a
> >> > compromise that provides both an easy-to-use API and a robust
> >> > implementation. For example, perhaps the buffer sizes need to be
> >> > specified or provided when the String is instantiated. Or we need an
> >> > alternative implementation that does more reliable memory allocation
> >> > (since we're not assuming that the internal buffer is continuous).
> >> > Other ideas welcome.
> >> >
> >> > I think the problem is that the failure modes are not benign. I
> haven't been through all the use cases so this might not work, but perhaps
> using a statically-allocated string ("NOMEM" ?) as a sentinel value instead
> of null when malloc fails might be one way? Also, there might be some
> benefit in making String immutable a la Java - overloaded operators in C++
> have a tendency to generate anonymous temporaries, which is going to lead to
> heap fragmentation as well.
> >> >
> >> > --
> >> > Alan Burlison
> >> > --
> >> >
> >> > _______________________________________________
___________________________________________________

Posted on the Developers mailing list. Go to http://arduino.cc/mailman/listinfo/developers_arduino.cc to subscribe. Is this test suite any different than the one in the github repo?

t.

On Jan 4, 2011, at 12:53 PM, Rick Anderson wrote:

> I just created a test and unpacked and tested it. I also created a
> test based on Tom's code. Not sure I caught the maximum value error
> for 0xFF.
>
> I also ran the tests for bug 411. All the tests compile, but there is
> still memory loss.
>
> I'm attaching the Arduino Test suite, and the test code so you can run
> them as you debug. Let me know if this was helpful.
>
> --Rick
>
> Test run results:
> Example: ATS_StringAssignmentTest.pde
> info.MANUFACTURER = Arduino
> info.CPU-NAME = ATmega328P
> info.GCC-Version = 4.3.2
> info.AVR-LibC-Ver = 1.6.4
> info.Compiled-date = Jan 4 2011
> info.Test-Suite-Name = ATS_StringAssignmentTest
> info.Free-memory = 1110 bytes
> Memory Usage (lost 59 bytes) ... FAIL
> --------------------------
> Ran 1 tests in 1.378s
>
> FAILED (failures=1)
>
>
> Example: ATS_StringMemoryTestPassByReference.pde
>
> info.MANUFACTURER = Arduino
> info.CPU-NAME = ATmega328P
> info.GCC-Version = 4.3.2
> info.AVR-LibC-Ver = 1.6.4
> info.Compiled-date = Jan 4 2011
> info.Test-Suite-Name = ATS_StringMemoryTestPassByReference
> info.Free-memory = 1120 bytes
> Memory Usage (lost 59 bytes) ... FAIL
> --------------------------
> Ran 1 tests in 1.389s
>
> FAILED (failures=1)
>
>
> Example: Tom Igoe Memory Test
> info.MANUFACTURER = Arduino
> info.CPU-NAME = ATmega328P
> info.GCC-Version = 4.3.2
> info.AVR-LibC-Ver = 1.6.4
> info.Compiled-date = Jan 4 2011
> info.Test-Suite-Name = Tom Igoe Memory Test
> info.Free-memory = 1328 bytes
> Memory Usage (lost 9 bytes) ... FAIL
> --------------------------
> Ran 1 tests in 1.374s
>
> FAILED (failures=1)
>
>
>
> --Rick
>
> Tom, rewrote your example as a test.
>
> //************************************************************************
> //* Arduino Tom Igoe Memory Test
> //* (C) 2010 by Rick Anderson
> //* Open source as per standard Arduino code
> //*
> //************************************************************************
> //* Jan 4, 2011 Started on Tom Igoe Memory Test
> //************************************************************************
>
> #include "WProgram.h"
> #include "HardwareSerial.h"
> #include
>
> //************************************************************************
> void setup()
> {
> int startMemoryUsage;
> /*
> * Create variable for the tests.
> */
>
> String webColor = "#000000";
>
> int red = 1023/4;
> int blue = 512/4;
> int green = 128/4;
>
> /*
> * initiate the test run
> */
> //Record starting memory amount
> startMemoryUsage = ATS_GetFreeMemory();
> //Begin test run
> ATS_begin("Arduino", "Tom Igoe Memory Test");
>
> webColor = "#";
> webColor += String(red, HEX);
> webColor += String(green, HEX);
> webColor += String(blue, HEX);
>
> ATS_ReportMemoryUsage(startMemoryUsage);
>
> /*
> * Test complete
> */
>
> ATS_end();
> }
>
>
> //************************************************************************
> void loop()
> {
>
>
> }
>
>
>
>
> On Mon, Jan 3, 2011 at 9:35 PM, Tom Igoe <> wrote:
>> It broke in the non-SDM version too, but it took longer to break. In the SDM version it breaks immediately. So it looks like whatever you did highlights the faults sooner, which is good. It also points to a need for an error response of some sort, in answer to your question last mail.
>>
>> t.
>>
>> On Jan 3, 2011, at 4:44 PM, Alexander Brevig wrote:
>>
>>> That breaking of String, does it only occur with the SDM version?
>>>
>>> If not, did you find any way to break it? Maybe any of the old faults related to memory?
>>>
>>>
>>> I actually have no time to check this myself right now, so I opted to just ask you.
>>>
>>> On Mon, Jan 3, 2011 at 10:35 PM, Tom Igoe <> wrote:
>>> Thanks, Alexander, and sorry for the delay.
>>>
>>> A few tests:
>>>
>>> For code that doesn't change the strings much, there's not a big difference, a couple dozen bytes' difference in code size. However, when you start to do dynamic things, it does add up. For example, the StringAppendOperator example is 4910 bytes in 0022, and 5148 bytes with the StaticDynamicMemory version. So it does start to take its toll, memory-wise.
>>>
>>> On some sketches it actually takes less memory. For example, the one below is 3738 bytes using the StaticDynamicMemory version, and 3986 bytes in 0022. However, it fails entirely on upload. When the value of (analog 0)/4 is high (0xFF), it never gets out of the setup(). So there's still a pretty easy way to break String, even with these improvements.
>>>
>>>
>>> void setup() {
>>> Serial.begin(9600);
>>> Serial.println("Beginning");
>>> }
>>>
>>> void loop() {
>>>
>>> String webColor = "#";
>>>
>>> int red = analogRead(A0)/4;
>>> webColor += String(red, HEX);
>>> int green = analogRead(A1)/4;
>>> webColor += String(green, HEX);
>>> int blue = analogRead(A2)/4;
>>>
>>> webColor += String(blue, HEX);
>>> Serial.println(webColor);
>>> }
>>>
>>>
>>>
>>>
>>>
>>> On Dec 16, 2010, at 1:27 AM, Alexander Brevig wrote:
>>>
>>>> Attached is a zip containing WString.h and .cpp plus StaticDynamicMemory.h.
>>>> Take a backup of the original WString files, and extract this zip into the hardware/arduino/cores/arduino folder.
>>>>
>>>> Now you're ready to test the modified String library, that does not fragment the heap.
>>>>
>>>>
>>>> In the WString header there is a #define called STRING_BUFFER which is set to 100 for now, change this to suit your test needs.
>>>>
>>>>
>>>> No error handling is implemented, what do you think we need?
>>>>
>>>> I plan to add an availableMemory():int method to the SDM library, and maybe some error flags and checks like hasError():int error
>>>>
>>>> I also suspect that this library is a bit slower performance wise, but I think that's just a cost we'll have to pay to being able to play with dynamic strings.
>>>>
>>>>
>>>> Hope to get feedback from someone!
>>>>
>>>> On Thu, Dec 16, 2010 at 1:11 AM, Alan Burlison <> wrote:
>>>> On 15/12/2010 16:19, David A. Mellis wrote:
>>>>
>>>> I think you're right, but I also don't think that telling people to
>>>> use the standard C library functions is a solution either. Trying out
>>>> this String class seems like one way of pushing forwards towards a
>>>> compromise that provides both an easy-to-use API and a robust
>>>> implementation. For example, perhaps the buffer sizes need to be
>>>> specified or provided when the String is instantiated. Or we need an
>>>> alternative implementation that does more reliable memory allocation
>>>> (since we're not assuming that the internal buffer is continuous).
>>>> Other ideas welcome.
>>>>
>>>> I think the problem is that the failure modes are not benign. I haven't been through all the use cases so this might not work, but perhaps using a statically-allocated string ("NOMEM" ?) as a sentinel value instead of null when malloc fails might be one way? Also, there might be some benefit in making String immutable a la Java - overloaded operators in C++ have a tendency to generate anonymous temporaries, which is going to lead to heap fragmentation as well.
>>>>
>>>> --
>>>> Alan Burlison
>>>> --
>>>>
>>>> _______________________________________________
___________________________________________________

Posted on the Developers mailing list. Go to http://arduino.cc/mailman/listinfo/developers_arduino.cc to subscribe. Same exact one. I just included it just in case.

--Rick

On Tue, Jan 4, 2011 at 9:01 PM, Tom Igoe <> wrote:
> Is this test suite any different than the one in the github repo?
>
> t.
>
> On Jan 4, 2011, at 12:53 PM, Rick Anderson wrote:
>
>> I just created a test and unpacked and tested it. I also created a
>> test based on Tom's code. Not sure I caught the maximum value error
>> for 0xFF.
>>
>> I also ran the tests for bug 411. All the tests compile, but there is
>> still memory loss.
>>
>> I'm attaching the Arduino Test suite, and the test code so you can run
>> them as you debug. Let me know if this was helpful.
>>
>> --Rick
>>
>> Test run results:
>> Example:  ATS_StringAssignmentTest.pde
>> info.MANUFACTURER    = Arduino
>> info.CPU-NAME        = ATmega328P
>> info.GCC-Version     = 4.3.2
>> info.AVR-LibC-Ver    = 1.6.4
>> info.Compiled-date   = Jan  4 2011
>> info.Test-Suite-Name = ATS_StringAssignmentTest
>> info.Free-memory     = 1110 bytes
>> Memory Usage (lost 59 bytes)                                ... FAIL
>> --------------------------
>> Ran 1 tests in 1.378s
>>
>> FAILED (failures=1)
>>
>>
>> Example: ATS_StringMemoryTestPassByReference.pde
>>
>> info.MANUFACTURER    = Arduino
>> info.CPU-NAME        = ATmega328P
>> info.GCC-Version     = 4.3.2
>> info.AVR-LibC-Ver    = 1.6.4
>> info.Compiled-date   = Jan  4 2011
>> info.Test-Suite-Name = ATS_StringMemoryTestPassByReference
>> info.Free-memory     = 1120 bytes
>> Memory Usage (lost 59 bytes)                                ... FAIL
>> --------------------------
>> Ran 1 tests in 1.389s
>>
>> FAILED (failures=1)
>>
>>
>> Example: Tom Igoe Memory Test
>> info.MANUFACTURER    = Arduino
>> info.CPU-NAME        = ATmega328P
>> info.GCC-Version     = 4.3.2
>> info.AVR-LibC-Ver    = 1.6.4
>> info.Compiled-date   = Jan  4 2011
>> info.Test-Suite-Name = Tom Igoe Memory Test
>> info.Free-memory     = 1328 bytes
>> Memory Usage (lost 9 bytes)                                 ... FAIL
>> --------------------------
>> Ran 1 tests in 1.374s
>>
>> FAILED (failures=1)
>>
>>
>>
>> --Rick
>>
>> Tom, rewrote your example as a test.
>>
>> //************************************************************************
>> //*   Arduino Tom Igoe Memory Test
>> //*           (C) 2010 by Rick Anderson
>> //*           Open source as per standard Arduino code
>> //*
>> //************************************************************************
>> //*   Jan 4,  2011     Started on Tom Igoe Memory Test
>> //************************************************************************
>>
>> #include      "WProgram.h"
>> #include      "HardwareSerial.h"
>> #include      
>>
>> //************************************************************************
>> void setup()
>> {
>>  int          startMemoryUsage;
>>  /*
>>    * Create variable for the tests.
>>   */
>>
>>  String webColor = "#000000";
>>
>>  int red = 1023/4;
>>  int blue = 512/4;
>>  int green = 128/4;
>>
>>  /*
>>  * initiate the test run
>>   */
>>  //Record starting memory amount
>>  startMemoryUsage     =       ATS_GetFreeMemory();
>>  //Begin test run
>>  ATS_begin("Arduino", "Tom Igoe Memory Test");
>>
>>  webColor = "#";
>>  webColor += String(red, HEX);
>>  webColor += String(green, HEX);
>>  webColor += String(blue, HEX);
>>
>>  ATS_ReportMemoryUsage(startMemoryUsage);
>>
>>  /*
>>   * Test complete
>>   */
>>
>>  ATS_end();
>> }
>>
>>
>> //************************************************************************
>> void loop()
>> {
>>
>>
>> }
>>
>>
>>
>>
>> On Mon, Jan 3, 2011 at 9:35 PM, Tom Igoe <> wrote:
>>> It broke in the non-SDM version too, but it took longer to break. In the SDM version it breaks immediately. So it looks like whatever you did highlights the faults sooner, which is good. It also points to a need for an error response of some sort, in answer to your question last mail.
>>>
>>> t.
>>>
>>> On Jan 3, 2011, at 4:44 PM, Alexander Brevig wrote:
>>>
>>>> That breaking of String, does it only occur with the SDM version?
>>>>
>>>> If not, did you find any way to break it? Maybe any of the old faults related to memory?
>>>>
>>>>
>>>> I actually have no time to check this myself right now, so I opted to just ask you.
>>>>
>>>> On Mon, Jan 3, 2011 at 10:35 PM, Tom Igoe <> wrote:
>>>> Thanks, Alexander, and sorry for the delay.
>>>>
>>>> A few tests:
>>>>
>>>> For code that doesn't change the strings much, there's not a big difference, a couple dozen bytes' difference in code size.  However, when you start to do dynamic things, it does add up.  For example, the StringAppendOperator example is  4910 bytes in 0022, and 5148 bytes with the StaticDynamicMemory version. So it does start to take its toll, memory-wise.
>>>>
>>>> On some sketches it actually takes less memory.  For example, the one below is 3738 bytes using the StaticDynamicMemory version, and 3986 bytes in 0022.  However, it fails entirely on upload.  When the value of (analog 0)/4 is high (0xFF), it never gets out of the setup(). So there's still a pretty easy way to break String, even with these improvements.
>>>>
>>>>
>>>> void setup() {
>>>>  Serial.begin(9600);
>>>>  Serial.println("Beginning");
>>>> }
>>>>
>>>> void loop() {
>>>>
>>>>  String webColor = "#";
>>>>
>>>>  int red = analogRead(A0)/4;
>>>>  webColor += String(red, HEX);
>>>>  int green = analogRead(A1)/4;
>>>>  webColor += String(green, HEX);
>>>>  int blue = analogRead(A2)/4;
>>>>
>>>>  webColor += String(blue, HEX);
>>>>  Serial.println(webColor);
>>>> }
>>>>
>>>>
>>>>
>>>>
>>>>
>>>> On Dec 16, 2010, at 1:27 AM, Alexander Brevig wrote:
>>>>
>>>>> Attached is a zip containing WString.h and .cpp plus StaticDynamicMemory.h.
>>>>> Take a backup of the original WString files, and extract this zip into the hardware/arduino/cores/arduino folder.
>>>>>
>>>>> Now you're ready to test the modified String library, that does not fragment the heap.
>>>>>
>>>>>
>>>>> In the WString header there is a #define called STRING_BUFFER which is set to 100 for now, change this to suit your test needs.
>>>>>
>>>>>
>>>>> No error handling is implemented, what do you think we need?
>>>>>
>>>>> I plan to add an availableMemory():int method to the SDM library, and maybe some error flags and checks like hasError():int error
>>>>>
>>>>> I also suspect that this library is a bit slower performance wise, but I think that's just a cost we'll have to pay to being able to play with dynamic strings.
>>>>>
>>>>>
>>>>> Hope to  get feedback from someone!
>>>>>
>>>>> On Thu, Dec 16, 2010 at 1:11 AM, Alan Burlison <> wrote:
>>>>> On 15/12/2010 16:19, David A. Mellis wrote:
>>>>>
>>>>> I think you're right, but I also don't think that telling people to
>>>>> use the standard C library functions is a solution either.  Trying out
>>>>> this String class seems like one way of pushing forwards towards a
>>>>> compromise that provides both an easy-to-use API and a robust
>>>>> implementation.  For example, perhaps the buffer sizes need to be
>>>>> specified or provided when the String is instantiated.  Or we need an
>>>>> alternative implementation that does more reliable memory allocation
>>>>> (since we're not assuming that the internal buffer is continuous).
>>>>> Other ideas welcome.
>>>>>
>>>>> I think the problem is that the failure modes are not benign.  I haven't been through all the use cases so this might not work, but perhaps using a statically-allocated string ("NOMEM" ?) as a sentinel value instead of null when malloc fails might be one way?  Also, there might be some benefit in making String immutable a la Java - overloaded operators in C++ have a tendency to generate anonymous temporaries, which is going to lead to heap fragmentation as well.
>>>>>
>>>>> --
>>>>> Alan Burlison
>>>>> --
>>>>>
>>>>> _______________________________________________
___________________________________________________

Posted on the Developers mailing list. Go to http://arduino.cc/mailman/listinfo/developers_arduino.cc to subscribe.

  #6  
05-01-2011 01:52 PM
Developers member admin is online now
User
 

That breaking of String, does it only occur with the SDM version?

If not, did you find any way to break it? Maybe any of the old faults
related to memory?


I actually have no time to check this myself right now, so I opted to just
ask you.

On Mon, Jan 3, 2011 at 10:35 PM, Tom Igoe <> wrote:

> Thanks, Alexander, and sorry for the delay.
>
> A few tests:
>
> For code that doesn't change the strings much, there's not a big
> difference, a couple dozen bytes' difference in code size. However, when
> you start to do dynamic things, it does add up. For example, the
> StringAppendOperator example is 4910 bytes in 0022, and 5148 bytes with the
> StaticDynamicMemory version. So it does start to take its toll, memory-wise.
>
> On some sketches it actually takes less memory. For example, the one below
> is 3738 bytes using the StaticDynamicMemory version, and 3986 bytes in 0022.
> However, it fails entirely on upload. When the value of (analog 0)/4 is
> high (0xFF), it never gets out of the setup(). So there's still a pretty
> easy way to break String, even with these improvements.
>
>
> void setup() {
> Serial.begin(9600);
> Serial.println("Beginning");
> }
>
> void loop() {
>
> String webColor = "#";
>
> int red = analogRead(A0)/4;
> webColor += String(red, HEX);
> int green = analogRead(A1)/4;
> webColor += String(green, HEX);
> int blue = analogRead(A2)/4;
>
> webColor += String(blue, HEX);
> Serial.println(webColor);
> }
>
>
>
>
>
> On Dec 16, 2010, at 1:27 AM, Alexander Brevig wrote:
>
> > Attached is a zip containing WString.h and .cpp plus
> StaticDynamicMemory.h.
> > Take a backup of the original WString files, and extract this zip into
> the hardware/arduino/cores/arduino folder.
> >
> > Now you're ready to test the modified String library, that does not
> fragment the heap.
> >
> >
> > In the WString header there is a #define called STRING_BUFFER which is
> set to 100 for now, change this to suit your test needs.
> >
> >
> > No error handling is implemented, what do you think we need?
> >
> > I plan to add an availableMemory():int method to the SDM library, and
> maybe some error flags and checks like hasError():int error
> >
> > I also suspect that this library is a bit slower performance wise, but I
> think that's just a cost we'll have to pay to being able to play with
> dynamic strings.
> >
> >
> > Hope to get feedback from someone!
> >
> > On Thu, Dec 16, 2010 at 1:11 AM, Alan Burlison <>
> wrote:
> > On 15/12/2010 16:19, David A. Mellis wrote:
> >
> > I think you're right, but I also don't think that telling people to
> > use the standard C library functions is a solution either. Trying out
> > this String class seems like one way of pushing forwards towards a
> > compromise that provides both an easy-to-use API and a robust
> > implementation. For example, perhaps the buffer sizes need to be
> > specified or provided when the String is instantiated. Or we need an
> > alternative implementation that does more reliable memory allocation
> > (since we're not assuming that the internal buffer is continuous).
> > Other ideas welcome.
> >
> > I think the problem is that the failure modes are not benign. I haven't
> been through all the use cases so this might not work, but perhaps using a
> statically-allocated string ("NOMEM" ?) as a sentinel value instead of null
> when malloc fails might be one way? Also, there might be some benefit in
> making String immutable a la Java - overloaded operators in C++ have a
> tendency to generate anonymous temporaries, which is going to lead to heap
> fragmentation as well.
> >
> > --
> > Alan Burlison
> > --
> >
> > _______________________________________________
___________________________________________________

Posted on the Developers mailing list. Go to http://arduino.cc/mailman/listinfo/developers_arduino.cc to subscribe. It broke in the non-SDM version too, but it took longer to break. In the SDM version it breaks immediately. So it looks like whatever you did highlights the faults sooner, which is good. It also points to a need for an error response of some sort, in answer to your question last mail.

t.

On Jan 3, 2011, at 4:44 PM, Alexander Brevig wrote:

> That breaking of String, does it only occur with the SDM version?
>
> If not, did you find any way to break it? Maybe any of the old faults related to memory?
>
>
> I actually have no time to check this myself right now, so I opted to just ask you.
>
> On Mon, Jan 3, 2011 at 10:35 PM, Tom Igoe <> wrote:
> Thanks, Alexander, and sorry for the delay.
>
> A few tests:
>
> For code that doesn't change the strings much, there's not a big difference, a couple dozen bytes' difference in code size. However, when you start to do dynamic things, it does add up. For example, the StringAppendOperator example is 4910 bytes in 0022, and 5148 bytes with the StaticDynamicMemory version. So it does start to take its toll, memory-wise.
>
> On some sketches it actually takes less memory. For example, the one below is 3738 bytes using the StaticDynamicMemory version, and 3986 bytes in 0022. However, it fails entirely on upload. When the value of (analog 0)/4 is high (0xFF), it never gets out of the setup(). So there's still a pretty easy way to break String, even with these improvements.
>
>
> void setup() {
> Serial.begin(9600);
> Serial.println("Beginning");
> }
>
> void loop() {
>
> String webColor = "#";
>
> int red = analogRead(A0)/4;
> webColor += String(red, HEX);
> int green = analogRead(A1)/4;
> webColor += String(green, HEX);
> int blue = analogRead(A2)/4;
>
> webColor += String(blue, HEX);
> Serial.println(webColor);
> }
>
>
>
>
>
> On Dec 16, 2010, at 1:27 AM, Alexander Brevig wrote:
>
> > Attached is a zip containing WString.h and .cpp plus StaticDynamicMemory.h.
> > Take a backup of the original WString files, and extract this zip into the hardware/arduino/cores/arduino folder.
> >
> > Now you're ready to test the modified String library, that does not fragment the heap.
> >
> >
> > In the WString header there is a #define called STRING_BUFFER which is set to 100 for now, change this to suit your test needs.
> >
> >
> > No error handling is implemented, what do you think we need?
> >
> > I plan to add an availableMemory():int method to the SDM library, and maybe some error flags and checks like hasError():int error
> >
> > I also suspect that this library is a bit slower performance wise, but I think that's just a cost we'll have to pay to being able to play with dynamic strings.
> >
> >
> > Hope to get feedback from someone!
> >
> > On Thu, Dec 16, 2010 at 1:11 AM, Alan Burlison <> wrote:
> > On 15/12/2010 16:19, David A. Mellis wrote:
> >
> > I think you're right, but I also don't think that telling people to
> > use the standard C library functions is a solution either. Trying out
> > this String class seems like one way of pushing forwards towards a
> > compromise that provides both an easy-to-use API and a robust
> > implementation. For example, perhaps the buffer sizes need to be
> > specified or provided when the String is instantiated. Or we need an
> > alternative implementation that does more reliable memory allocation
> > (since we're not assuming that the internal buffer is continuous).
> > Other ideas welcome.
> >
> > I think the problem is that the failure modes are not benign. I haven't been through all the use cases so this might not work, but perhaps using a statically-allocated string ("NOMEM" ?) as a sentinel value instead of null when malloc fails might be one way? Also, there might be some benefit in making String immutable a la Java - overloaded operators in C++ have a tendency to generate anonymous temporaries, which is going to lead to heap fragmentation as well.
> >
> > --
> > Alan Burlison
> > --
> >
> > _______________________________________________
___________________________________________________

Posted on the Developers mailing list. Go to http://arduino.cc/mailman/listinfo/developers_arduino.cc to subscribe. There seems to be a bug with the assignment operator, I'm on it and I'll get
back to you as soon as I get something done.

Thank you for your tests and feedback.


I'll do some tests on my own before I repost it here.

On Tue, Jan 4, 2011 at 6:53 PM, Rick Anderson
<>wrote:

> I just created a test and unpacked and tested it. I also created a
> test based on Tom's code. Not sure I caught the maximum value error
> for 0xFF.
>
> I also ran the tests for bug 411. All the tests compile, but there is
> still memory loss.
>
> I'm attaching the Arduino Test suite, and the test code so you can run
> them as you debug. Let me know if this was helpful.
>
> --Rick
>
> Test run results:
> Example: ATS_StringAssignmentTest.pde
> info.MANUFACTURER = Arduino
> info.CPU-NAME = ATmega328P
> info.GCC-Version = 4.3.2
> info.AVR-LibC-Ver = 1.6.4
> info.Compiled-date = Jan 4 2011
> info.Test-Suite-Name = ATS_StringAssignmentTest
> info.Free-memory = 1110 bytes
> Memory Usage (lost 59 bytes) ... FAIL
> --------------------------
> Ran 1 tests in 1.378s
>
> FAILED (failures=1)
>
>
> Example: ATS_StringMemoryTestPassByReference.pde
>
> info.MANUFACTURER = Arduino
> info.CPU-NAME = ATmega328P
> info.GCC-Version = 4.3.2
> info.AVR-LibC-Ver = 1.6.4
> info.Compiled-date = Jan 4 2011
> info.Test-Suite-Name = ATS_StringMemoryTestPassByReference
> info.Free-memory = 1120 bytes
> Memory Usage (lost 59 bytes) ... FAIL
> --------------------------
> Ran 1 tests in 1.389s
>
> FAILED (failures=1)
>
>
> Example: Tom Igoe Memory Test
> info.MANUFACTURER = Arduino
> info.CPU-NAME = ATmega328P
> info.GCC-Version = 4.3.2
> info.AVR-LibC-Ver = 1.6.4
> info.Compiled-date = Jan 4 2011
> info.Test-Suite-Name = Tom Igoe Memory Test
> info.Free-memory = 1328 bytes
> Memory Usage (lost 9 bytes) ... FAIL
> --------------------------
> Ran 1 tests in 1.374s
>
> FAILED (failures=1)
>
>
>
> --Rick
>
> Tom, rewrote your example as a test.
>
> //************************************************************************
> //* Arduino Tom Igoe Memory Test
> //* (C) 2010 by Rick Anderson
> //* Open source as per standard Arduino code
> //*
> //************************************************************************
> //* Jan 4, 2011 Started on Tom Igoe Memory Test
> //************************************************************************
>
> #include "WProgram.h"
> #include "HardwareSerial.h"
> #include
>
> //************************************************************************
> void setup()
> {
> int startMemoryUsage;
> /*
> * Create variable for the tests.
> */
>
> String webColor = "#000000";
>
> int red = 1023/4;
> int blue = 512/4;
> int green = 128/4;
>
> /*
> * initiate the test run
> */
> //Record starting memory amount
> startMemoryUsage = ATS_GetFreeMemory();
> //Begin test run
> ATS_begin("Arduino", "Tom Igoe Memory Test");
>
> webColor = "#";
> webColor += String(red, HEX);
> webColor += String(green, HEX);
> webColor += String(blue, HEX);
>
> ATS_ReportMemoryUsage(startMemoryUsage);
>
> /*
> * Test complete
> */
>
> ATS_end();
> }
>
>
> //************************************************************************
> void loop()
> {
>
>
> }
>
>
>
>
> On Mon, Jan 3, 2011 at 9:35 PM, Tom Igoe <> wrote:
> > It broke in the non-SDM version too, but it took longer to break. In the
> SDM version it breaks immediately. So it looks like whatever you did
> highlights the faults sooner, which is good. It also points to a need for an
> error response of some sort, in answer to your question last mail.
> >
> > t.
> >
> > On Jan 3, 2011, at 4:44 PM, Alexander Brevig wrote:
> >
> >> That breaking of String, does it only occur with the SDM version?
> >>
> >> If not, did you find any way to break it? Maybe any of the old faults
> related to memory?
> >>
> >>
> >> I actually have no time to check this myself right now, so I opted to
> just ask you.
> >>
> >> On Mon, Jan 3, 2011 at 10:35 PM, Tom Igoe <> wrote:
> >> Thanks, Alexander, and sorry for the delay.
> >>
> >> A few tests:
> >>
> >> For code that doesn't change the strings much, there's not a big
> difference, a couple dozen bytes' difference in code size. However, when
> you start to do dynamic things, it does add up. For example, the
> StringAppendOperator example is 4910 bytes in 0022, and 5148 bytes with the
> StaticDynamicMemory version. So it does start to take its toll, memory-wise.
> >>
> >> On some sketches it actually takes less memory. For example, the one
> below is 3738 bytes using the StaticDynamicMemory version, and 3986 bytes in
> 0022. However, it fails entirely on upload. When the value of (analog 0)/4
> is high (0xFF), it never gets out of the setup(). So there's still a pretty
> easy way to break String, even with these improvements.
> >>
> >>
> >> void setup() {
> >> Serial.begin(9600);
> >> Serial.println("Beginning");
> >> }
> >>
> >> void loop() {
> >>
> >> String webColor = "#";
> >>
> >> int red = analogRead(A0)/4;
> >> webColor += String(red, HEX);
> >> int green = analogRead(A1)/4;
> >> webColor += String(green, HEX);
> >> int blue = analogRead(A2)/4;
> >>
> >> webColor += String(blue, HEX);
> >> Serial.println(webColor);
> >> }
> >>
> >>
> >>
> >>
> >>
> >> On Dec 16, 2010, at 1:27 AM, Alexander Brevig wrote:
> >>
> >> > Attached is a zip containing WString.h and .cpp plus
> StaticDynamicMemory.h.
> >> > Take a backup of the original WString files, and extract this zip into
> the hardware/arduino/cores/arduino folder.
> >> >
> >> > Now you're ready to test the modified String library, that does not
> fragment the heap.
> >> >
> >> >
> >> > In the WString header there is a #define called STRING_BUFFER which is
> set to 100 for now, change this to suit your test needs.
> >> >
> >> >
> >> > No error handling is implemented, what do you think we need?
> >> >
> >> > I plan to add an availableMemory():int method to the SDM library, and
> maybe some error flags and checks like hasError():int error
> >> >
> >> > I also suspect that this library is a bit slower performance wise, but
> I think that's just a cost we'll have to pay to being able to play with
> dynamic strings.
> >> >
> >> >
> >> > Hope to get feedback from someone!
> >> >
> >> > On Thu, Dec 16, 2010 at 1:11 AM, Alan Burlison <
> > wrote:
> >> > On 15/12/2010 16:19, David A. Mellis wrote:
> >> >
> >> > I think you're right, but I also don't think that telling people to
> >> > use the standard C library functions is a solution either. Trying out
> >> > this String class seems like one way of pushing forwards towards a
> >> > compromise that provides both an easy-to-use API and a robust
> >> > implementation. For example, perhaps the buffer sizes need to be
> >> > specified or provided when the String is instantiated. Or we need an
> >> > alternative implementation that does more reliable memory allocation
> >> > (since we're not assuming that the internal buffer is continuous).
> >> > Other ideas welcome.
> >> >
> >> > I think the problem is that the failure modes are not benign. I
> haven't been through all the use cases so this might not work, but perhaps
> using a statically-allocated string ("NOMEM" ?) as a sentinel value instead
> of null when malloc fails might be one way? Also, there might be some
> benefit in making String immutable a la Java - overloaded operators in C++
> have a tendency to generate anonymous temporaries, which is going to lead to
> heap fragmentation as well.
> >> >
> >> > --
> >> > Alan Burlison
> >> > --
> >> >
> >> > _______________________________________________
___________________________________________________

Posted on the Developers mailing list. Go to http://arduino.cc/mailman/listinfo/developers_arduino.cc to subscribe. Is this test suite any different than the one in the github repo?

t.

On Jan 4, 2011, at 12:53 PM, Rick Anderson wrote:

> I just created a test and unpacked and tested it. I also created a
> test based on Tom's code. Not sure I caught the maximum value error
> for 0xFF.
>
> I also ran the tests for bug 411. All the tests compile, but there is
> still memory loss.
>
> I'm attaching the Arduino Test suite, and the test code so you can run
> them as you debug. Let me know if this was helpful.
>
> --Rick
>
> Test run results:
> Example: ATS_StringAssignmentTest.pde
> info.MANUFACTURER = Arduino
> info.CPU-NAME = ATmega328P
> info.GCC-Version = 4.3.2
> info.AVR-LibC-Ver = 1.6.4
> info.Compiled-date = Jan 4 2011
> info.Test-Suite-Name = ATS_StringAssignmentTest
> info.Free-memory = 1110 bytes
> Memory Usage (lost 59 bytes) ... FAIL
> --------------------------
> Ran 1 tests in 1.378s
>
> FAILED (failures=1)
>
>
> Example: ATS_StringMemoryTestPassByReference.pde
>
> info.MANUFACTURER = Arduino
> info.CPU-NAME = ATmega328P
> info.GCC-Version = 4.3.2
> info.AVR-LibC-Ver = 1.6.4
> info.Compiled-date = Jan 4 2011
> info.Test-Suite-Name = ATS_StringMemoryTestPassByReference
> info.Free-memory = 1120 bytes
> Memory Usage (lost 59 bytes) ... FAIL
> --------------------------
> Ran 1 tests in 1.389s
>
> FAILED (failures=1)
>
>
> Example: Tom Igoe Memory Test
> info.MANUFACTURER = Arduino
> info.CPU-NAME = ATmega328P
> info.GCC-Version = 4.3.2
> info.AVR-LibC-Ver = 1.6.4
> info.Compiled-date = Jan 4 2011
> info.Test-Suite-Name = Tom Igoe Memory Test
> info.Free-memory = 1328 bytes
> Memory Usage (lost 9 bytes) ... FAIL
> --------------------------
> Ran 1 tests in 1.374s
>
> FAILED (failures=1)
>
>
>
> --Rick
>
> Tom, rewrote your example as a test.
>
> //************************************************************************
> //* Arduino Tom Igoe Memory Test
> //* (C) 2010 by Rick Anderson
> //* Open source as per standard Arduino code
> //*
> //************************************************************************
> //* Jan 4, 2011 Started on Tom Igoe Memory Test
> //************************************************************************
>
> #include "WProgram.h"
> #include "HardwareSerial.h"
> #include
>
> //************************************************************************
> void setup()
> {
> int startMemoryUsage;
> /*
> * Create variable for the tests.
> */
>
> String webColor = "#000000";
>
> int red = 1023/4;
> int blue = 512/4;
> int green = 128/4;
>
> /*
> * initiate the test run
> */
> //Record starting memory amount
> startMemoryUsage = ATS_GetFreeMemory();
> //Begin test run
> ATS_begin("Arduino", "Tom Igoe Memory Test");
>
> webColor = "#";
> webColor += String(red, HEX);
> webColor += String(green, HEX);
> webColor += String(blue, HEX);
>
> ATS_ReportMemoryUsage(startMemoryUsage);
>
> /*
> * Test complete
> */
>
> ATS_end();
> }
>
>
> //************************************************************************
> void loop()
> {
>
>
> }
>
>
>
>
> On Mon, Jan 3, 2011 at 9:35 PM, Tom Igoe <> wrote:
>> It broke in the non-SDM version too, but it took longer to break. In the SDM version it breaks immediately. So it looks like whatever you did highlights the faults sooner, which is good. It also points to a need for an error response of some sort, in answer to your question last mail.
>>
>> t.
>>
>> On Jan 3, 2011, at 4:44 PM, Alexander Brevig wrote:
>>
>>> That breaking of String, does it only occur with the SDM version?
>>>
>>> If not, did you find any way to break it? Maybe any of the old faults related to memory?
>>>
>>>
>>> I actually have no time to check this myself right now, so I opted to just ask you.
>>>
>>> On Mon, Jan 3, 2011 at 10:35 PM, Tom Igoe <> wrote:
>>> Thanks, Alexander, and sorry for the delay.
>>>
>>> A few tests:
>>>
>>> For code that doesn't change the strings much, there's not a big difference, a couple dozen bytes' difference in code size. However, when you start to do dynamic things, it does add up. For example, the StringAppendOperator example is 4910 bytes in 0022, and 5148 bytes with the StaticDynamicMemory version. So it does start to take its toll, memory-wise.
>>>
>>> On some sketches it actually takes less memory. For example, the one below is 3738 bytes using the StaticDynamicMemory version, and 3986 bytes in 0022. However, it fails entirely on upload. When the value of (analog 0)/4 is high (0xFF), it never gets out of the setup(). So there's still a pretty easy way to break String, even with these improvements.
>>>
>>>
>>> void setup() {
>>> Serial.begin(9600);
>>> Serial.println("Beginning");
>>> }
>>>
>>> void loop() {
>>>
>>> String webColor = "#";
>>>
>>> int red = analogRead(A0)/4;
>>> webColor += String(red, HEX);
>>> int green = analogRead(A1)/4;
>>> webColor += String(green, HEX);
>>> int blue = analogRead(A2)/4;
>>>
>>> webColor += String(blue, HEX);
>>> Serial.println(webColor);
>>> }
>>>
>>>
>>>
>>>
>>>
>>> On Dec 16, 2010, at 1:27 AM, Alexander Brevig wrote:
>>>
>>>> Attached is a zip containing WString.h and .cpp plus StaticDynamicMemory.h.
>>>> Take a backup of the original WString files, and extract this zip into the hardware/arduino/cores/arduino folder.
>>>>
>>>> Now you're ready to test the modified String library, that does not fragment the heap.
>>>>
>>>>
>>>> In the WString header there is a #define called STRING_BUFFER which is set to 100 for now, change this to suit your test needs.
>>>>
>>>>
>>>> No error handling is implemented, what do you think we need?
>>>>
>>>> I plan to add an availableMemory():int method to the SDM library, and maybe some error flags and checks like hasError():int error
>>>>
>>>> I also suspect that this library is a bit slower performance wise, but I think that's just a cost we'll have to pay to being able to play with dynamic strings.
>>>>
>>>>
>>>> Hope to get feedback from someone!
>>>>
>>>> On Thu, Dec 16, 2010 at 1:11 AM, Alan Burlison <> wrote:
>>>> On 15/12/2010 16:19, David A. Mellis wrote:
>>>>
>>>> I think you're right, but I also don't think that telling people to
>>>> use the standard C library functions is a solution either. Trying out
>>>> this String class seems like one way of pushing forwards towards a
>>>> compromise that provides both an easy-to-use API and a robust
>>>> implementation. For example, perhaps the buffer sizes need to be
>>>> specified or provided when the String is instantiated. Or we need an
>>>> alternative implementation that does more reliable memory allocation
>>>> (since we're not assuming that the internal buffer is continuous).
>>>> Other ideas welcome.
>>>>
>>>> I think the problem is that the failure modes are not benign. I haven't been through all the use cases so this might not work, but perhaps using a statically-allocated string ("NOMEM" ?) as a sentinel value instead of null when malloc fails might be one way? Also, there might be some benefit in making String immutable a la Java - overloaded operators in C++ have a tendency to generate anonymous temporaries, which is going to lead to heap fragmentation as well.
>>>>
>>>> --
>>>> Alan Burlison
>>>> --
>>>>
>>>> _______________________________________________
___________________________________________________

Posted on the Developers mailing list. Go to http://arduino.cc/mailman/listinfo/developers_arduino.cc to subscribe. Same exact one. I just included it just in case.

--Rick

On Tue, Jan 4, 2011 at 9:01 PM, Tom Igoe <> wrote:
> Is this test suite any different than the one in the github repo?
>
> t.
>
> On Jan 4, 2011, at 12:53 PM, Rick Anderson wrote:
>
>> I just created a test and unpacked and tested it. I also created a
>> test based on Tom's code. Not sure I caught the maximum value error
>> for 0xFF.
>>
>> I also ran the tests for bug 411. All the tests compile, but there is
>> still memory loss.
>>
>> I'm attaching the Arduino Test suite, and the test code so you can run
>> them as you debug. Let me know if this was helpful.
>>
>> --Rick
>>
>> Test run results:
>> Example:  ATS_StringAssignmentTest.pde
>> info.MANUFACTURER    = Arduino
>> info.CPU-NAME        = ATmega328P
>> info.GCC-Version     = 4.3.2
>> info.AVR-LibC-Ver    = 1.6.4
>> info.Compiled-date   = Jan  4 2011
>> info.Test-Suite-Name = ATS_StringAssignmentTest
>> info.Free-memory     = 1110 bytes
>> Memory Usage (lost 59 bytes)                                ... FAIL
>> --------------------------
>> Ran 1 tests in 1.378s
>>
>> FAILED (failures=1)
>>
>>
>> Example: ATS_StringMemoryTestPassByReference.pde
>>
>> info.MANUFACTURER    = Arduino
>> info.CPU-NAME        = ATmega328P
>> info.GCC-Version     = 4.3.2
>> info.AVR-LibC-Ver    = 1.6.4
>> info.Compiled-date   = Jan  4 2011
>> info.Test-Suite-Name = ATS_StringMemoryTestPassByReference
>> info.Free-memory     = 1120 bytes
>> Memory Usage (lost 59 bytes)                                ... FAIL
>> --------------------------
>> Ran 1 tests in 1.389s
>>
>> FAILED (failures=1)
>>
>>
>> Example: Tom Igoe Memory Test
>> info.MANUFACTURER    = Arduino
>> info.CPU-NAME        = ATmega328P
>> info.GCC-Version     = 4.3.2
>> info.AVR-LibC-Ver    = 1.6.4
>> info.Compiled-date   = Jan  4 2011
>> info.Test-Suite-Name = Tom Igoe Memory Test
>> info.Free-memory     = 1328 bytes
>> Memory Usage (lost 9 bytes)                                 ... FAIL
>> --------------------------
>> Ran 1 tests in 1.374s
>>
>> FAILED (failures=1)
>>
>>
>>
>> --Rick
>>
>> Tom, rewrote your example as a test.
>>
>> //************************************************************************
>> //*   Arduino Tom Igoe Memory Test
>> //*           (C) 2010 by Rick Anderson
>> //*           Open source as per standard Arduino code
>> //*
>> //************************************************************************
>> //*   Jan 4,  2011     Started on Tom Igoe Memory Test
>> //************************************************************************
>>
>> #include      "WProgram.h"
>> #include      "HardwareSerial.h"
>> #include      
>>
>> //************************************************************************
>> void setup()
>> {
>>  int          startMemoryUsage;
>>  /*
>>    * Create variable for the tests.
>>   */
>>
>>  String webColor = "#000000";
>>
>>  int red = 1023/4;
>>  int blue = 512/4;
>>  int green = 128/4;
>>
>>  /*
>>  * initiate the test run
>>   */
>>  //Record starting memory amount
>>  startMemoryUsage     =       ATS_GetFreeMemory();
>>  //Begin test run
>>  ATS_begin("Arduino", "Tom Igoe Memory Test");
>>
>>  webColor = "#";
>>  webColor += String(red, HEX);
>>  webColor += String(green, HEX);
>>  webColor += String(blue, HEX);
>>
>>  ATS_ReportMemoryUsage(startMemoryUsage);
>>
>>  /*
>>   * Test complete
>>   */
>>
>>  ATS_end();
>> }
>>
>>
>> //************************************************************************
>> void loop()
>> {
>>
>>
>> }
>>
>>
>>
>>
>> On Mon, Jan 3, 2011 at 9:35 PM, Tom Igoe <> wrote:
>>> It broke in the non-SDM version too, but it took longer to break. In the SDM version it breaks immediately. So it looks like whatever you did highlights the faults sooner, which is good. It also points to a need for an error response of some sort, in answer to your question last mail.
>>>
>>> t.
>>>
>>> On Jan 3, 2011, at 4:44 PM, Alexander Brevig wrote:
>>>
>>>> That breaking of String, does it only occur with the SDM version?
>>>>
>>>> If not, did you find any way to break it? Maybe any of the old faults related to memory?
>>>>
>>>>
>>>> I actually have no time to check this myself right now, so I opted to just ask you.
>>>>
>>>> On Mon, Jan 3, 2011 at 10:35 PM, Tom Igoe <> wrote:
>>>> Thanks, Alexander, and sorry for the delay.
>>>>
>>>> A few tests:
>>>>
>>>> For code that doesn't change the strings much, there's not a big difference, a couple dozen bytes' difference in code size.  However, when you start to do dynamic things, it does add up.  For example, the StringAppendOperator example is  4910 bytes in 0022, and 5148 bytes with the StaticDynamicMemory version. So it does start to take its toll, memory-wise.
>>>>
>>>> On some sketches it actually takes less memory.  For example, the one below is 3738 bytes using the StaticDynamicMemory version, and 3986 bytes in 0022.  However, it fails entirely on upload.  When the value of (analog 0)/4 is high (0xFF), it never gets out of the setup(). So there's still a pretty easy way to break String, even with these improvements.
>>>>
>>>>
>>>> void setup() {
>>>>  Serial.begin(9600);
>>>>  Serial.println("Beginning");
>>>> }
>>>>
>>>> void loop() {
>>>>
>>>>  String webColor = "#";
>>>>
>>>>  int red = analogRead(A0)/4;
>>>>  webColor += String(red, HEX);
>>>>  int green = analogRead(A1)/4;
>>>>  webColor += String(green, HEX);
>>>>  int blue = analogRead(A2)/4;
>>>>
>>>>  webColor += String(blue, HEX);
>>>>  Serial.println(webColor);
>>>> }
>>>>
>>>>
>>>>
>>>>
>>>>
>>>> On Dec 16, 2010, at 1:27 AM, Alexander Brevig wrote:
>>>>
>>>>> Attached is a zip containing WString.h and .cpp plus StaticDynamicMemory.h.
>>>>> Take a backup of the original WString files, and extract this zip into the hardware/arduino/cores/arduino folder.
>>>>>
>>>>> Now you're ready to test the modified String library, that does not fragment the heap.
>>>>>
>>>>>
>>>>> In the WString header there is a #define called STRING_BUFFER which is set to 100 for now, change this to suit your test needs.
>>>>>
>>>>>
>>>>> No error handling is implemented, what do you think we need?
>>>>>
>>>>> I plan to add an availableMemory():int method to the SDM library, and maybe some error flags and checks like hasError():int error
>>>>>
>>>>> I also suspect that this library is a bit slower performance wise, but I think that's just a cost we'll have to pay to being able to play with dynamic strings.
>>>>>
>>>>>
>>>>> Hope to  get feedback from someone!
>>>>>
>>>>> On Thu, Dec 16, 2010 at 1:11 AM, Alan Burlison <> wrote:
>>>>> On 15/12/2010 16:19, David A. Mellis wrote:
>>>>>
>>>>> I think you're right, but I also don't think that telling people to
>>>>> use the standard C library functions is a solution either.  Trying out
>>>>> this String class seems like one way of pushing forwards towards a
>>>>> compromise that provides both an easy-to-use API and a robust
>>>>> implementation.  For example, perhaps the buffer sizes need to be
>>>>> specified or provided when the String is instantiated.  Or we need an
>>>>> alternative implementation that does more reliable memory allocation
>>>>> (since we're not assuming that the internal buffer is continuous).
>>>>> Other ideas welcome.
>>>>>
>>>>> I think the problem is that the failure modes are not benign.  I haven't been through all the use cases so this might not work, but perhaps using a statically-allocated string ("NOMEM" ?) as a sentinel value instead of null when malloc fails might be one way?  Also, there might be some benefit in making String immutable a la Java - overloaded operators in C++ have a tendency to generate anonymous temporaries, which is going to lead to heap fragmentation as well.
>>>>>
>>>>> --
>>>>> Alan Burlison
>>>>> --
>>>>>
>>>>> _______________________________________________
___________________________________________________

Posted on the Developers mailing list. Go to http://arduino.cc/mailman/listinfo/developers_arduino.cc to subscribe. On 04/01/2011 17:53, Rick Anderson wrote:

> I also ran the tests for bug 411. All the tests compile, but there is
> still memory loss.

Most of the assumptions made by the test harness and test case code are
wrong, any reports of 'lost' memory are therefore likely to be wrong as
well. If you want to do leak detection you can't do it in the naive way
it is being done at present.

--
Alan Burlison
--

_______________________________________________
___________________________________________________

Posted on the Developers mailing list. Go to http://arduino.cc/mailman/listinfo/developers_arduino.cc to subscribe.

  #7  
05-01-2011 03:19 PM
Developers member admin is online now
User
 

That breaking of String, does it only occur with the SDM version?

If not, did you find any way to break it? Maybe any of the old faults
related to memory?


I actually have no time to check this myself right now, so I opted to just
ask you.

On Mon, Jan 3, 2011 at 10:35 PM, Tom Igoe <> wrote:

> Thanks, Alexander, and sorry for the delay.
>
> A few tests:
>
> For code that doesn't change the strings much, there's not a big
> difference, a couple dozen bytes' difference in code size. However, when
> you start to do dynamic things, it does add up. For example, the
> StringAppendOperator example is 4910 bytes in 0022, and 5148 bytes with the
> StaticDynamicMemory version. So it does start to take its toll, memory-wise.
>
> On some sketches it actually takes less memory. For example, the one below
> is 3738 bytes using the StaticDynamicMemory version, and 3986 bytes in 0022.
> However, it fails entirely on upload. When the value of (analog 0)/4 is
> high (0xFF), it never gets out of the setup(). So there's still a pretty
> easy way to break String, even with these improvements.
>
>
> void setup() {
> Serial.begin(9600);
> Serial.println("Beginning");
> }
>
> void loop() {
>
> String webColor = "#";
>
> int red = analogRead(A0)/4;
> webColor += String(red, HEX);
> int green = analogRead(A1)/4;
> webColor += String(green, HEX);
> int blue = analogRead(A2)/4;
>
> webColor += String(blue, HEX);
> Serial.println(webColor);
> }
>
>
>
>
>
> On Dec 16, 2010, at 1:27 AM, Alexander Brevig wrote:
>
> > Attached is a zip containing WString.h and .cpp plus
> StaticDynamicMemory.h.
> > Take a backup of the original WString files, and extract this zip into
> the hardware/arduino/cores/arduino folder.
> >
> > Now you're ready to test the modified String library, that does not
> fragment the heap.
> >
> >
> > In the WString header there is a #define called STRING_BUFFER which is
> set to 100 for now, change this to suit your test needs.
> >
> >
> > No error handling is implemented, what do you think we need?
> >
> > I plan to add an availableMemory():int method to the SDM library, and
> maybe some error flags and checks like hasError():int error
> >
> > I also suspect that this library is a bit slower performance wise, but I
> think that's just a cost we'll have to pay to being able to play with
> dynamic strings.
> >
> >
> > Hope to get feedback from someone!
> >
> > On Thu, Dec 16, 2010 at 1:11 AM, Alan Burlison <>
> wrote:
> > On 15/12/2010 16:19, David A. Mellis wrote:
> >
> > I think you're right, but I also don't think that telling people to
> > use the standard C library functions is a solution either. Trying out
> > this String class seems like one way of pushing forwards towards a
> > compromise that provides both an easy-to-use API and a robust
> > implementation. For example, perhaps the buffer sizes need to be
> > specified or provided when the String is instantiated. Or we need an
> > alternative implementation that does more reliable memory allocation
> > (since we're not assuming that the internal buffer is continuous).
> > Other ideas welcome.
> >
> > I think the problem is that the failure modes are not benign. I haven't
> been through all the use cases so this might not work, but perhaps using a
> statically-allocated string ("NOMEM" ?) as a sentinel value instead of null
> when malloc fails might be one way? Also, there might be some benefit in
> making String immutable a la Java - overloaded operators in C++ have a
> tendency to generate anonymous temporaries, which is going to lead to heap
> fragmentation as well.
> >
> > --
> > Alan Burlison
> > --
> >
> > _______________________________________________
___________________________________________________

Posted on the Developers mailing list. Go to http://arduino.cc/mailman/listinfo/developers_arduino.cc to subscribe. It broke in the non-SDM version too, but it took longer to break. In the SDM version it breaks immediately. So it looks like whatever you did highlights the faults sooner, which is good. It also points to a need for an error response of some sort, in answer to your question last mail.

t.

On Jan 3, 2011, at 4:44 PM, Alexander Brevig wrote:

> That breaking of String, does it only occur with the SDM version?
>
> If not, did you find any way to break it? Maybe any of the old faults related to memory?
>
>
> I actually have no time to check this myself right now, so I opted to just ask you.
>
> On Mon, Jan 3, 2011 at 10:35 PM, Tom Igoe <> wrote:
> Thanks, Alexander, and sorry for the delay.
>
> A few tests:
>
> For code that doesn't change the strings much, there's not a big difference, a couple dozen bytes' difference in code size. However, when you start to do dynamic things, it does add up. For example, the StringAppendOperator example is 4910 bytes in 0022, and 5148 bytes with the StaticDynamicMemory version. So it does start to take its toll, memory-wise.
>
> On some sketches it actually takes less memory. For example, the one below is 3738 bytes using the StaticDynamicMemory version, and 3986 bytes in 0022. However, it fails entirely on upload. When the value of (analog 0)/4 is high (0xFF), it never gets out of the setup(). So there's still a pretty easy way to break String, even with these improvements.
>
>
> void setup() {
> Serial.begin(9600);
> Serial.println("Beginning");
> }
>
> void loop() {
>
> String webColor = "#";
>
> int red = analogRead(A0)/4;
> webColor += String(red, HEX);
> int green = analogRead(A1)/4;
> webColor += String(green, HEX);
> int blue = analogRead(A2)/4;
>
> webColor += String(blue, HEX);
> Serial.println(webColor);
> }
>
>
>
>
>
> On Dec 16, 2010, at 1:27 AM, Alexander Brevig wrote:
>
> > Attached is a zip containing WString.h and .cpp plus StaticDynamicMemory.h.
> > Take a backup of the original WString files, and extract this zip into the hardware/arduino/cores/arduino folder.
> >
> > Now you're ready to test the modified String library, that does not fragment the heap.
> >
> >
> > In the WString header there is a #define called STRING_BUFFER which is set to 100 for now, change this to suit your test needs.
> >
> >
> > No error handling is implemented, what do you think we need?
> >
> > I plan to add an availableMemory():int method to the SDM library, and maybe some error flags and checks like hasError():int error
> >
> > I also suspect that this library is a bit slower performance wise, but I think that's just a cost we'll have to pay to being able to play with dynamic strings.
> >
> >
> > Hope to get feedback from someone!
> >
> > On Thu, Dec 16, 2010 at 1:11 AM, Alan Burlison <> wrote:
> > On 15/12/2010 16:19, David A. Mellis wrote:
> >
> > I think you're right, but I also don't think that telling people to
> > use the standard C library functions is a solution either. Trying out
> > this String class seems like one way of pushing forwards towards a
> > compromise that provides both an easy-to-use API and a robust
> > implementation. For example, perhaps the buffer sizes need to be
> > specified or provided when the String is instantiated. Or we need an
> > alternative implementation that does more reliable memory allocation
> > (since we're not assuming that the internal buffer is continuous).
> > Other ideas welcome.
> >
> > I think the problem is that the failure modes are not benign. I haven't been through all the use cases so this might not work, but perhaps using a statically-allocated string ("NOMEM" ?) as a sentinel value instead of null when malloc fails might be one way? Also, there might be some benefit in making String immutable a la Java - overloaded operators in C++ have a tendency to generate anonymous temporaries, which is going to lead to heap fragmentation as well.
> >
> > --
> > Alan Burlison
> > --
> >
> > _______________________________________________
___________________________________________________

Posted on the Developers mailing list. Go to http://arduino.cc/mailman/listinfo/developers_arduino.cc to subscribe. There seems to be a bug with the assignment operator, I'm on it and I'll get
back to you as soon as I get something done.

Thank you for your tests and feedback.


I'll do some tests on my own before I repost it here.

On Tue, Jan 4, 2011 at 6:53 PM, Rick Anderson
<>wrote:

> I just created a test and unpacked and tested it. I also created a
> test based on Tom's code. Not sure I caught the maximum value error
> for 0xFF.
>
> I also ran the tests for bug 411. All the tests compile, but there is
> still memory loss.
>
> I'm attaching the Arduino Test suite, and the test code so you can run
> them as you debug. Let me know if this was helpful.
>
> --Rick
>
> Test run results:
> Example: ATS_StringAssignmentTest.pde
> info.MANUFACTURER = Arduino
> info.CPU-NAME = ATmega328P
> info.GCC-Version = 4.3.2
> info.AVR-LibC-Ver = 1.6.4
> info.Compiled-date = Jan 4 2011
> info.Test-Suite-Name = ATS_StringAssignmentTest
> info.Free-memory = 1110 bytes
> Memory Usage (lost 59 bytes) ... FAIL
> --------------------------
> Ran 1 tests in 1.378s
>
> FAILED (failures=1)
>
>
> Example: ATS_StringMemoryTestPassByReference.pde
>
> info.MANUFACTURER = Arduino
> info.CPU-NAME = ATmega328P
> info.GCC-Version = 4.3.2
> info.AVR-LibC-Ver = 1.6.4
> info.Compiled-date = Jan 4 2011
> info.Test-Suite-Name = ATS_StringMemoryTestPassByReference
> info.Free-memory = 1120 bytes
> Memory Usage (lost 59 bytes) ... FAIL
> --------------------------
> Ran 1 tests in 1.389s
>
> FAILED (failures=1)
>
>
> Example: Tom Igoe Memory Test
> info.MANUFACTURER = Arduino
> info.CPU-NAME = ATmega328P
> info.GCC-Version = 4.3.2
> info.AVR-LibC-Ver = 1.6.4
> info.Compiled-date = Jan 4 2011
> info.Test-Suite-Name = Tom Igoe Memory Test
> info.Free-memory = 1328 bytes
> Memory Usage (lost 9 bytes) ... FAIL
> --------------------------
> Ran 1 tests in 1.374s
>
> FAILED (failures=1)
>
>
>
> --Rick
>
> Tom, rewrote your example as a test.
>
> //************************************************************************
> //* Arduino Tom Igoe Memory Test
> //* (C) 2010 by Rick Anderson
> //* Open source as per standard Arduino code
> //*
> //************************************************************************
> //* Jan 4, 2011 Started on Tom Igoe Memory Test
> //************************************************************************
>
> #include "WProgram.h"
> #include "HardwareSerial.h"
> #include
>
> //************************************************************************
> void setup()
> {
> int startMemoryUsage;
> /*
> * Create variable for the tests.
> */
>
> String webColor = "#000000";
>
> int red = 1023/4;
> int blue = 512/4;
> int green = 128/4;
>
> /*
> * initiate the test run
> */
> //Record starting memory amount
> startMemoryUsage = ATS_GetFreeMemory();
> //Begin test run
> ATS_begin("Arduino", "Tom Igoe Memory Test");
>
> webColor = "#";
> webColor += String(red, HEX);
> webColor += String(green, HEX);
> webColor += String(blue, HEX);
>
> ATS_ReportMemoryUsage(startMemoryUsage);
>
> /*
> * Test complete
> */
>
> ATS_end();
> }
>
>
> //************************************************************************
> void loop()
> {
>
>
> }
>
>
>
>
> On Mon, Jan 3, 2011 at 9:35 PM, Tom Igoe <> wrote:
> > It broke in the non-SDM version too, but it took longer to break. In the
> SDM version it breaks immediately. So it looks like whatever you did
> highlights the faults sooner, which is good. It also points to a need for an
> error response of some sort, in answer to your question last mail.
> >
> > t.
> >
> > On Jan 3, 2011, at 4:44 PM, Alexander Brevig wrote:
> >
> >> That breaking of String, does it only occur with the SDM version?
> >>
> >> If not, did you find any way to break it? Maybe any of the old faults
> related to memory?
> >>
> >>
> >> I actually have no time to check this myself right now, so I opted to
> just ask you.
> >>
> >> On Mon, Jan 3, 2011 at 10:35 PM, Tom Igoe <> wrote:
> >> Thanks, Alexander, and sorry for the delay.
> >>
> >> A few tests:
> >>
> >> For code that doesn't change the strings much, there's not a big
> difference, a couple dozen bytes' difference in code size. However, when
> you start to do dynamic things, it does add up. For example, the
> StringAppendOperator example is 4910 bytes in 0022, and 5148 bytes with the
> StaticDynamicMemory version. So it does start to take its toll, memory-wise.
> >>
> >> On some sketches it actually takes less memory. For example, the one
> below is 3738 bytes using the StaticDynamicMemory version, and 3986 bytes in
> 0022. However, it fails entirely on upload. When the value of (analog 0)/4
> is high (0xFF), it never gets out of the setup(). So there's still a pretty
> easy way to break String, even with these improvements.
> >>
> >>
> >> void setup() {
> >> Serial.begin(9600);
> >> Serial.println("Beginning");
> >> }
> >>
> >> void loop() {
> >>
> >> String webColor = "#";
> >>
> >> int red = analogRead(A0)/4;
> >> webColor += String(red, HEX);
> >> int green = analogRead(A1)/4;
> >> webColor += String(green, HEX);
> >> int blue = analogRead(A2)/4;
> >>
> >> webColor += String(blue, HEX);
> >> Serial.println(webColor);
> >> }
> >>
> >>
> >>
> >>
> >>
> >> On Dec 16, 2010, at 1:27 AM, Alexander Brevig wrote:
> >>
> >> > Attached is a zip containing WString.h and .cpp plus
> StaticDynamicMemory.h.
> >> > Take a backup of the original WString files, and extract this zip into
> the hardware/arduino/cores/arduino folder.
> >> >
> >> > Now you're ready to test the modified String library, that does not
> fragment the heap.
> >> >
> >> >
> >> > In the WString header there is a #define called STRING_BUFFER which is
> set to 100 for now, change this to suit your test needs.
> >> >
> >> >
> >> > No error handling is implemented, what do you think we need?
> >> >
> >> > I plan to add an availableMemory():int method to the SDM library, and
> maybe some error flags and checks like hasError():int error
> >> >
> >> > I also suspect that this library is a bit slower performance wise, but
> I think that's just a cost we'll have to pay to being able to play with
> dynamic strings.
> >> >
> >> >
> >> > Hope to get feedback from someone!
> >> >
> >> > On Thu, Dec 16, 2010 at 1:11 AM, Alan Burlison <
> > wrote:
> >> > On 15/12/2010 16:19, David A. Mellis wrote:
> >> >
> >> > I think you're right, but I also don't think that telling people to
> >> > use the standard C library functions is a solution either. Trying out
> >> > this String class seems like one way of pushing forwards towards a
> >> > compromise that provides both an easy-to-use API and a robust
> >> > implementation. For example, perhaps the buffer sizes need to be
> >> > specified or provided when the String is instantiated. Or we need an
> >> > alternative implementation that does more reliable memory allocation
> >> > (since we're not assuming that the internal buffer is continuous).
> >> > Other ideas welcome.
> >> >
> >> > I think the problem is that the failure modes are not benign. I
> haven't been through all the use cases so this might not work, but perhaps
> using a statically-allocated string ("NOMEM" ?) as a sentinel value instead
> of null when malloc fails might be one way? Also, there might be some
> benefit in making String immutable a la Java - overloaded operators in C++
> have a tendency to generate anonymous temporaries, which is going to lead to
> heap fragmentation as well.
> >> >
> >> > --
> >> > Alan Burlison
> >> > --
> >> >
> >> > _______________________________________________
___________________________________________________

Posted on the Developers mailing list. Go to http://arduino.cc/mailman/listinfo/developers_arduino.cc to subscribe. Is this test suite any different than the one in the github repo?

t.

On Jan 4, 2011, at 12:53 PM, Rick Anderson wrote:

> I just created a test and unpacked and tested it. I also created a
> test based on Tom's code. Not sure I caught the maximum value error
> for 0xFF.
>
> I also ran the tests for bug 411. All the tests compile, but there is
> still memory loss.
>
> I'm attaching the Arduino Test suite, and the test code so you can run
> them as you debug. Let me know if this was helpful.
>
> --Rick
>
> Test run results:
> Example: ATS_StringAssignmentTest.pde
> info.MANUFACTURER = Arduino
> info.CPU-NAME = ATmega328P
> info.GCC-Version = 4.3.2
> info.AVR-LibC-Ver = 1.6.4
> info.Compiled-date = Jan 4 2011
> info.Test-Suite-Name = ATS_StringAssignmentTest
> info.Free-memory = 1110 bytes
> Memory Usage (lost 59 bytes) ... FAIL
> --------------------------
> Ran 1 tests in 1.378s
>
> FAILED (failures=1)
>
>
> Example: ATS_StringMemoryTestPassByReference.pde
>
> info.MANUFACTURER = Arduino
> info.CPU-NAME = ATmega328P
> info.GCC-Version = 4.3.2
> info.AVR-LibC-Ver = 1.6.4
> info.Compiled-date = Jan 4 2011
> info.Test-Suite-Name = ATS_StringMemoryTestPassByReference
> info.Free-memory = 1120 bytes
> Memory Usage (lost 59 bytes) ... FAIL
> --------------------------
> Ran 1 tests in 1.389s
>
> FAILED (failures=1)
>
>
> Example: Tom Igoe Memory Test
> info.MANUFACTURER = Arduino
> info.CPU-NAME = ATmega328P
> info.GCC-Version = 4.3.2
> info.AVR-LibC-Ver = 1.6.4
> info.Compiled-date = Jan 4 2011
> info.Test-Suite-Name = Tom Igoe Memory Test
> info.Free-memory = 1328 bytes
> Memory Usage (lost 9 bytes) ... FAIL
> --------------------------
> Ran 1 tests in 1.374s
>
> FAILED (failures=1)
>
>
>
> --Rick
>
> Tom, rewrote your example as a test.
>
> //************************************************************************
> //* Arduino Tom Igoe Memory Test
> //* (C) 2010 by Rick Anderson
> //* Open source as per standard Arduino code
> //*
> //************************************************************************
> //* Jan 4, 2011 Started on Tom Igoe Memory Test
> //************************************************************************
>
> #include "WProgram.h"
> #include "HardwareSerial.h"
> #include
>
> //************************************************************************
> void setup()
> {
> int startMemoryUsage;
> /*
> * Create variable for the tests.
> */
>
> String webColor = "#000000";
>
> int red = 1023/4;
> int blue = 512/4;
> int green = 128/4;
>
> /*
> * initiate the test run
> */
> //Record starting memory amount
> startMemoryUsage = ATS_GetFreeMemory();
> //Begin test run
> ATS_begin("Arduino", "Tom Igoe Memory Test");
>
> webColor = "#";
> webColor += String(red, HEX);
> webColor += String(green, HEX);
> webColor += String(blue, HEX);
>
> ATS_ReportMemoryUsage(startMemoryUsage);
>
> /*
> * Test complete
> */
>
> ATS_end();
> }
>
>
> //************************************************************************
> void loop()
> {
>
>
> }
>
>
>
>
> On Mon, Jan 3, 2011 at 9:35 PM, Tom Igoe <> wrote:
>> It broke in the non-SDM version too, but it took longer to break. In the SDM version it breaks immediately. So it looks like whatever you did highlights the faults sooner, which is good. It also points to a need for an error response of some sort, in answer to your question last mail.
>>
>> t.
>>
>> On Jan 3, 2011, at 4:44 PM, Alexander Brevig wrote:
>>
>>> That breaking of String, does it only occur with the SDM version?
>>>
>>> If not, did you find any way to break it? Maybe any of the old faults related to memory?
>>>
>>>
>>> I actually have no time to check this myself right now, so I opted to just ask you.
>>>
>>> On Mon, Jan 3, 2011 at 10:35 PM, Tom Igoe <> wrote:
>>> Thanks, Alexander, and sorry for the delay.
>>>
>>> A few tests:
>>>
>>> For code that doesn't change the strings much, there's not a big difference, a couple dozen bytes' difference in code size. However, when you start to do dynamic things, it does add up. For example, the StringAppendOperator example is 4910 bytes in 0022, and 5148 bytes with the StaticDynamicMemory version. So it does start to take its toll, memory-wise.
>>>
>>> On some sketches it actually takes less memory. For example, the one below is 3738 bytes using the StaticDynamicMemory version, and 3986 bytes in 0022. However, it fails entirely on upload. When the value of (analog 0)/4 is high (0xFF), it never gets out of the setup(). So there's still a pretty easy way to break String, even with these improvements.
>>>
>>>
>>> void setup() {
>>> Serial.begin(9600);
>>> Serial.println("Beginning");
>>> }
>>>
>>> void loop() {
>>>
>>> String webColor = "#";
>>>
>>> int red = analogRead(A0)/4;
>>> webColor += String(red, HEX);
>>> int green = analogRead(A1)/4;
>>> webColor += String(green, HEX);
>>> int blue = analogRead(A2)/4;
>>>
>>> webColor += String(blue, HEX);
>>> Serial.println(webColor);
>>> }
>>>
>>>
>>>
>>>
>>>
>>> On Dec 16, 2010, at 1:27 AM, Alexander Brevig wrote:
>>>
>>>> Attached is a zip containing WString.h and .cpp plus StaticDynamicMemory.h.
>>>> Take a backup of the original WString files, and extract this zip into the hardware/arduino/cores/arduino folder.
>>>>
>>>> Now you're ready to test the modified String library, that does not fragment the heap.
>>>>
>>>>
>>>> In the WString header there is a #define called STRING_BUFFER which is set to 100 for now, change this to suit your test needs.
>>>>
>>>>
>>>> No error handling is implemented, what do you think we need?
>>>>
>>>> I plan to add an availableMemory():int method to the SDM library, and maybe some error flags and checks like hasError():int error
>>>>
>>>> I also suspect that this library is a bit slower performance wise, but I think that's just a cost we'll have to pay to being able to play with dynamic strings.
>>>>
>>>>
>>>> Hope to get feedback from someone!
>>>>
>>>> On Thu, Dec 16, 2010 at 1:11 AM, Alan Burlison <> wrote:
>>>> On 15/12/2010 16:19, David A. Mellis wrote:
>>>>
>>>> I think you're right, but I also don't think that telling people to
>>>> use the standard C library functions is a solution either. Trying out
>>>> this String class seems like one way of pushing forwards towards a
>>>> compromise that provides both an easy-to-use API and a robust
>>>> implementation. For example, perhaps the buffer sizes need to be
>>>> specified or provided when the String is instantiated. Or we need an
>>>> alternative implementation that does more reliable memory allocation
>>>> (since we're not assuming that the internal buffer is continuous).
>>>> Other ideas welcome.
>>>>
>>>> I think the problem is that the failure modes are not benign. I haven't been through all the use cases so this might not work, but perhaps using a statically-allocated string ("NOMEM" ?) as a sentinel value instead of null when malloc fails might be one way? Also, there might be some benefit in making String immutable a la Java - overloaded operators in C++ have a tendency to generate anonymous temporaries, which is going to lead to heap fragmentation as well.
>>>>
>>>> --
>>>> Alan Burlison
>>>> --
>>>>
>>>> _______________________________________________
___________________________________________________

Posted on the Developers mailing list. Go to http://arduino.cc/mailman/listinfo/developers_arduino.cc to subscribe. Same exact one. I just included it just in case.

--Rick

On Tue, Jan 4, 2011 at 9:01 PM, Tom Igoe <> wrote:
> Is this test suite any different than the one in the github repo?
>
> t.
>
> On Jan 4, 2011, at 12:53 PM, Rick Anderson wrote:
>
>> I just created a test and unpacked and tested it. I also created a
>> test based on Tom's code. Not sure I caught the maximum value error
>> for 0xFF.
>>
>> I also ran the tests for bug 411. All the tests compile, but there is
>> still memory loss.
>>
>> I'm attaching the Arduino Test suite, and the test code so you can run
>> them as you debug. Let me know if this was helpful.
>>
>> --Rick
>>
>> Test run results:
>> Example:  ATS_StringAssignmentTest.pde
>> info.MANUFACTURER    = Arduino
>> info.CPU-NAME        = ATmega328P
>> info.GCC-Version     = 4.3.2
>> info.AVR-LibC-Ver    = 1.6.4
>> info.Compiled-date   = Jan  4 2011
>> info.Test-Suite-Name = ATS_StringAssignmentTest
>> info.Free-memory     = 1110 bytes
>> Memory Usage (lost 59 bytes)                                ... FAIL
>> --------------------------
>> Ran 1 tests in 1.378s
>>
>> FAILED (failures=1)
>>
>>
>> Example: ATS_StringMemoryTestPassByReference.pde
>>
>> info.MANUFACTURER    = Arduino
>> info.CPU-NAME        = ATmega328P
>> info.GCC-Version     = 4.3.2
>> info.AVR-LibC-Ver    = 1.6.4
>> info.Compiled-date   = Jan  4 2011
>> info.Test-Suite-Name = ATS_StringMemoryTestPassByReference
>> info.Free-memory     = 1120 bytes
>> Memory Usage (lost 59 bytes)                                ... FAIL
>> --------------------------
>> Ran 1 tests in 1.389s
>>
>> FAILED (failures=1)
>>
>>
>> Example: Tom Igoe Memory Test
>> info.MANUFACTURER    = Arduino
>> info.CPU-NAME        = ATmega328P
>> info.GCC-Version     = 4.3.2
>> info.AVR-LibC-Ver    = 1.6.4
>> info.Compiled-date   = Jan  4 2011
>> info.Test-Suite-Name = Tom Igoe Memory Test
>> info.Free-memory     = 1328 bytes
>> Memory Usage (lost 9 bytes)                                 ... FAIL
>> --------------------------
>> Ran 1 tests in 1.374s
>>
>> FAILED (failures=1)
>>
>>
>>
>> --Rick
>>
>> Tom, rewrote your example as a test.
>>
>> //************************************************************************
>> //*   Arduino Tom Igoe Memory Test
>> //*           (C) 2010 by Rick Anderson
>> //*           Open source as per standard Arduino code
>> //*
>> //************************************************************************
>> //*   Jan 4,  2011     Started on Tom Igoe Memory Test
>> //************************************************************************
>>
>> #include      "WProgram.h"
>> #include      "HardwareSerial.h"
>> #include      
>>
>> //************************************************************************
>> void setup()
>> {
>>  int          startMemoryUsage;
>>  /*
>>    * Create variable for the tests.
>>   */
>>
>>  String webColor = "#000000";
>>
>>  int red = 1023/4;
>>  int blue = 512/4;
>>  int green = 128/4;
>>
>>  /*
>>  * initiate the test run
>>   */
>>  //Record starting memory amount
>>  startMemoryUsage     =       ATS_GetFreeMemory();
>>  //Begin test run
>>  ATS_begin("Arduino", "Tom Igoe Memory Test");
>>
>>  webColor = "#";
>>  webColor += String(red, HEX);
>>  webColor += String(green, HEX);
>>  webColor += String(blue, HEX);
>>
>>  ATS_ReportMemoryUsage(startMemoryUsage);
>>
>>  /*
>>   * Test complete
>>   */
>>
>>  ATS_end();
>> }
>>
>>
>> //************************************************************************
>> void loop()
>> {
>>
>>
>> }
>>
>>
>>
>>
>> On Mon, Jan 3, 2011 at 9:35 PM, Tom Igoe <> wrote:
>>> It broke in the non-SDM version too, but it took longer to break. In the SDM version it breaks immediately. So it looks like whatever you did highlights the faults sooner, which is good. It also points to a need for an error response of some sort, in answer to your question last mail.
>>>
>>> t.
>>>
>>> On Jan 3, 2011, at 4:44 PM, Alexander Brevig wrote:
>>>
>>>> That breaking of String, does it only occur with the SDM version?
>>>>
>>>> If not, did you find any way to break it? Maybe any of the old faults related to memory?
>>>>
>>>>
>>>> I actually have no time to check this myself right now, so I opted to just ask you.
>>>>
>>>> On Mon, Jan 3, 2011 at 10:35 PM, Tom Igoe <> wrote:
>>>> Thanks, Alexander, and sorry for the delay.
>>>>
>>>> A few tests:
>>>>
>>>> For code that doesn't change the strings much, there's not a big difference, a couple dozen bytes' difference in code size.  However, when you start to do dynamic things, it does add up.  For example, the StringAppendOperator example is  4910 bytes in 0022, and 5148 bytes with the StaticDynamicMemory version. So it does start to take its toll, memory-wise.
>>>>
>>>> On some sketches it actually takes less memory.  For example, the one below is 3738 bytes using the StaticDynamicMemory version, and 3986 bytes in 0022.  However, it fails entirely on upload.  When the value of (analog 0)/4 is high (0xFF), it never gets out of the setup(). So there's still a pretty easy way to break String, even with these improvements.
>>>>
>>>>
>>>> void setup() {
>>>>  Serial.begin(9600);
>>>>  Serial.println("Beginning");
>>>> }
>>>>
>>>> void loop() {
>>>>
>>>>  String webColor = "#";
>>>>
>>>>  int red = analogRead(A0)/4;
>>>>  webColor += String(red, HEX);
>>>>  int green = analogRead(A1)/4;
>>>>  webColor += String(green, HEX);
>>>>  int blue = analogRead(A2)/4;
>>>>
>>>>  webColor += String(blue, HEX);
>>>>  Serial.println(webColor);
>>>> }
>>>>
>>>>
>>>>
>>>>
>>>>
>>>> On Dec 16, 2010, at 1:27 AM, Alexander Brevig wrote:
>>>>
>>>>> Attached is a zip containing WString.h and .cpp plus StaticDynamicMemory.h.
>>>>> Take a backup of the original WString files, and extract this zip into the hardware/arduino/cores/arduino folder.
>>>>>
>>>>> Now you're ready to test the modified String library, that does not fragment the heap.
>>>>>
>>>>>
>>>>> In the WString header there is a #define called STRING_BUFFER which is set to 100 for now, change this to suit your test needs.
>>>>>
>>>>>
>>>>> No error handling is implemented, what do you think we need?
>>>>>
>>>>> I plan to add an availableMemory():int method to the SDM library, and maybe some error flags and checks like hasError():int error
>>>>>
>>>>> I also suspect that this library is a bit slower performance wise, but I think that's just a cost we'll have to pay to being able to play with dynamic strings.
>>>>>
>>>>>
>>>>> Hope to  get feedback from someone!
>>>>>
>>>>> On Thu, Dec 16, 2010 at 1:11 AM, Alan Burlison <> wrote:
>>>>> On 15/12/2010 16:19, David A. Mellis wrote:
>>>>>
>>>>> I think you're right, but I also don't think that telling people to
>>>>> use the standard C library functions is a solution either.  Trying out
>>>>> this String class seems like one way of pushing forwards towards a
>>>>> compromise that provides both an easy-to-use API and a robust
>>>>> implementation.  For example, perhaps the buffer sizes need to be
>>>>> specified or provided when the String is instantiated.  Or we need an
>>>>> alternative implementation that does more reliable memory allocation
>>>>> (since we're not assuming that the internal buffer is continuous).
>>>>> Other ideas welcome.
>>>>>
>>>>> I think the problem is that the failure modes are not benign.  I haven't been through all the use cases so this might not work, but perhaps using a statically-allocated string ("NOMEM" ?) as a sentinel value instead of null when malloc fails might be one way?  Also, there might be some benefit in making String immutable a la Java - overloaded operators in C++ have a tendency to generate anonymous temporaries, which is going to lead to heap fragmentation as well.
>>>>>
>>>>> --
>>>>> Alan Burlison
>>>>> --
>>>>>
>>>>> _______________________________________________
___________________________________________________

Posted on the Developers mailing list. Go to http://arduino.cc/mailman/listinfo/developers_arduino.cc to subscribe. On 04/01/2011 17:53, Rick Anderson wrote:

> I also ran the tests for bug 411. All the tests compile, but there is
> still memory loss.

Most of the assumptions made by the test harness and test case code are
wrong, any reports of 'lost' memory are therefore likely to be wrong as
well. If you want to do leak detection you can't do it in the naive way
it is being done at present.

--
Alan Burlison
--

_______________________________________________
___________________________________________________

Posted on the Developers mailing list. Go to http://arduino.cc/mailman/listinfo/developers_arduino.cc to subscribe. Alan,

The tests themselves are quick and dirty, and not strategic or
comprehensive. I'd like your input to create a good procedure for
memory testing. I also have feedback from Paul Stoffregen for the test
suite:
----
Another problem involves gcc's optimizer ignoring the inline request
for ATS_ReportMemoryUsage. As the comment in the code explains, it
must be inline to avoid measuring its own stack frame. I believe
adding this line in ArduinoTestSuite.h fixes the problem by forcing
gcc to inline.

inline void ATS_ReportMemoryUsage(int _memoryUsageAtStart)
__attribute__((always_inline, unused));

The last problem is a tiny bit of dynamic memory permanently held for
the free list. To allow for this, the test really should call
malloc() and free() once, so the allocator is fully initialized before
testing.
----

I'd like to combine both sets of feedback, and set up some issues in
the system, then fix them. Is the above the problem you saw? Are their
other assumptions that would impact measuring memory? And updating the
memory test in the the test suite.

In terms of creating tests for memory leaks. It looks best to move all
the memory usage inside a function. What else could be done to
constrain the problem, and measuring more affectively.

I'm traveling back to NJ today, so I can't respond right away.

--Rick

On Wed, Jan 5, 2011 at 8:52 AM, Alan Burlison <> wrote:
> On 04/01/2011 17:53, Rick Anderson wrote:
>
>> I also ran the tests for bug 411. All the tests compile, but there is
>> still memory loss.
>
> Most of the assumptions made by the test harness and test case code are
> wrong, any reports of 'lost' memory are therefore likely to be wrong as
> well.  If you want to do leak detection you can't do it in the naive way it
> is being done at present.
>
> --
> Alan Burlison
> --
>



--
President
Fair Use Building and Research (****) Labs
http://fubarlabs.org

_______________________________________________
___________________________________________________

Posted on the Developers mailing list. Go to http://arduino.cc/mailman/listinfo/developers_arduino.cc to subscribe.

  #8  
05-01-2011 06:10 PM
Developers member admin is online now
User
 

That breaking of String, does it only occur with the SDM version?

If not, did you find any way to break it? Maybe any of the old faults
related to memory?


I actually have no time to check this myself right now, so I opted to just
ask you.

On Mon, Jan 3, 2011 at 10:35 PM, Tom Igoe <> wrote:

> Thanks, Alexander, and sorry for the delay.
>
> A few tests:
>
> For code that doesn't change the strings much, there's not a big
> difference, a couple dozen bytes' difference in code size. However, when
> you start to do dynamic things, it does add up. For example, the
> StringAppendOperator example is 4910 bytes in 0022, and 5148 bytes with the
> StaticDynamicMemory version. So it does start to take its toll, memory-wise.
>
> On some sketches it actually takes less memory. For example, the one below
> is 3738 bytes using the StaticDynamicMemory version, and 3986 bytes in 0022.
> However, it fails entirely on upload. When the value of (analog 0)/4 is
> high (0xFF), it never gets out of the setup(). So there's still a pretty
> easy way to break String, even with these improvements.
>
>
> void setup() {
> Serial.begin(9600);
> Serial.println("Beginning");
> }
>
> void loop() {
>
> String webColor = "#";
>
> int red = analogRead(A0)/4;
> webColor += String(red, HEX);
> int green = analogRead(A1)/4;
> webColor += String(green, HEX);
> int blue = analogRead(A2)/4;
>
> webColor += String(blue, HEX);
> Serial.println(webColor);
> }
>
>
>
>
>
> On Dec 16, 2010, at 1:27 AM, Alexander Brevig wrote:
>
> > Attached is a zip containing WString.h and .cpp plus
> StaticDynamicMemory.h.
> > Take a backup of the original WString files, and extract this zip into
> the hardware/arduino/cores/arduino folder.
> >
> > Now you're ready to test the modified String library, that does not
> fragment the heap.
> >
> >
> > In the WString header there is a #define called STRING_BUFFER which is
> set to 100 for now, change this to suit your test needs.
> >
> >
> > No error handling is implemented, what do you think we need?
> >
> > I plan to add an availableMemory():int method to the SDM library, and
> maybe some error flags and checks like hasError():int error
> >
> > I also suspect that this library is a bit slower performance wise, but I
> think that's just a cost we'll have to pay to being able to play with
> dynamic strings.
> >
> >
> > Hope to get feedback from someone!
> >
> > On Thu, Dec 16, 2010 at 1:11 AM, Alan Burlison <>
> wrote:
> > On 15/12/2010 16:19, David A. Mellis wrote:
> >
> > I think you're right, but I also don't think that telling people to
> > use the standard C library functions is a solution either. Trying out
> > this String class seems like one way of pushing forwards towards a
> > compromise that provides both an easy-to-use API and a robust
> > implementation. For example, perhaps the buffer sizes need to be
> > specified or provided when the String is instantiated. Or we need an
> > alternative implementation that does more reliable memory allocation
> > (since we're not assuming that the internal buffer is continuous).
> > Other ideas welcome.
> >
> > I think the problem is that the failure modes are not benign. I haven't
> been through all the use cases so this might not work, but perhaps using a
> statically-allocated string ("NOMEM" ?) as a sentinel value instead of null
> when malloc fails might be one way? Also, there might be some benefit in
> making String immutable a la Java - overloaded operators in C++ have a
> tendency to generate anonymous temporaries, which is going to lead to heap
> fragmentation as well.
> >
> > --
> > Alan Burlison
> > --
> >
> > _______________________________________________
___________________________________________________

Posted on the Developers mailing list. Go to http://arduino.cc/mailman/listinfo/developers_arduino.cc to subscribe. It broke in the non-SDM version too, but it took longer to break. In the SDM version it breaks immediately. So it looks like whatever you did highlights the faults sooner, which is good. It also points to a need for an error response of some sort, in answer to your question last mail.

t.

On Jan 3, 2011, at 4:44 PM, Alexander Brevig wrote:

> That breaking of String, does it only occur with the SDM version?
>
> If not, did you find any way to break it? Maybe any of the old faults related to memory?
>
>
> I actually have no time to check this myself right now, so I opted to just ask you.
>
> On Mon, Jan 3, 2011 at 10:35 PM, Tom Igoe <> wrote:
> Thanks, Alexander, and sorry for the delay.
>
> A few tests:
>
> For code that doesn't change the strings much, there's not a big difference, a couple dozen bytes' difference in code size. However, when you start to do dynamic things, it does add up. For example, the StringAppendOperator example is 4910 bytes in 0022, and 5148 bytes with the StaticDynamicMemory version. So it does start to take its toll, memory-wise.
>
> On some sketches it actually takes less memory. For example, the one below is 3738 bytes using the StaticDynamicMemory version, and 3986 bytes in 0022. However, it fails entirely on upload. When the value of (analog 0)/4 is high (0xFF), it never gets out of the setup(). So there's still a pretty easy way to break String, even with these improvements.
>
>
> void setup() {
> Serial.begin(9600);
> Serial.println("Beginning");
> }
>
> void loop() {
>
> String webColor = "#";
>
> int red = analogRead(A0)/4;
> webColor += String(red, HEX);
> int green = analogRead(A1)/4;
> webColor += String(green, HEX);
> int blue = analogRead(A2)/4;
>
> webColor += String(blue, HEX);
> Serial.println(webColor);
> }
>
>
>
>
>
> On Dec 16, 2010, at 1:27 AM, Alexander Brevig wrote:
>
> > Attached is a zip containing WString.h and .cpp plus StaticDynamicMemory.h.
> > Take a backup of the original WString files, and extract this zip into the hardware/arduino/cores/arduino folder.
> >
> > Now you're ready to test the modified String library, that does not fragment the heap.
> >
> >
> > In the WString header there is a #define called STRING_BUFFER which is set to 100 for now, change this to suit your test needs.
> >
> >
> > No error handling is implemented, what do you think we need?
> >
> > I plan to add an availableMemory():int method to the SDM library, and maybe some error flags and checks like hasError():int error
> >
> > I also suspect that this library is a bit slower performance wise, but I think that's just a cost we'll have to pay to being able to play with dynamic strings.
> >
> >
> > Hope to get feedback from someone!
> >
> > On Thu, Dec 16, 2010 at 1:11 AM, Alan Burlison <> wrote:
> > On 15/12/2010 16:19, David A. Mellis wrote:
> >
> > I think you're right, but I also don't think that telling people to
> > use the standard C library functions is a solution either. Trying out
> > this String class seems like one way of pushing forwards towards a
> > compromise that provides both an easy-to-use API and a robust
> > implementation. For example, perhaps the buffer sizes need to be
> > specified or provided when the String is instantiated. Or we need an
> > alternative implementation that does more reliable memory allocation
> > (since we're not assuming that the internal buffer is continuous).
> > Other ideas welcome.
> >
> > I think the problem is that the failure modes are not benign. I haven't been through all the use cases so this might not work, but perhaps using a statically-allocated string ("NOMEM" ?) as a sentinel value instead of null when malloc fails might be one way? Also, there might be some benefit in making String immutable a la Java - overloaded operators in C++ have a tendency to generate anonymous temporaries, which is going to lead to heap fragmentation as well.
> >
> > --
> > Alan Burlison
> > --
> >
> > _______________________________________________
___________________________________________________

Posted on the Developers mailing list. Go to http://arduino.cc/mailman/listinfo/developers_arduino.cc to subscribe. There seems to be a bug with the assignment operator, I'm on it and I'll get
back to you as soon as I get something done.

Thank you for your tests and feedback.


I'll do some tests on my own before I repost it here.

On Tue, Jan 4, 2011 at 6:53 PM, Rick Anderson
<>wrote:

> I just created a test and unpacked and tested it. I also created a
> test based on Tom's code. Not sure I caught the maximum value error
> for 0xFF.
>
> I also ran the tests for bug 411. All the tests compile, but there is
> still memory loss.
>
> I'm attaching the Arduino Test suite, and the test code so you can run
> them as you debug. Let me know if this was helpful.
>
> --Rick
>
> Test run results:
> Example: ATS_StringAssignmentTest.pde
> info.MANUFACTURER = Arduino
> info.CPU-NAME = ATmega328P
> info.GCC-Version = 4.3.2
> info.AVR-LibC-Ver = 1.6.4
> info.Compiled-date = Jan 4 2011
> info.Test-Suite-Name = ATS_StringAssignmentTest
> info.Free-memory = 1110 bytes
> Memory Usage (lost 59 bytes) ... FAIL
> --------------------------
> Ran 1 tests in 1.378s
>
> FAILED (failures=1)
>
>
> Example: ATS_StringMemoryTestPassByReference.pde
>
> info.MANUFACTURER = Arduino
> info.CPU-NAME = ATmega328P
> info.GCC-Version = 4.3.2
> info.AVR-LibC-Ver = 1.6.4
> info.Compiled-date = Jan 4 2011
> info.Test-Suite-Name = ATS_StringMemoryTestPassByReference
> info.Free-memory = 1120 bytes
> Memory Usage (lost 59 bytes) ... FAIL
> --------------------------
> Ran 1 tests in 1.389s
>
> FAILED (failures=1)
>
>
> Example: Tom Igoe Memory Test
> info.MANUFACTURER = Arduino
> info.CPU-NAME = ATmega328P
> info.GCC-Version = 4.3.2
> info.AVR-LibC-Ver = 1.6.4
> info.Compiled-date = Jan 4 2011
> info.Test-Suite-Name = Tom Igoe Memory Test
> info.Free-memory = 1328 bytes
> Memory Usage (lost 9 bytes) ... FAIL
> --------------------------
> Ran 1 tests in 1.374s
>
> FAILED (failures=1)
>
>
>
> --Rick
>
> Tom, rewrote your example as a test.
>
> //************************************************************************
> //* Arduino Tom Igoe Memory Test
> //* (C) 2010 by Rick Anderson
> //* Open source as per standard Arduino code
> //*
> //************************************************************************
> //* Jan 4, 2011 Started on Tom Igoe Memory Test
> //************************************************************************
>
> #include "WProgram.h"
> #include "HardwareSerial.h"
> #include
>
> //************************************************************************
> void setup()
> {
> int startMemoryUsage;
> /*
> * Create variable for the tests.
> */
>
> String webColor = "#000000";
>
> int red = 1023/4;
> int blue = 512/4;
> int green = 128/4;
>
> /*
> * initiate the test run
> */
> //Record starting memory amount
> startMemoryUsage = ATS_GetFreeMemory();
> //Begin test run
> ATS_begin("Arduino", "Tom Igoe Memory Test");
>
> webColor = "#";
> webColor += String(red, HEX);
> webColor += String(green, HEX);
> webColor += String(blue, HEX);
>
> ATS_ReportMemoryUsage(startMemoryUsage);
>
> /*
> * Test complete
> */
>
> ATS_end();
> }
>
>
> //************************************************************************
> void loop()
> {
>
>
> }
>
>
>
>
> On Mon, Jan 3, 2011 at 9:35 PM, Tom Igoe <> wrote:
> > It broke in the non-SDM version too, but it took longer to break. In the
> SDM version it breaks immediately. So it looks like whatever you did
> highlights the faults sooner, which is good. It also points to a need for an
> error response of some sort, in answer to your question last mail.
> >
> > t.
> >
> > On Jan 3, 2011, at 4:44 PM, Alexander Brevig wrote:
> >
> >> That breaking of String, does it only occur with the SDM version?
> >>
> >> If not, did you find any way to break it? Maybe any of the old faults
> related to memory?
> >>
> >>
> >> I actually have no time to check this myself right now, so I opted to
> just ask you.
> >>
> >> On Mon, Jan 3, 2011 at 10:35 PM, Tom Igoe <> wrote:
> >> Thanks, Alexander, and sorry for the delay.
> >>
> >> A few tests:
> >>
> >> For code that doesn't change the strings much, there's not a big
> difference, a couple dozen bytes' difference in code size. However, when
> you start to do dynamic things, it does add up. For example, the
> StringAppendOperator example is 4910 bytes in 0022, and 5148 bytes with the
> StaticDynamicMemory version. So it does start to take its toll, memory-wise.
> >>
> >> On some sketches it actually takes less memory. For example, the one
> below is 3738 bytes using the StaticDynamicMemory version, and 3986 bytes in
> 0022. However, it fails entirely on upload. When the value of (analog 0)/4
> is high (0xFF), it never gets out of the setup(). So there's still a pretty
> easy way to break String, even with these improvements.
> >>
> >>
> >> void setup() {
> >> Serial.begin(9600);
> >> Serial.println("Beginning");
> >> }
> >>
> >> void loop() {
> >>
> >> String webColor = "#";
> >>
> >> int red = analogRead(A0)/4;
> >> webColor += String(red, HEX);
> >> int green = analogRead(A1)/4;
> >> webColor += String(green, HEX);
> >> int blue = analogRead(A2)/4;
> >>
> >> webColor += String(blue, HEX);
> >> Serial.println(webColor);
> >> }
> >>
> >>
> >>
> >>
> >>
> >> On Dec 16, 2010, at 1:27 AM, Alexander Brevig wrote:
> >>
> >> > Attached is a zip containing WString.h and .cpp plus
> StaticDynamicMemory.h.
> >> > Take a backup of the original WString files, and extract this zip into
> the hardware/arduino/cores/arduino folder.
> >> >
> >> > Now you're ready to test the modified String library, that does not
> fragment the heap.
> >> >
> >> >
> >> > In the WString header there is a #define called STRING_BUFFER which is
> set to 100 for now, change this to suit your test needs.
> >> >
> >> >
> >> > No error handling is implemented, what do you think we need?
> >> >
> >> > I plan to add an availableMemory():int method to the SDM library, and
> maybe some error flags and checks like hasError():int error
> >> >
> >> > I also suspect that this library is a bit slower performance wise, but
> I think that's just a cost we'll have to pay to being able to play with
> dynamic strings.
> >> >
> >> >
> >> > Hope to get feedback from someone!
> >> >
> >> > On Thu, Dec 16, 2010 at 1:11 AM, Alan Burlison <
> > wrote:
> >> > On 15/12/2010 16:19, David A. Mellis wrote:
> >> >
> >> > I think you're right, but I also don't think that telling people to
> >> > use the standard C library functions is a solution either. Trying out
> >> > this String class seems like one way of pushing forwards towards a
> >> > compromise that provides both an easy-to-use API and a robust
> >> > implementation. For example, perhaps the buffer sizes need to be
> >> > specified or provided when the String is instantiated. Or we need an
> >> > alternative implementation that does more reliable memory allocation
> >> > (since we're not assuming that the internal buffer is continuous).
> >> > Other ideas welcome.
> >> >
> >> > I think the problem is that the failure modes are not benign. I
> haven't been through all the use cases so this might not work, but perhaps
> using a statically-allocated string ("NOMEM" ?) as a sentinel value instead
> of null when malloc fails might be one way? Also, there might be some
> benefit in making String immutable a la Java - overloaded operators in C++
> have a tendency to generate anonymous temporaries, which is going to lead to
> heap fragmentation as well.
> >> >
> >> > --
> >> > Alan Burlison
> >> > --
> >> >
> >> > _______________________________________________
___________________________________________________

Posted on the Developers mailing list. Go to http://arduino.cc/mailman/listinfo/developers_arduino.cc to subscribe. Is this test suite any different than the one in the github repo?

t.

On Jan 4, 2011, at 12:53 PM, Rick Anderson wrote:

> I just created a test and unpacked and tested it. I also created a
> test based on Tom's code. Not sure I caught the maximum value error
> for 0xFF.
>
> I also ran the tests for bug 411. All the tests compile, but there is
> still memory loss.
>
> I'm attaching the Arduino Test suite, and the test code so you can run
> them as you debug. Let me know if this was helpful.
>
> --Rick
>
> Test run results:
> Example: ATS_StringAssignmentTest.pde
> info.MANUFACTURER = Arduino
> info.CPU-NAME = ATmega328P
> info.GCC-Version = 4.3.2
> info.AVR-LibC-Ver = 1.6.4
> info.Compiled-date = Jan 4 2011
> info.Test-Suite-Name = ATS_StringAssignmentTest
> info.Free-memory = 1110 bytes
> Memory Usage (lost 59 bytes) ... FAIL
> --------------------------
> Ran 1 tests in 1.378s
>
> FAILED (failures=1)
>
>
> Example: ATS_StringMemoryTestPassByReference.pde
>
> info.MANUFACTURER = Arduino
> info.CPU-NAME = ATmega328P
> info.GCC-Version = 4.3.2
> info.AVR-LibC-Ver = 1.6.4
> info.Compiled-date = Jan 4 2011
> info.Test-Suite-Name = ATS_StringMemoryTestPassByReference
> info.Free-memory = 1120 bytes
> Memory Usage (lost 59 bytes) ... FAIL
> --------------------------
> Ran 1 tests in 1.389s
>
> FAILED (failures=1)
>
>
> Example: Tom Igoe Memory Test
> info.MANUFACTURER = Arduino
> info.CPU-NAME = ATmega328P
> info.GCC-Version = 4.3.2
> info.AVR-LibC-Ver = 1.6.4
> info.Compiled-date = Jan 4 2011
> info.Test-Suite-Name = Tom Igoe Memory Test
> info.Free-memory = 1328 bytes
> Memory Usage (lost 9 bytes) ... FAIL
> --------------------------
> Ran 1 tests in 1.374s
>
> FAILED (failures=1)
>
>
>
> --Rick
>
> Tom, rewrote your example as a test.
>
> //************************************************************************
> //* Arduino Tom Igoe Memory Test
> //* (C) 2010 by Rick Anderson
> //* Open source as per standard Arduino code
> //*
> //************************************************************************
> //* Jan 4, 2011 Started on Tom Igoe Memory Test
> //************************************************************************
>
> #include "WProgram.h"
> #include "HardwareSerial.h"
> #include
>
> //************************************************************************
> void setup()
> {
> int startMemoryUsage;
> /*
> * Create variable for the tests.
> */
>
> String webColor = "#000000";
>
> int red = 1023/4;
> int blue = 512/4;
> int green = 128/4;
>
> /*
> * initiate the test run
> */
> //Record starting memory amount
> startMemoryUsage = ATS_GetFreeMemory();
> //Begin test run
> ATS_begin("Arduino", "Tom Igoe Memory Test");
>
> webColor = "#";
> webColor += String(red, HEX);
> webColor += String(green, HEX);
> webColor += String(blue, HEX);
>
> ATS_ReportMemoryUsage(startMemoryUsage);
>
> /*
> * Test complete
> */
>
> ATS_end();
> }
>
>
> //************************************************************************
> void loop()
> {
>
>
> }
>
>
>
>
> On Mon, Jan 3, 2011 at 9:35 PM, Tom Igoe <> wrote:
>> It broke in the non-SDM version too, but it took longer to break. In the SDM version it breaks immediately. So it looks like whatever you did highlights the faults sooner, which is good. It also points to a need for an error response of some sort, in answer to your question last mail.
>>
>> t.
>>
>> On Jan 3, 2011, at 4:44 PM, Alexander Brevig wrote:
>>
>>> That breaking of String, does it only occur with the SDM version?
>>>
>>> If not, did you find any way to break it? Maybe any of the old faults related to memory?
>>>
>>>
>>> I actually have no time to check this myself right now, so I opted to just ask you.
>>>
>>> On Mon, Jan 3, 2011 at 10:35 PM, Tom Igoe <> wrote:
>>> Thanks, Alexander, and sorry for the delay.
>>>
>>> A few tests:
>>>
>>> For code that doesn't change the strings much, there's not a big difference, a couple dozen bytes' difference in code size. However, when you start to do dynamic things, it does add up. For example, the StringAppendOperator example is 4910 bytes in 0022, and 5148 bytes with the StaticDynamicMemory version. So it does start to take its toll, memory-wise.
>>>
>>> On some sketches it actually takes less memory. For example, the one below is 3738 bytes using the StaticDynamicMemory version, and 3986 bytes in 0022. However, it fails entirely on upload. When the value of (analog 0)/4 is high (0xFF), it never gets out of the setup(). So there's still a pretty easy way to break String, even with these improvements.
>>>
>>>
>>> void setup() {
>>> Serial.begin(9600);
>>> Serial.println("Beginning");
>>> }
>>>
>>> void loop() {
>>>
>>> String webColor = "#";
>>>
>>> int red = analogRead(A0)/4;
>>> webColor += String(red, HEX);
>>> int green = analogRead(A1)/4;
>>> webColor += String(green, HEX);
>>> int blue = analogRead(A2)/4;
>>>
>>> webColor += String(blue, HEX);
>>> Serial.println(webColor);
>>> }
>>>
>>>
>>>
>>>
>>>
>>> On Dec 16, 2010, at 1:27 AM, Alexander Brevig wrote:
>>>
>>>> Attached is a zip containing WString.h and .cpp plus StaticDynamicMemory.h.
>>>> Take a backup of the original WString files, and extract this zip into the hardware/arduino/cores/arduino folder.
>>>>
>>>> Now you're ready to test the modified String library, that does not fragment the heap.
>>>>
>>>>
>>>> In the WString header there is a #define called STRING_BUFFER which is set to 100 for now, change this to suit your test needs.
>>>>
>>>>
>>>> No error handling is implemented, what do you think we need?
>>>>
>>>> I plan to add an availableMemory():int method to the SDM library, and maybe some error flags and checks like hasError():int error
>>>>
>>>> I also suspect that this library is a bit slower performance wise, but I think that's just a cost we'll have to pay to being able to play with dynamic strings.
>>>>
>>>>
>>>> Hope to get feedback from someone!
>>>>
>>>> On Thu, Dec 16, 2010 at 1:11 AM, Alan Burlison <> wrote:
>>>> On 15/12/2010 16:19, David A. Mellis wrote:
>>>>
>>>> I think you're right, but I also don't think that telling people to
>>>> use the standard C library functions is a solution either. Trying out
>>>> this String class seems like one way of pushing forwards towards a
>>>> compromise that provides both an easy-to-use API and a robust
>>>> implementation. For example, perhaps the buffer sizes need to be
>>>> specified or provided when the String is instantiated. Or we need an
>>>> alternative implementation that does more reliable memory allocation
>>>> (since we're not assuming that the internal buffer is continuous).
>>>> Other ideas welcome.
>>>>
>>>> I think the problem is that the failure modes are not benign. I haven't been through all the use cases so this might not work, but perhaps using a statically-allocated string ("NOMEM" ?) as a sentinel value instead of null when malloc fails might be one way? Also, there might be some benefit in making String immutable a la Java - overloaded operators in C++ have a tendency to generate anonymous temporaries, which is going to lead to heap fragmentation as well.
>>>>
>>>> --
>>>> Alan Burlison
>>>> --
>>>>
>>>> _______________________________________________
___________________________________________________

Posted on the Developers mailing list. Go to http://arduino.cc/mailman/listinfo/developers_arduino.cc to subscribe. Same exact one. I just included it just in case.

--Rick

On Tue, Jan 4, 2011 at 9:01 PM, Tom Igoe <> wrote:
> Is this test suite any different than the one in the github repo?
>
> t.
>
> On Jan 4, 2011, at 12:53 PM, Rick Anderson wrote:
>
>> I just created a test and unpacked and tested it. I also created a
>> test based on Tom's code. Not sure I caught the maximum value error
>> for 0xFF.
>>
>> I also ran the tests for bug 411. All the tests compile, but there is
>> still memory loss.
>>
>> I'm attaching the Arduino Test suite, and the test code so you can run
>> them as you debug. Let me know if this was helpful.
>>
>> --Rick
>>
>> Test run results:
>> Example:  ATS_StringAssignmentTest.pde
>> info.MANUFACTURER    = Arduino
>> info.CPU-NAME        = ATmega328P
>> info.GCC-Version     = 4.3.2
>> info.AVR-LibC-Ver    = 1.6.4
>> info.Compiled-date   = Jan  4 2011
>> info.Test-Suite-Name = ATS_StringAssignmentTest
>> info.Free-memory     = 1110 bytes
>> Memory Usage (lost 59 bytes)                                ... FAIL
>> --------------------------
>> Ran 1 tests in 1.378s
>>
>> FAILED (failures=1)
>>
>>
>> Example: ATS_StringMemoryTestPassByReference.pde
>>
>> info.MANUFACTURER    = Arduino
>> info.CPU-NAME        = ATmega328P
>> info.GCC-Version     = 4.3.2
>> info.AVR-LibC-Ver    = 1.6.4
>> info.Compiled-date   = Jan  4 2011
>> info.Test-Suite-Name = ATS_StringMemoryTestPassByReference
>> info.Free-memory     = 1120 bytes
>> Memory Usage (lost 59 bytes)                                ... FAIL
>> --------------------------
>> Ran 1 tests in 1.389s
>>
>> FAILED (failures=1)
>>
>>
>> Example: Tom Igoe Memory Test
>> info.MANUFACTURER    = Arduino
>> info.CPU-NAME        = ATmega328P
>> info.GCC-Version     = 4.3.2
>> info.AVR-LibC-Ver    = 1.6.4
>> info.Compiled-date   = Jan  4 2011
>> info.Test-Suite-Name = Tom Igoe Memory Test
>> info.Free-memory     = 1328 bytes
>> Memory Usage (lost 9 bytes)                                 ... FAIL
>> --------------------------
>> Ran 1 tests in 1.374s
>>
>> FAILED (failures=1)
>>
>>
>>
>> --Rick
>>
>> Tom, rewrote your example as a test.
>>
>> //************************************************************************
>> //*   Arduino Tom Igoe Memory Test
>> //*           (C) 2010 by Rick Anderson
>> //*           Open source as per standard Arduino code
>> //*
>> //************************************************************************
>> //*   Jan 4,  2011     Started on Tom Igoe Memory Test
>> //************************************************************************
>>
>> #include      "WProgram.h"
>> #include      "HardwareSerial.h"
>> #include      
>>
>> //************************************************************************
>> void setup()
>> {
>>  int          startMemoryUsage;
>>  /*
>>    * Create variable for the tests.
>>   */
>>
>>  String webColor = "#000000";
>>
>>  int red = 1023/4;
>>  int blue = 512/4;
>>  int green = 128/4;
>>
>>  /*
>>  * initiate the test run
>>   */
>>  //Record starting memory amount
>>  startMemoryUsage     =       ATS_GetFreeMemory();
>>  //Begin test run
>>  ATS_begin("Arduino", "Tom Igoe Memory Test");
>>
>>  webColor = "#";
>>  webColor += String(red, HEX);
>>  webColor += String(green, HEX);
>>  webColor += String(blue, HEX);
>>
>>  ATS_ReportMemoryUsage(startMemoryUsage);
>>
>>  /*
>>   * Test complete
>>   */
>>
>>  ATS_end();
>> }
>>
>>
>> //************************************************************************
>> void loop()
>> {
>>
>>
>> }
>>
>>
>>
>>
>> On Mon, Jan 3, 2011 at 9:35 PM, Tom Igoe <> wrote:
>>> It broke in the non-SDM version too, but it took longer to break. In the SDM version it breaks immediately. So it looks like whatever you did highlights the faults sooner, which is good. It also points to a need for an error response of some sort, in answer to your question last mail.
>>>
>>> t.
>>>
>>> On Jan 3, 2011, at 4:44 PM, Alexander Brevig wrote:
>>>
>>>> That breaking of String, does it only occur with the SDM version?
>>>>
>>>> If not, did you find any way to break it? Maybe any of the old faults related to memory?
>>>>
>>>>
>>>> I actually have no time to check this myself right now, so I opted to just ask you.
>>>>
>>>> On Mon, Jan 3, 2011 at 10:35 PM, Tom Igoe <> wrote:
>>>> Thanks, Alexander, and sorry for the delay.
>>>>
>>>> A few tests:
>>>>
>>>> For code that doesn't change the strings much, there's not a big difference, a couple dozen bytes' difference in code size.  However, when you start to do dynamic things, it does add up.  For example, the StringAppendOperator example is  4910 bytes in 0022, and 5148 bytes with the StaticDynamicMemory version. So it does start to take its toll, memory-wise.
>>>>
>>>> On some sketches it actually takes less memory.  For example, the one below is 3738 bytes using the StaticDynamicMemory version, and 3986 bytes in 0022.  However, it fails entirely on upload.  When the value of (analog 0)/4 is high (0xFF), it never gets out of the setup(). So there's still a pretty easy way to break String, even with these improvements.
>>>>
>>>>
>>>> void setup() {
>>>>  Serial.begin(9600);
>>>>  Serial.println("Beginning");
>>>> }
>>>>
>>>> void loop() {
>>>>
>>>>  String webColor = "#";
>>>>
>>>>  int red = analogRead(A0)/4;
>>>>  webColor += String(red, HEX);
>>>>  int green = analogRead(A1)/4;
>>>>  webColor += String(green, HEX);
>>>>  int blue = analogRead(A2)/4;
>>>>
>>>>  webColor += String(blue, HEX);
>>>>  Serial.println(webColor);
>>>> }
>>>>
>>>>
>>>>
>>>>
>>>>
>>>> On Dec 16, 2010, at 1:27 AM, Alexander Brevig wrote:
>>>>
>>>>> Attached is a zip containing WString.h and .cpp plus StaticDynamicMemory.h.
>>>>> Take a backup of the original WString files, and extract this zip into the hardware/arduino/cores/arduino folder.
>>>>>
>>>>> Now you're ready to test the modified String library, that does not fragment the heap.
>>>>>
>>>>>
>>>>> In the WString header there is a #define called STRING_BUFFER which is set to 100 for now, change this to suit your test needs.
>>>>>
>>>>>
>>>>> No error handling is implemented, what do you think we need?
>>>>>
>>>>> I plan to add an availableMemory():int method to the SDM library, and maybe some error flags and checks like hasError():int error
>>>>>
>>>>> I also suspect that this library is a bit slower performance wise, but I think that's just a cost we'll have to pay to being able to play with dynamic strings.
>>>>>
>>>>>
>>>>> Hope to  get feedback from someone!
>>>>>
>>>>> On Thu, Dec 16, 2010 at 1:11 AM, Alan Burlison <> wrote:
>>>>> On 15/12/2010 16:19, David A. Mellis wrote:
>>>>>
>>>>> I think you're right, but I also don't think that telling people to
>>>>> use the standard C library functions is a solution either.  Trying out
>>>>> this String class seems like one way of pushing forwards towards a
>>>>> compromise that provides both an easy-to-use API and a robust
>>>>> implementation.  For example, perhaps the buffer sizes need to be
>>>>> specified or provided when the String is instantiated.  Or we need an
>>>>> alternative implementation that does more reliable memory allocation
>>>>> (since we're not assuming that the internal buffer is continuous).
>>>>> Other ideas welcome.
>>>>>
>>>>> I think the problem is that the failure modes are not benign.  I haven't been through all the use cases so this might not work, but perhaps using a statically-allocated string ("NOMEM" ?) as a sentinel value instead of null when malloc fails might be one way?  Also, there might be some benefit in making String immutable a la Java - overloaded operators in C++ have a tendency to generate anonymous temporaries, which is going to lead to heap fragmentation as well.
>>>>>
>>>>> --
>>>>> Alan Burlison
>>>>> --
>>>>>
>>>>> _______________________________________________
___________________________________________________

Posted on the Developers mailing list. Go to http://arduino.cc/mailman/listinfo/developers_arduino.cc to subscribe. On 04/01/2011 17:53, Rick Anderson wrote:

> I also ran the tests for bug 411. All the tests compile, but there is
> still memory loss.

Most of the assumptions made by the test harness and test case code are
wrong, any reports of 'lost' memory are therefore likely to be wrong as
well. If you want to do leak detection you can't do it in the naive way
it is being done at present.

--
Alan Burlison
--

_______________________________________________
___________________________________________________

Posted on the Developers mailing list. Go to http://arduino.cc/mailman/listinfo/developers_arduino.cc to subscribe. Alan,

The tests themselves are quick and dirty, and not strategic or
comprehensive. I'd like your input to create a good procedure for
memory testing. I also have feedback from Paul Stoffregen for the test
suite:
----
Another problem involves gcc's optimizer ignoring the inline request
for ATS_ReportMemoryUsage. As the comment in the code explains, it
must be inline to avoid measuring its own stack frame. I believe
adding this line in ArduinoTestSuite.h fixes the problem by forcing
gcc to inline.

inline void ATS_ReportMemoryUsage(int _memoryUsageAtStart)
__attribute__((always_inline, unused));

The last problem is a tiny bit of dynamic memory permanently held for
the free list. To allow for this, the test really should call
malloc() and free() once, so the allocator is fully initialized before
testing.
----

I'd like to combine both sets of feedback, and set up some issues in
the system, then fix them. Is the above the problem you saw? Are their
other assumptions that would impact measuring memory? And updating the
memory test in the the test suite.

In terms of creating tests for memory leaks. It looks best to move all
the memory usage inside a function. What else could be done to
constrain the problem, and measuring more affectively.

I'm traveling back to NJ today, so I can't respond right away.

--Rick

On Wed, Jan 5, 2011 at 8:52 AM, Alan Burlison <> wrote:
> On 04/01/2011 17:53, Rick Anderson wrote:
>
>> I also ran the tests for bug 411. All the tests compile, but there is
>> still memory loss.
>
> Most of the assumptions made by the test harness and test case code are
> wrong, any reports of 'lost' memory are therefore likely to be wrong as
> well.  If you want to do leak detection you can't do it in the naive way it
> is being done at present.
>
> --
> Alan Burlison
> --
>



--
President
Fair Use Building and Research (****) Labs
http://fubarlabs.org

_______________________________________________
___________________________________________________

Posted on the Developers mailing list. Go to http://arduino.cc/mailman/listinfo/developers_arduino.cc to subscribe. On 05/01/2011 15:19, Rick Anderson wrote:

> ----
> Another problem involves gcc's optimizer ignoring the inline request
> for ATS_ReportMemoryUsage. As the comment in the code explains, it
> must be inline to avoid measuring its own stack frame. I believe
> adding this line in ArduinoTestSuite.h fixes the problem by forcing
> gcc to inline.
>
> inline void ATS_ReportMemoryUsage(int _memoryUsageAtStart)
> __attribute__((always_inline, unused));

Yes, that's one of the problems. And even the __attribute__
'workaround' is a fragile hack.

> The last problem is a tiny bit of dynamic memory permanently held for
> the free list. To allow for this, the test really should call
> malloc() and free() once, so the allocator is fully initialized before

That's part of a problem, but an initial call malloc/free call isn't
guaranteed to make all the issues go away either. From looking at the
avr-libc malloc implementation it does try to coalesce the heap, but
relying on multiple malloc implementation artefacts is a really bad idea
- there's no guarantee that future malloc implementations will always
coalesce on every free, and there's no guarantee that __bss_end or
__brkval will always be adjusted on each malloc/free call.

The other issue is that of object lifetimes. The test code has
instances of String objects which are allocated on the stack and that
are still in scope when the 'leak' memory check is performed. That
means the String destructors won't have been called and the dynamically
allocated part of the String will still be allocated.

A true memory leak is a block of allocated memory that has no references
to it. However that's not what the test code is checking for. If a
library routine used malloc to perform a one-time library-private buffer
allocation where the buffer is retained for the lifetime of the program,
the current leak checking would incorrectly report that as a leak. It
isn't a leak because there's still a reference to the block inside the
library.

The only semi-reliable way to do what you want is to use an instrumented
malloc implementation, and that's going to be very difficult to
implement on a constrained platform such as the AVR. If you want to
test the String implementation for leaks, my advice is to do it on a
more capable platform (e.g. *nix) and use one of the many instrumented
mallocs that are available.

--
Alan Burlison
--

_______________________________________________
___________________________________________________

Posted on the Developers mailing list. Go to http://arduino.cc/mailman/listinfo/developers_arduino.cc to subscribe.

  #9  
05-01-2011 06:25 PM
Developers member admin is online now
User
 

That breaking of String, does it only occur with the SDM version?

If not, did you find any way to break it? Maybe any of the old faults
related to memory?


I actually have no time to check this myself right now, so I opted to just
ask you.

On Mon, Jan 3, 2011 at 10:35 PM, Tom Igoe <> wrote:

> Thanks, Alexander, and sorry for the delay.
>
> A few tests:
>
> For code that doesn't change the strings much, there's not a big
> difference, a couple dozen bytes' difference in code size. However, when
> you start to do dynamic things, it does add up. For example, the
> StringAppendOperator example is 4910 bytes in 0022, and 5148 bytes with the
> StaticDynamicMemory version. So it does start to take its toll, memory-wise.
>
> On some sketches it actually takes less memory. For example, the one below
> is 3738 bytes using the StaticDynamicMemory version, and 3986 bytes in 0022.
> However, it fails entirely on upload. When the value of (analog 0)/4 is
> high (0xFF), it never gets out of the setup(). So there's still a pretty
> easy way to break String, even with these improvements.
>
>
> void setup() {
> Serial.begin(9600);
> Serial.println("Beginning");
> }
>
> void loop() {
>
> String webColor = "#";
>
> int red = analogRead(A0)/4;
> webColor += String(red, HEX);
> int green = analogRead(A1)/4;
> webColor += String(green, HEX);
> int blue = analogRead(A2)/4;
>
> webColor += String(blue, HEX);
> Serial.println(webColor);
> }
>
>
>
>
>
> On Dec 16, 2010, at 1:27 AM, Alexander Brevig wrote:
>
> > Attached is a zip containing WString.h and .cpp plus
> StaticDynamicMemory.h.
> > Take a backup of the original WString files, and extract this zip into
> the hardware/arduino/cores/arduino folder.
> >
> > Now you're ready to test the modified String library, that does not
> fragment the heap.
> >
> >
> > In the WString header there is a #define called STRING_BUFFER which is
> set to 100 for now, change this to suit your test needs.
> >
> >
> > No error handling is implemented, what do you think we need?
> >
> > I plan to add an availableMemory():int method to the SDM library, and
> maybe some error flags and checks like hasError():int error
> >
> > I also suspect that this library is a bit slower performance wise, but I
> think that's just a cost we'll have to pay to being able to play with
> dynamic strings.
> >
> >
> > Hope to get feedback from someone!
> >
> > On Thu, Dec 16, 2010 at 1:11 AM, Alan Burlison <>
> wrote:
> > On 15/12/2010 16:19, David A. Mellis wrote:
> >
> > I think you're right, but I also don't think that telling people to
> > use the standard C library functions is a solution either. Trying out
> > this String class seems like one way of pushing forwards towards a
> > compromise that provides both an easy-to-use API and a robust
> > implementation. For example, perhaps the buffer sizes need to be
> > specified or provided when the String is instantiated. Or we need an
> > alternative implementation that does more reliable memory allocation
> > (since we're not assuming that the internal buffer is continuous).
> > Other ideas welcome.
> >
> > I think the problem is that the failure modes are not benign. I haven't
> been through all the use cases so this might not work, but perhaps using a
> statically-allocated string ("NOMEM" ?) as a sentinel value instead of null
> when malloc fails might be one way? Also, there might be some benefit in
> making String immutable a la Java - overloaded operators in C++ have a
> tendency to generate anonymous temporaries, which is going to lead to heap
> fragmentation as well.
> >
> > --
> > Alan Burlison
> > --
> >
> > _______________________________________________
___________________________________________________

Posted on the Developers mailing list. Go to http://arduino.cc/mailman/listinfo/developers_arduino.cc to subscribe. It broke in the non-SDM version too, but it took longer to break. In the SDM version it breaks immediately. So it looks like whatever you did highlights the faults sooner, which is good. It also points to a need for an error response of some sort, in answer to your question last mail.

t.

On Jan 3, 2011, at 4:44 PM, Alexander Brevig wrote:

> That breaking of String, does it only occur with the SDM version?
>
> If not, did you find any way to break it? Maybe any of the old faults related to memory?
>
>
> I actually have no time to check this myself right now, so I opted to just ask you.
>
> On Mon, Jan 3, 2011 at 10:35 PM, Tom Igoe <> wrote:
> Thanks, Alexander, and sorry for the delay.
>
> A few tests:
>
> For code that doesn't change the strings much, there's not a big difference, a couple dozen bytes' difference in code size. However, when you start to do dynamic things, it does add up. For example, the StringAppendOperator example is 4910 bytes in 0022, and 5148 bytes with the StaticDynamicMemory version. So it does start to take its toll, memory-wise.
>
> On some sketches it actually takes less memory. For example, the one below is 3738 bytes using the StaticDynamicMemory version, and 3986 bytes in 0022. However, it fails entirely on upload. When the value of (analog 0)/4 is high (0xFF), it never gets out of the setup(). So there's still a pretty easy way to break String, even with these improvements.
>
>
> void setup() {
> Serial.begin(9600);
> Serial.println("Beginning");
> }
>
> void loop() {
>
> String webColor = "#";
>
> int red = analogRead(A0)/4;
> webColor += String(red, HEX);
> int green = analogRead(A1)/4;
> webColor += String(green, HEX);
> int blue = analogRead(A2)/4;
>
> webColor += String(blue, HEX);
> Serial.println(webColor);
> }
>
>
>
>
>
> On Dec 16, 2010, at 1:27 AM, Alexander Brevig wrote:
>
> > Attached is a zip containing WString.h and .cpp plus StaticDynamicMemory.h.
> > Take a backup of the original WString files, and extract this zip into the hardware/arduino/cores/arduino folder.
> >
> > Now you're ready to test the modified String library, that does not fragment the heap.
> >
> >
> > In the WString header there is a #define called STRING_BUFFER which is set to 100 for now, change this to suit your test needs.
> >
> >
> > No error handling is implemented, what do you think we need?
> >
> > I plan to add an availableMemory():int method to the SDM library, and maybe some error flags and checks like hasError():int error
> >
> > I also suspect that this library is a bit slower performance wise, but I think that's just a cost we'll have to pay to being able to play with dynamic strings.
> >
> >
> > Hope to get feedback from someone!
> >
> > On Thu, Dec 16, 2010 at 1:11 AM, Alan Burlison <> wrote:
> > On 15/12/2010 16:19, David A. Mellis wrote:
> >
> > I think you're right, but I also don't think that telling people to
> > use the standard C library functions is a solution either. Trying out
> > this String class seems like one way of pushing forwards towards a
> > compromise that provides both an easy-to-use API and a robust
> > implementation. For example, perhaps the buffer sizes need to be
> > specified or provided when the String is instantiated. Or we need an
> > alternative implementation that does more reliable memory allocation
> > (since we're not assuming that the internal buffer is continuous).
> > Other ideas welcome.
> >
> > I think the problem is that the failure modes are not benign. I haven't been through all the use cases so this might not work, but perhaps using a statically-allocated string ("NOMEM" ?) as a sentinel value instead of null when malloc fails might be one way? Also, there might be some benefit in making String immutable a la Java - overloaded operators in C++ have a tendency to generate anonymous temporaries, which is going to lead to heap fragmentation as well.
> >
> > --
> > Alan Burlison
> > --
> >
> > _______________________________________________
___________________________________________________

Posted on the Developers mailing list. Go to http://arduino.cc/mailman/listinfo/developers_arduino.cc to subscribe. There seems to be a bug with the assignment operator, I'm on it and I'll get
back to you as soon as I get something done.

Thank you for your tests and feedback.


I'll do some tests on my own before I repost it here.

On Tue, Jan 4, 2011 at 6:53 PM, Rick Anderson
<>wrote:

> I just created a test and unpacked and tested it. I also created a
> test based on Tom's code. Not sure I caught the maximum value error
> for 0xFF.
>
> I also ran the tests for bug 411. All the tests compile, but there is
> still memory loss.
>
> I'm attaching the Arduino Test suite, and the test code so you can run
> them as you debug. Let me know if this was helpful.
>
> --Rick
>
> Test run results:
> Example: ATS_StringAssignmentTest.pde
> info.MANUFACTURER = Arduino
> info.CPU-NAME = ATmega328P
> info.GCC-Version = 4.3.2
> info.AVR-LibC-Ver = 1.6.4
> info.Compiled-date = Jan 4 2011
> info.Test-Suite-Name = ATS_StringAssignmentTest
> info.Free-memory = 1110 bytes
> Memory Usage (lost 59 bytes) ... FAIL
> --------------------------
> Ran 1 tests in 1.378s
>
> FAILED (failures=1)
>
>
> Example: ATS_StringMemoryTestPassByReference.pde
>
> info.MANUFACTURER = Arduino
> info.CPU-NAME = ATmega328P
> info.GCC-Version = 4.3.2
> info.AVR-LibC-Ver = 1.6.4
> info.Compiled-date = Jan 4 2011
> info.Test-Suite-Name = ATS_StringMemoryTestPassByReference
> info.Free-memory = 1120 bytes
> Memory Usage (lost 59 bytes) ... FAIL
> --------------------------
> Ran 1 tests in 1.389s
>
> FAILED (failures=1)
>
>
> Example: Tom Igoe Memory Test
> info.MANUFACTURER = Arduino
> info.CPU-NAME = ATmega328P
> info.GCC-Version = 4.3.2
> info.AVR-LibC-Ver = 1.6.4
> info.Compiled-date = Jan 4 2011
> info.Test-Suite-Name = Tom Igoe Memory Test
> info.Free-memory = 1328 bytes
> Memory Usage (lost 9 bytes) ... FAIL
> --------------------------
> Ran 1 tests in 1.374s
>
> FAILED (failures=1)
>
>
>
> --Rick
>
> Tom, rewrote your example as a test.
>
> //************************************************************************
> //* Arduino Tom Igoe Memory Test
> //* (C) 2010 by Rick Anderson
> //* Open source as per standard Arduino code
> //*
> //************************************************************************
> //* Jan 4, 2011 Started on Tom Igoe Memory Test
> //************************************************************************
>
> #include "WProgram.h"
> #include "HardwareSerial.h"
> #include
>
> //************************************************************************
> void setup()
> {
> int startMemoryUsage;
> /*
> * Create variable for the tests.
> */
>
> String webColor = "#000000";
>
> int red = 1023/4;
> int blue = 512/4;
> int green = 128/4;
>
> /*
> * initiate the test run
> */
> //Record starting memory amount
> startMemoryUsage = ATS_GetFreeMemory();
> //Begin test run
> ATS_begin("Arduino", "Tom Igoe Memory Test");
>
> webColor = "#";
> webColor += String(red, HEX);
> webColor += String(green, HEX);
> webColor += String(blue, HEX);
>
> ATS_ReportMemoryUsage(startMemoryUsage);
>
> /*
> * Test complete
> */
>
> ATS_end();
> }
>
>
> //************************************************************************
> void loop()
> {
>
>
> }
>
>
>
>
> On Mon, Jan 3, 2011 at 9:35 PM, Tom Igoe <> wrote:
> > It broke in the non-SDM version too, but it took longer to break. In the
> SDM version it breaks immediately. So it looks like whatever you did
> highlights the faults sooner, which is good. It also points to a need for an
> error response of some sort, in answer to your question last mail.
> >
> > t.
> >
> > On Jan 3, 2011, at 4:44 PM, Alexander Brevig wrote:
> >
> >> That breaking of String, does it only occur with the SDM version?
> >>
> >> If not, did you find any way to break it? Maybe any of the old faults
> related to memory?
> >>
> >>
> >> I actually have no time to check this myself right now, so I opted to
> just ask you.
> >>
> >> On Mon, Jan 3, 2011 at 10:35 PM, Tom Igoe <> wrote:
> >> Thanks, Alexander, and sorry for the delay.
> >>
> >> A few tests:
> >>
> >> For code that doesn't change the strings much, there's not a big
> difference, a couple dozen bytes' difference in code size. However, when
> you start to do dynamic things, it does add up. For example, the
> StringAppendOperator example is 4910 bytes in 0022, and 5148 bytes with the
> StaticDynamicMemory version. So it does start to take its toll, memory-wise.
> >>
> >> On some sketches it actually takes less memory. For example, the one
> below is 3738 bytes using the StaticDynamicMemory version, and 3986 bytes in
> 0022. However, it fails entirely on upload. When the value of (analog 0)/4
> is high (0xFF), it never gets out of the setup(). So there's still a pretty
> easy way to break String, even with these improvements.
> >>
> >>
> >> void setup() {
> >> Serial.begin(9600);
> >> Serial.println("Beginning");
> >> }
> >>
> >> void loop() {
> >>
> >> String webColor = "#";
> >>
> >> int red = analogRead(A0)/4;
> >> webColor += String(red, HEX);
> >> int green = analogRead(A1)/4;
> >> webColor += String(green, HEX);
> >> int blue = analogRead(A2)/4;
> >>
> >> webColor += String(blue, HEX);
> >> Serial.println(webColor);
> >> }
> >>
> >>
> >>
> >>
> >>
> >> On Dec 16, 2010, at 1:27 AM, Alexander Brevig wrote:
> >>
> >> > Attached is a zip containing WString.h and .cpp plus
> StaticDynamicMemory.h.
> >> > Take a backup of the original WString files, and extract this zip into
> the hardware/arduino/cores/arduino folder.
> >> >
> >> > Now you're ready to test the modified String library, that does not
> fragment the heap.
> >> >
> >> >
> >> > In the WString header there is a #define called STRING_BUFFER which is
> set to 100 for now, change this to suit your test needs.
> >> >
> >> >
> >> > No error handling is implemented, what do you think we need?
> >> >
> >> > I plan to add an availableMemory():int method to the SDM library, and
> maybe some error flags and checks like hasError():int error
> >> >
> >> > I also suspect that this library is a bit slower performance wise, but
> I think that's just a cost we'll have to pay to being able to play with
> dynamic strings.
> >> >
> >> >
> >> > Hope to get feedback from someone!
> >> >
> >> > On Thu, Dec 16, 2010 at 1:11 AM, Alan Burlison <
> > wrote:
> >> > On 15/12/2010 16:19, David A. Mellis wrote:
> >> >
> >> > I think you're right, but I also don't think that telling people to
> >> > use the standard C library functions is a solution either. Trying out
> >> > this String class seems like one way of pushing forwards towards a
> >> > compromise that provides both an easy-to-use API and a robust
> >> > implementation. For example, perhaps the buffer sizes need to be
> >> > specified or provided when the String is instantiated. Or we need an
> >> > alternative implementation that does more reliable memory allocation
> >> > (since we're not assuming that the internal buffer is continuous).
> >> > Other ideas welcome.
> >> >
> >> > I think the problem is that the failure modes are not benign. I
> haven't been through all the use cases so this might not work, but perhaps
> using a statically-allocated string ("NOMEM" ?) as a sentinel value instead
> of null when malloc fails might be one way? Also, there might be some
> benefit in making String immutable a la Java - overloaded operators in C++
> have a tendency to generate anonymous temporaries, which is going to lead to
> heap fragmentation as well.
> >> >
> >> > --
> >> > Alan Burlison
> >> > --
> >> >
> >> > _______________________________________________
___________________________________________________

Posted on the Developers mailing list. Go to http://arduino.cc/mailman/listinfo/developers_arduino.cc to subscribe. Is this test suite any different than the one in the github repo?

t.

On Jan 4, 2011, at 12:53 PM, Rick Anderson wrote:

> I just created a test and unpacked and tested it. I also created a
> test based on Tom's code. Not sure I caught the maximum value error
> for 0xFF.
>
> I also ran the tests for bug 411. All the tests compile, but there is
> still memory loss.
>
> I'm attaching the Arduino Test suite, and the test code so you can run
> them as you debug. Let me know if this was helpful.
>
> --Rick
>
> Test run results:
> Example: ATS_StringAssignmentTest.pde
> info.MANUFACTURER = Arduino
> info.CPU-NAME = ATmega328P
> info.GCC-Version = 4.3.2
> info.AVR-LibC-Ver = 1.6.4
> info.Compiled-date = Jan 4 2011
> info.Test-Suite-Name = ATS_StringAssignmentTest
> info.Free-memory = 1110 bytes
> Memory Usage (lost 59 bytes) ... FAIL
> --------------------------
> Ran 1 tests in 1.378s
>
> FAILED (failures=1)
>
>
> Example: ATS_StringMemoryTestPassByReference.pde
>
> info.MANUFACTURER = Arduino
> info.CPU-NAME = ATmega328P
> info.GCC-Version = 4.3.2
> info.AVR-LibC-Ver = 1.6.4
> info.Compiled-date = Jan 4 2011
> info.Test-Suite-Name = ATS_StringMemoryTestPassByReference
> info.Free-memory = 1120 bytes
> Memory Usage (lost 59 bytes) ... FAIL
> --------------------------
> Ran 1 tests in 1.389s
>
> FAILED (failures=1)
>
>
> Example: Tom Igoe Memory Test
> info.MANUFACTURER = Arduino
> info.CPU-NAME = ATmega328P
> info.GCC-Version = 4.3.2
> info.AVR-LibC-Ver = 1.6.4
> info.Compiled-date = Jan 4 2011
> info.Test-Suite-Name = Tom Igoe Memory Test
> info.Free-memory = 1328 bytes
> Memory Usage (lost 9 bytes) ... FAIL
> --------------------------
> Ran 1 tests in 1.374s
>
> FAILED (failures=1)
>
>
>
> --Rick
>
> Tom, rewrote your example as a test.
>
> //************************************************************************
> //* Arduino Tom Igoe Memory Test
> //* (C) 2010 by Rick Anderson
> //* Open source as per standard Arduino code
> //*
> //************************************************************************
> //* Jan 4, 2011 Started on Tom Igoe Memory Test
> //************************************************************************
>
> #include "WProgram.h"
> #include "HardwareSerial.h"
> #include
>
> //************************************************************************
> void setup()
> {
> int startMemoryUsage;
> /*
> * Create variable for the tests.
> */
>
> String webColor = "#000000";
>
> int red = 1023/4;
> int blue = 512/4;
> int green = 128/4;
>
> /*
> * initiate the test run
> */
> //Record starting memory amount
> startMemoryUsage = ATS_GetFreeMemory();
> //Begin test run
> ATS_begin("Arduino", "Tom Igoe Memory Test");
>
> webColor = "#";
> webColor += String(red, HEX);
> webColor += String(green, HEX);
> webColor += String(blue, HEX);
>
> ATS_ReportMemoryUsage(startMemoryUsage);
>
> /*
> * Test complete
> */
>
> ATS_end();
> }
>
>
> //************************************************************************
> void loop()
> {
>
>
> }
>
>
>
>
> On Mon, Jan 3, 2011 at 9:35 PM, Tom Igoe <> wrote:
>> It broke in the non-SDM version too, but it took longer to break. In the SDM version it breaks immediately. So it looks like whatever you did highlights the faults sooner, which is good. It also points to a need for an error response of some sort, in answer to your question last mail.
>>
>> t.
>>
>> On Jan 3, 2011, at 4:44 PM, Alexander Brevig wrote:
>>
>>> That breaking of String, does it only occur with the SDM version?
>>>
>>> If not, did you find any way to break it? Maybe any of the old faults related to memory?
>>>
>>>
>>> I actually have no time to check this myself right now, so I opted to just ask you.
>>>
>>> On Mon, Jan 3, 2011 at 10:35 PM, Tom Igoe <> wrote:
>>> Thanks, Alexander, and sorry for the delay.
>>>
>>> A few tests:
>>>
>>> For code that doesn't change the strings much, there's not a big difference, a couple dozen bytes' difference in code size. However, when you start to do dynamic things, it does add up. For example, the StringAppendOperator example is 4910 bytes in 0022, and 5148 bytes with the StaticDynamicMemory version. So it does start to take its toll, memory-wise.
>>>
>>> On some sketches it actually takes less memory. For example, the one below is 3738 bytes using the StaticDynamicMemory version, and 3986 bytes in 0022. However, it fails entirely on upload. When the value of (analog 0)/4 is high (0xFF), it never gets out of the setup(). So there's still a pretty easy way to break String, even with these improvements.
>>>
>>>
>>> void setup() {
>>> Serial.begin(9600);
>>> Serial.println("Beginning");
>>> }
>>>
>>> void loop() {
>>>
>>> String webColor = "#";
>>>
>>> int red = analogRead(A0)/4;
>>> webColor += String(red, HEX);
>>> int green = analogRead(A1)/4;
>>> webColor += String(green, HEX);
>>> int blue = analogRead(A2)/4;
>>>
>>> webColor += String(blue, HEX);
>>> Serial.println(webColor);
>>> }
>>>
>>>
>>>
>>>
>>>
>>> On Dec 16, 2010, at 1:27 AM, Alexander Brevig wrote:
>>>
>>>> Attached is a zip containing WString.h and .cpp plus StaticDynamicMemory.h.
>>>> Take a backup of the original WString files, and extract this zip into the hardware/arduino/cores/arduino folder.
>>>>
>>>> Now you're ready to test the modified String library, that does not fragment the heap.
>>>>
>>>>
>>>> In the WString header there is a #define called STRING_BUFFER which is set to 100 for now, change this to suit your test needs.
>>>>
>>>>
>>>> No error handling is implemented, what do you think we need?
>>>>
>>>> I plan to add an availableMemory():int method to the SDM library, and maybe some error flags and checks like hasError():int error
>>>>
>>>> I also suspect that this library is a bit slower performance wise, but I think that's just a cost we'll have to pay to being able to play with dynamic strings.
>>>>
>>>>
>>>> Hope to get feedback from someone!
>>>>
>>>> On Thu, Dec 16, 2010 at 1:11 AM, Alan Burlison <> wrote:
>>>> On 15/12/2010 16:19, David A. Mellis wrote:
>>>>
>>>> I think you're right, but I also don't think that telling people to
>>>> use the standard C library functions is a solution either. Trying out
>>>> this String class seems like one way of pushing forwards towards a
>>>> compromise that provides both an easy-to-use API and a robust
>>>> implementation. For example, perhaps the buffer sizes need to be
>>>> specified or provided when the String is instantiated. Or we need an
>>>> alternative implementation that does more reliable memory allocation
>>>> (since we're not assuming that the internal buffer is continuous).
>>>> Other ideas welcome.
>>>>
>>>> I think the problem is that the failure modes are not benign. I haven't been through all the use cases so this might not work, but perhaps using a statically-allocated string ("NOMEM" ?) as a sentinel value instead of null when malloc fails might be one way? Also, there might be some benefit in making String immutable a la Java - overloaded operators in C++ have a tendency to generate anonymous temporaries, which is going to lead to heap fragmentation as well.
>>>>
>>>> --
>>>> Alan Burlison
>>>> --
>>>>
>>>> _______________________________________________
___________________________________________________

Posted on the Developers mailing list. Go to http://arduino.cc/mailman/listinfo/developers_arduino.cc to subscribe. Same exact one. I just included it just in case.

--Rick

On Tue, Jan 4, 2011 at 9:01 PM, Tom Igoe <> wrote:
> Is this test suite any different than the one in the github repo?
>
> t.
>
> On Jan 4, 2011, at 12:53 PM, Rick Anderson wrote:
>
>> I just created a test and unpacked and tested it. I also created a
>> test based on Tom's code. Not sure I caught the maximum value error
>> for 0xFF.
>>
>> I also ran the tests for bug 411. All the tests compile, but there is
>> still memory loss.
>>
>> I'm attaching the Arduino Test suite, and the test code so you can run
>> them as you debug. Let me know if this was helpful.
>>
>> --Rick
>>
>> Test run results:
>> Example:  ATS_StringAssignmentTest.pde
>> info.MANUFACTURER    = Arduino
>> info.CPU-NAME        = ATmega328P
>> info.GCC-Version     = 4.3.2
>> info.AVR-LibC-Ver    = 1.6.4
>> info.Compiled-date   = Jan  4 2011
>> info.Test-Suite-Name = ATS_StringAssignmentTest
>> info.Free-memory     = 1110 bytes
>> Memory Usage (lost 59 bytes)                                ... FAIL
>> --------------------------
>> Ran 1 tests in 1.378s
>>
>> FAILED (failures=1)
>>
>>
>> Example: ATS_StringMemoryTestPassByReference.pde
>>
>> info.MANUFACTURER    = Arduino
>> info.CPU-NAME        = ATmega328P
>> info.GCC-Version     = 4.3.2
>> info.AVR-LibC-Ver    = 1.6.4
>> info.Compiled-date   = Jan  4 2011
>> info.Test-Suite-Name = ATS_StringMemoryTestPassByReference
>> info.Free-memory     = 1120 bytes
>> Memory Usage (lost 59 bytes)                                ... FAIL
>> --------------------------
>> Ran 1 tests in 1.389s
>>
>> FAILED (failures=1)
>>
>>
>> Example: Tom Igoe Memory Test
>> info.MANUFACTURER    = Arduino
>> info.CPU-NAME        = ATmega328P
>> info.GCC-Version     = 4.3.2
>> info.AVR-LibC-Ver    = 1.6.4
>> info.Compiled-date   = Jan  4 2011
>> info.Test-Suite-Name = Tom Igoe Memory Test
>> info.Free-memory     = 1328 bytes
>> Memory Usage (lost 9 bytes)                                 ... FAIL
>> --------------------------
>> Ran 1 tests in 1.374s
>>
>> FAILED (failures=1)
>>
>>
>>
>> --Rick
>>
>> Tom, rewrote your example as a test.
>>
>> //************************************************************************
>> //*   Arduino Tom Igoe Memory Test
>> //*           (C) 2010 by Rick Anderson
>> //*           Open source as per standard Arduino code
>> //*
>> //************************************************************************
>> //*   Jan 4,  2011     Started on Tom Igoe Memory Test
>> //************************************************************************
>>
>> #include      "WProgram.h"
>> #include      "HardwareSerial.h"
>> #include      
>>
>> //************************************************************************
>> void setup()
>> {
>>  int          startMemoryUsage;
>>  /*
>>    * Create variable for the tests.
>>   */
>>
>>  String webColor = "#000000";
>>
>>  int red = 1023/4;
>>  int blue = 512/4;
>>  int green = 128/4;
>>
>>  /*
>>  * initiate the test run
>>   */
>>  //Record starting memory amount
>>  startMemoryUsage     =       ATS_GetFreeMemory();
>>  //Begin test run
>>  ATS_begin("Arduino", "Tom Igoe Memory Test");
>>
>>  webColor = "#";
>>  webColor += String(red, HEX);
>>  webColor += String(green, HEX);
>>  webColor += String(blue, HEX);
>>
>>  ATS_ReportMemoryUsage(startMemoryUsage);
>>
>>  /*
>>   * Test complete
>>   */
>>
>>  ATS_end();
>> }
>>
>>
>> //************************************************************************
>> void loop()
>> {
>>
>>
>> }
>>
>>
>>
>>
>> On Mon, Jan 3, 2011 at 9:35 PM, Tom Igoe <> wrote:
>>> It broke in the non-SDM version too, but it took longer to break. In the SDM version it breaks immediately. So it looks like whatever you did highlights the faults sooner, which is good. It also points to a need for an error response of some sort, in answer to your question last mail.
>>>
>>> t.
>>>
>>> On Jan 3, 2011, at 4:44 PM, Alexander Brevig wrote:
>>>
>>>> That breaking of String, does it only occur with the SDM version?
>>>>
>>>> If not, did you find any way to break it? Maybe any of the old faults related to memory?
>>>>
>>>>
>>>> I actually have no time to check this myself right now, so I opted to just ask you.
>>>>
>>>> On Mon, Jan 3, 2011 at 10:35 PM, Tom Igoe <> wrote:
>>>> Thanks, Alexander, and sorry for the delay.
>>>>
>>>> A few tests:
>>>>
>>>> For code that doesn't change the strings much, there's not a big difference, a couple dozen bytes' difference in code size.  However, when you start to do dynamic things, it does add up.  For example, the StringAppendOperator example is  4910 bytes in 0022, and 5148 bytes with the StaticDynamicMemory version. So it does start to take its toll, memory-wise.
>>>>
>>>> On some sketches it actually takes less memory.  For example, the one below is 3738 bytes using the StaticDynamicMemory version, and 3986 bytes in 0022.  However, it fails entirely on upload.  When the value of (analog 0)/4 is high (0xFF), it never gets out of the setup(). So there's still a pretty easy way to break String, even with these improvements.
>>>>
>>>>
>>>> void setup() {
>>>>  Serial.begin(9600);
>>>>  Serial.println("Beginning");
>>>> }
>>>>
>>>> void loop() {
>>>>
>>>>  String webColor = "#";
>>>>
>>>>  int red = analogRead(A0)/4;
>>>>  webColor += String(red, HEX);
>>>>  int green = analogRead(A1)/4;
>>>>  webColor += String(green, HEX);
>>>>  int blue = analogRead(A2)/4;
>>>>
>>>>  webColor += String(blue, HEX);
>>>>  Serial.println(webColor);
>>>> }
>>>>
>>>>
>>>>
>>>>
>>>>
>>>> On Dec 16, 2010, at 1:27 AM, Alexander Brevig wrote:
>>>>
>>>>> Attached is a zip containing WString.h and .cpp plus StaticDynamicMemory.h.
>>>>> Take a backup of the original WString files, and extract this zip into the hardware/arduino/cores/arduino folder.
>>>>>
>>>>> Now you're ready to test the modified String library, that does not fragment the heap.
>>>>>
>>>>>
>>>>> In the WString header there is a #define called STRING_BUFFER which is set to 100 for now, change this to suit your test needs.
>>>>>
>>>>>
>>>>> No error handling is implemented, what do you think we need?
>>>>>
>>>>> I plan to add an availableMemory():int method to the SDM library, and maybe some error flags and checks like hasError():int error
>>>>>
>>>>> I also suspect that this library is a bit slower performance wise, but I think that's just a cost we'll have to pay to being able to play with dynamic strings.
>>>>>
>>>>>
>>>>> Hope to  get feedback from someone!
>>>>>
>>>>> On Thu, Dec 16, 2010 at 1:11 AM, Alan Burlison <> wrote:
>>>>> On 15/12/2010 16:19, David A. Mellis wrote:
>>>>>
>>>>> I think you're right, but I also don't think that telling people to
>>>>> use the standard C library functions is a solution either.  Trying out
>>>>> this String class seems like one way of pushing forwards towards a
>>>>> compromise that provides both an easy-to-use API and a robust
>>>>> implementation.  For example, perhaps the buffer sizes need to be
>>>>> specified or provided when the String is instantiated.  Or we need an
>>>>> alternative implementation that does more reliable memory allocation
>>>>> (since we're not assuming that the internal buffer is continuous).
>>>>> Other ideas welcome.
>>>>>
>>>>> I think the problem is that the failure modes are not benign.  I haven't been through all the use cases so this might not work, but perhaps using a statically-allocated string ("NOMEM" ?) as a sentinel value instead of null when malloc fails might be one way?  Also, there might be some benefit in making String immutable a la Java - overloaded operators in C++ have a tendency to generate anonymous temporaries, which is going to lead to heap fragmentation as well.
>>>>>
>>>>> --
>>>>> Alan Burlison
>>>>> --
>>>>>
>>>>> _______________________________________________
___________________________________________________

Posted on the Developers mailing list. Go to http://arduino.cc/mailman/listinfo/developers_arduino.cc to subscribe. On 04/01/2011 17:53, Rick Anderson wrote:

> I also ran the tests for bug 411. All the tests compile, but there is
> still memory loss.

Most of the assumptions made by the test harness and test case code are
wrong, any reports of 'lost' memory are therefore likely to be wrong as
well. If you want to do leak detection you can't do it in the naive way
it is being done at present.

--
Alan Burlison
--

_______________________________________________
___________________________________________________

Posted on the Developers mailing list. Go to http://arduino.cc/mailman/listinfo/developers_arduino.cc to subscribe. Alan,

The tests themselves are quick and dirty, and not strategic or
comprehensive. I'd like your input to create a good procedure for
memory testing. I also have feedback from Paul Stoffregen for the test
suite:
----
Another problem involves gcc's optimizer ignoring the inline request
for ATS_ReportMemoryUsage. As the comment in the code explains, it
must be inline to avoid measuring its own stack frame. I believe
adding this line in ArduinoTestSuite.h fixes the problem by forcing
gcc to inline.

inline void ATS_ReportMemoryUsage(int _memoryUsageAtStart)
__attribute__((always_inline, unused));

The last problem is a tiny bit of dynamic memory permanently held for
the free list. To allow for this, the test really should call
malloc() and free() once, so the allocator is fully initialized before
testing.
----

I'd like to combine both sets of feedback, and set up some issues in
the system, then fix them. Is the above the problem you saw? Are their
other assumptions that would impact measuring memory? And updating the
memory test in the the test suite.

In terms of creating tests for memory leaks. It looks best to move all
the memory usage inside a function. What else could be done to
constrain the problem, and measuring more affectively.

I'm traveling back to NJ today, so I can't respond right away.

--Rick

On Wed, Jan 5, 2011 at 8:52 AM, Alan Burlison <> wrote:
> On 04/01/2011 17:53, Rick Anderson wrote:
>
>> I also ran the tests for bug 411. All the tests compile, but there is
>> still memory loss.
>
> Most of the assumptions made by the test harness and test case code are
> wrong, any reports of 'lost' memory are therefore likely to be wrong as
> well.  If you want to do leak detection you can't do it in the naive way it
> is being done at present.
>
> --
> Alan Burlison
> --
>



--
President
Fair Use Building and Research (****) Labs
http://fubarlabs.org

_______________________________________________
___________________________________________________

Posted on the Developers mailing list. Go to http://arduino.cc/mailman/listinfo/developers_arduino.cc to subscribe. On 05/01/2011 15:19, Rick Anderson wrote:

> ----
> Another problem involves gcc's optimizer ignoring the inline request
> for ATS_ReportMemoryUsage. As the comment in the code explains, it
> must be inline to avoid measuring its own stack frame. I believe
> adding this line in ArduinoTestSuite.h fixes the problem by forcing
> gcc to inline.
>
> inline void ATS_ReportMemoryUsage(int _memoryUsageAtStart)
> __attribute__((always_inline, unused));

Yes, that's one of the problems. And even the __attribute__
'workaround' is a fragile hack.

> The last problem is a tiny bit of dynamic memory permanently held for
> the free list. To allow for this, the test really should call
> malloc() and free() once, so the allocator is fully initialized before

That's part of a problem, but an initial call malloc/free call isn't
guaranteed to make all the issues go away either. From looking at the
avr-libc malloc implementation it does try to coalesce the heap, but
relying on multiple malloc implementation artefacts is a really bad idea
- there's no guarantee that future malloc implementations will always
coalesce on every free, and there's no guarantee that __bss_end or
__brkval will always be adjusted on each malloc/free call.

The other issue is that of object lifetimes. The test code has
instances of String objects which are allocated on the stack and that
are still in scope when the 'leak' memory check is performed. That
means the String destructors won't have been called and the dynamically
allocated part of the String will still be allocated.

A true memory leak is a block of allocated memory that has no references
to it. However that's not what the test code is checking for. If a
library routine used malloc to perform a one-time library-private buffer
allocation where the buffer is retained for the lifetime of the program,
the current leak checking would incorrectly report that as a leak. It
isn't a leak because there's still a reference to the block inside the
library.

The only semi-reliable way to do what you want is to use an instrumented
malloc implementation, and that's going to be very difficult to
implement on a constrained platform such as the AVR. If you want to
test the String implementation for leaks, my advice is to do it on a
more capable platform (e.g. *nix) and use one of the many instrumented
mallocs that are available.

--
Alan Burlison
--

_______________________________________________
___________________________________________________

Posted on the Developers mailing list. Go to http://arduino.cc/mailman/listinfo/developers_arduino.cc to subscribe. Slightly unrelated to what you guys are discussing now but:
I'm not sure if I've made this clear, but the new version of String that I'm
working on now does not use malloc or any other c function for dynamic
memory. What happens is that I allocate memory statically on the stack and
serve that memory dynamically to the instances of String.

I have some time on my hands now and have a look at getting the += not to
break the code

On Wed, Jan 5, 2011 at 7:10 PM, Alan Burlison <>wrote:

> On 05/01/2011 15:19, Rick Anderson wrote:
>
> ----
>> Another problem involves gcc's optimizer ignoring the inline request
>> for ATS_ReportMemoryUsage. As the comment in the code explains, it
>> must be inline to avoid measuring its own stack frame. I believe
>> adding this line in ArduinoTestSuite.h fixes the problem by forcing
>> gcc to inline.
>>
>> inline void ATS_ReportMemoryUsage(int _memoryUsageAtStart)
>> __attribute__((always_inline, unused));
>>
>
> Yes, that's one of the problems. And even the __attribute__ 'workaround'
> is a fragile hack.
>
>
> The last problem is a tiny bit of dynamic memory permanently held for
>> the free list. To allow for this, the test really should call
>> malloc() and free() once, so the allocator is fully initialized before
>>
>
> That's part of a problem, but an initial call malloc/free call isn't
> guaranteed to make all the issues go away either. From looking at the
> avr-libc malloc implementation it does try to coalesce the heap, but relying
> on multiple malloc implementation artefacts is a really bad idea - there's
> no guarantee that future malloc implementations will always coalesce on
> every free, and there's no guarantee that __bss_end or __brkval will always
> be adjusted on each malloc/free call.
>
> The other issue is that of object lifetimes. The test code has instances
> of String objects which are allocated on the stack and that are still in
> scope when the 'leak' memory check is performed. That means the String
> destructors won't have been called and the dynamically allocated part of the
> String will still be allocated.
>
> A true memory leak is a block of allocated memory that has no references to
> it. However that's not what the test code is checking for. If a library
> routine used malloc to perform a one-time library-private buffer allocation
> where the buffer is retained for the lifetime of the program, the current
> leak checking would incorrectly report that as a leak. It isn't a leak
> because there's still a reference to the block inside the library.
>
> The only semi-reliable way to do what you want is to use an instrumented
> malloc implementation, and that's going to be very difficult to implement on
> a constrained platform such as the AVR. If you want to test the String
> implementation for leaks, my advice is to do it on a more capable platform
> (e.g. *nix) and use one of the many instrumented mallocs that are available.
>
> --
> Alan Burlison
> --
>
>
> _______________________________________________
___________________________________________________

Posted on the Developers mailing list. Go to http://arduino.cc/mailman/listinfo/developers_arduino.cc to subscribe.

  #10  
05-01-2011 06:33 PM
Developers member admin is online now
User
 

That breaking of String, does it only occur with the SDM version?

If not, did you find any way to break it? Maybe any of the old faults
related to memory?


I actually have no time to check this myself right now, so I opted to just
ask you.

On Mon, Jan 3, 2011 at 10:35 PM, Tom Igoe <> wrote:

> Thanks, Alexander, and sorry for the delay.
>
> A few tests:
>
> For code that doesn't change the strings much, there's not a big
> difference, a couple dozen bytes' difference in code size. However, when
> you start to do dynamic things, it does add up. For example, the
> StringAppendOperator example is 4910 bytes in 0022, and 5148 bytes with the
> StaticDynamicMemory version. So it does start to take its toll, memory-wise.
>
> On some sketches it actually takes less memory. For example, the one below
> is 3738 bytes using the StaticDynamicMemory version, and 3986 bytes in 0022.
> However, it fails entirely on upload. When the value of (analog 0)/4 is
> high (0xFF), it never gets out of the setup(). So there's still a pretty
> easy way to break String, even with these improvements.
>
>
> void setup() {
> Serial.begin(9600);
> Serial.println("Beginning");
> }
>
> void loop() {
>
> String webColor = "#";
>
> int red = analogRead(A0)/4;
> webColor += String(red, HEX);
> int green = analogRead(A1)/4;
> webColor += String(green, HEX);
> int blue = analogRead(A2)/4;
>
> webColor += String(blue, HEX);
> Serial.println(webColor);
> }
>
>
>
>
>
> On Dec 16, 2010, at 1:27 AM, Alexander Brevig wrote:
>
> > Attached is a zip containing WString.h and .cpp plus
> StaticDynamicMemory.h.
> > Take a backup of the original WString files, and extract this zip into
> the hardware/arduino/cores/arduino folder.
> >
> > Now you're ready to test the modified String library, that does not
> fragment the heap.
> >
> >
> > In the WString header there is a #define called STRING_BUFFER which is
> set to 100 for now, change this to suit your test needs.
> >
> >
> > No error handling is implemented, what do you think we need?
> >
> > I plan to add an availableMemory():int method to the SDM library, and
> maybe some error flags and checks like hasError():int error
> >
> > I also suspect that this library is a bit slower performance wise, but I
> think that's just a cost we'll have to pay to being able to play with
> dynamic strings.
> >
> >
> > Hope to get feedback from someone!
> >
> > On Thu, Dec 16, 2010 at 1:11 AM, Alan Burlison <>
> wrote:
> > On 15/12/2010 16:19, David A. Mellis wrote:
> >
> > I think you're right, but I also don't think that telling people to
> > use the standard C library functions is a solution either. Trying out
> > this String class seems like one way of pushing forwards towards a
> > compromise that provides both an easy-to-use API and a robust
> > implementation. For example, perhaps the buffer sizes need to be
> > specified or provided when the String is instantiated. Or we need an
> > alternative implementation that does more reliable memory allocation
> > (since we're not assuming that the internal buffer is continuous).
> > Other ideas welcome.
> >
> > I think the problem is that the failure modes are not benign. I haven't
> been through all the use cases so this might not work, but perhaps using a
> statically-allocated string ("NOMEM" ?) as a sentinel value instead of null
> when malloc fails might be one way? Also, there might be some benefit in
> making String immutable a la Java - overloaded operators in C++ have a
> tendency to generate anonymous temporaries, which is going to lead to heap
> fragmentation as well.
> >
> > --
> > Alan Burlison
> > --
> >
> > _______________________________________________
___________________________________________________

Posted on the Developers mailing list. Go to http://arduino.cc/mailman/listinfo/developers_arduino.cc to subscribe. It broke in the non-SDM version too, but it took longer to break. In the SDM version it breaks immediately. So it looks like whatever you did highlights the faults sooner, which is good. It also points to a need for an error response of some sort, in answer to your question last mail.

t.

On Jan 3, 2011, at 4:44 PM, Alexander Brevig wrote:

> That breaking of String, does it only occur with the SDM version?
>
> If not, did you find any way to break it? Maybe any of the old faults related to memory?
>
>
> I actually have no time to check this myself right now, so I opted to just ask you.
>
> On Mon, Jan 3, 2011 at 10:35 PM, Tom Igoe <> wrote:
> Thanks, Alexander, and sorry for the delay.
>
> A few tests:
>
> For code that doesn't change the strings much, there's not a big difference, a couple dozen bytes' difference in code size. However, when you start to do dynamic things, it does add up. For example, the StringAppendOperator example is 4910 bytes in 0022, and 5148 bytes with the StaticDynamicMemory version. So it does start to take its toll, memory-wise.
>
> On some sketches it actually takes less memory. For example, the one below is 3738 bytes using the StaticDynamicMemory version, and 3986 bytes in 0022. However, it fails entirely on upload. When the value of (analog 0)/4 is high (0xFF), it never gets out of the setup(). So there's still a pretty easy way to break String, even with these improvements.
>
>
> void setup() {
> Serial.begin(9600);
> Serial.println("Beginning");
> }
>
> void loop() {
>
> String webColor = "#";
>
> int red = analogRead(A0)/4;
> webColor += String(red, HEX);
> int green = analogRead(A1)/4;
> webColor += String(green, HEX);
> int blue = analogRead(A2)/4;
>
> webColor += String(blue, HEX);
> Serial.println(webColor);
> }
>
>
>
>
>
> On Dec 16, 2010, at 1:27 AM, Alexander Brevig wrote:
>
> > Attached is a zip containing WString.h and .cpp plus StaticDynamicMemory.h.
> > Take a backup of the original WString files, and extract this zip into the hardware/arduino/cores/arduino folder.
> >
> > Now you're ready to test the modified String library, that does not fragment the heap.
> >
> >
> > In the WString header there is a #define called STRING_BUFFER which is set to 100 for now, change this to suit your test needs.
> >
> >
> > No error handling is implemented, what do you think we need?
> >
> > I plan to add an availableMemory():int method to the SDM library, and maybe some error flags and checks like hasError():int error
> >
> > I also suspect that this library is a bit slower performance wise, but I think that's just a cost we'll have to pay to being able to play with dynamic strings.
> >
> >
> > Hope to get feedback from someone!
> >
> > On Thu, Dec 16, 2010 at 1:11 AM, Alan Burlison <> wrote:
> > On 15/12/2010 16:19, David A. Mellis wrote:
> >
> > I think you're right, but I also don't think that telling people to
> > use the standard C library functions is a solution either. Trying out
> > this String class seems like one way of pushing forwards towards a
> > compromise that provides both an easy-to-use API and a robust
> > implementation. For example, perhaps the buffer sizes need to be
> > specified or provided when the String is instantiated. Or we need an
> > alternative implementation that does more reliable memory allocation
> > (since we're not assuming that the internal buffer is continuous).
> > Other ideas welcome.
> >
> > I think the problem is that the failure modes are not benign. I haven't been through all the use cases so this might not work, but perhaps using a statically-allocated string ("NOMEM" ?) as a sentinel value instead of null when malloc fails might be one way? Also, there might be some benefit in making String immutable a la Java - overloaded operators in C++ have a tendency to generate anonymous temporaries, which is going to lead to heap fragmentation as well.
> >
> > --
> > Alan Burlison
> > --
> >
> > _______________________________________________
___________________________________________________

Posted on the Developers mailing list. Go to http://arduino.cc/mailman/listinfo/developers_arduino.cc to subscribe. There seems to be a bug with the assignment operator, I'm on it and I'll get
back to you as soon as I get something done.

Thank you for your tests and feedback.


I'll do some tests on my own before I repost it here.

On Tue, Jan 4, 2011 at 6:53 PM, Rick Anderson
<>wrote:

> I just created a test and unpacked and tested it. I also created a
> test based on Tom's code. Not sure I caught the maximum value error
> for 0xFF.
>
> I also ran the tests for bug 411. All the tests compile, but there is
> still memory loss.
>
> I'm attaching the Arduino Test suite, and the test code so you can run
> them as you debug. Let me know if this was helpful.
>
> --Rick
>
> Test run results:
> Example: ATS_StringAssignmentTest.pde
> info.MANUFACTURER = Arduino
> info.CPU-NAME = ATmega328P
> info.GCC-Version = 4.3.2
> info.AVR-LibC-Ver = 1.6.4
> info.Compiled-date = Jan 4 2011
> info.Test-Suite-Name = ATS_StringAssignmentTest
> info.Free-memory = 1110 bytes
> Memory Usage (lost 59 bytes) ... FAIL
> --------------------------
> Ran 1 tests in 1.378s
>
> FAILED (failures=1)
>
>
> Example: ATS_StringMemoryTestPassByReference.pde
>
> info.MANUFACTURER = Arduino
> info.CPU-NAME = ATmega328P
> info.GCC-Version = 4.3.2
> info.AVR-LibC-Ver = 1.6.4
> info.Compiled-date = Jan 4 2011
> info.Test-Suite-Name = ATS_StringMemoryTestPassByReference
> info.Free-memory = 1120 bytes
> Memory Usage (lost 59 bytes) ... FAIL
> --------------------------
> Ran 1 tests in 1.389s
>
> FAILED (failures=1)
>
>
> Example: Tom Igoe Memory Test
> info.MANUFACTURER = Arduino
> info.CPU-NAME = ATmega328P
> info.GCC-Version = 4.3.2
> info.AVR-LibC-Ver = 1.6.4
> info.Compiled-date = Jan 4 2011
> info.Test-Suite-Name = Tom Igoe Memory Test
> info.Free-memory = 1328 bytes
> Memory Usage (lost 9 bytes) ... FAIL
> --------------------------
> Ran 1 tests in 1.374s
>
> FAILED (failures=1)
>
>
>
> --Rick
>
> Tom, rewrote your example as a test.
>
> //************************************************************************
> //* Arduino Tom Igoe Memory Test
> //* (C) 2010 by Rick Anderson
> //* Open source as per standard Arduino code
> //*
> //************************************************************************
> //* Jan 4, 2011 Started on Tom Igoe Memory Test
> //************************************************************************
>
> #include "WProgram.h"
> #include "HardwareSerial.h"
> #include
>
> //************************************************************************
> void setup()
> {
> int startMemoryUsage;
> /*
> * Create variable for the tests.
> */
>
> String webColor = "#000000";
>
> int red = 1023/4;
> int blue = 512/4;
> int green = 128/4;
>
> /*
> * initiate the test run
> */
> //Record starting memory amount
> startMemoryUsage = ATS_GetFreeMemory();
> //Begin test run
> ATS_begin("Arduino", "Tom Igoe Memory Test");
>
> webColor = "#";
> webColor += String(red, HEX);
> webColor += String(green, HEX);
> webColor += String(blue, HEX);
>
> ATS_ReportMemoryUsage(startMemoryUsage);
>
> /*
> * Test complete
> */
>
> ATS_end();
> }
>
>
> //************************************************************************
> void loop()
> {
>
>
> }
>
>
>
>
> On Mon, Jan 3, 2011 at 9:35 PM, Tom Igoe <> wrote:
> > It broke in the non-SDM version too, but it took longer to break. In the
> SDM version it breaks immediately. So it looks like whatever you did
> highlights the faults sooner, which is good. It also points to a need for an
> error response of some sort, in answer to your question last mail.
> >
> > t.
> >
> > On Jan 3, 2011, at 4:44 PM, Alexander Brevig wrote:
> >
> >> That breaking of String, does it only occur with the SDM version?
> >>
> >> If not, did you find any way to break it? Maybe any of the old faults
> related to memory?
> >>
> >>
> >> I actually have no time to check this myself right now, so I opted to
> just ask you.
> >>
> >> On Mon, Jan 3, 2011 at 10:35 PM, Tom Igoe <> wrote:
> >> Thanks, Alexander, and sorry for the delay.
> >>
> >> A few tests:
> >>
> >> For code that doesn't change the strings much, there's not a big
> difference, a couple dozen bytes' difference in code size. However, when
> you start to do dynamic things, it does add up. For example, the
> StringAppendOperator example is 4910 bytes in 0022, and 5148 bytes with the
> StaticDynamicMemory version. So it does start to take its toll, memory-wise.
> >>
> >> On some sketches it actually takes less memory. For example, the one
> below is 3738 bytes using the StaticDynamicMemory version, and 3986 bytes in
> 0022. However, it fails entirely on upload. When the value of (analog 0)/4
> is high (0xFF), it never gets out of the setup(). So there's still a pretty
> easy way to break String, even with these improvements.
> >>
> >>
> >> void setup() {
> >> Serial.begin(9600);
> >> Serial.println("Beginning");
> >> }
> >>
> >> void loop() {
> >>
> >> String webColor = "#";
> >>
> >> int red = analogRead(A0)/4;
> >> webColor += String(red, HEX);
> >> int green = analogRead(A1)/4;
> >> webColor += String(green, HEX);
> >> int blue = analogRead(A2)/4;
> >>
> >> webColor += String(blue, HEX);
> >> Serial.println(webColor);
> >> }
> >>
> >>
> >>
> >>
> >>
> >> On Dec 16, 2010, at 1:27 AM, Alexander Brevig wrote:
> >>
> >> > Attached is a zip containing WString.h and .cpp plus
> StaticDynamicMemory.h.
> >> > Take a backup of the original WString files, and extract this zip into
> the hardware/arduino/cores/arduino folder.
> >> >
> >> > Now you're ready to test the modified String library, that does not
> fragment the heap.
> >> >
> >> >
> >> > In the WString header there is a #define called STRING_BUFFER which is
> set to 100 for now, change this to suit your test needs.
> >> >
> >> >
> >> > No error handling is implemented, what do you think we need?
> >> >
> >> > I plan to add an availableMemory():int method to the SDM library, and
> maybe some error flags and checks like hasError():int error
> >> >
> >> > I also suspect that this library is a bit slower performance wise, but
> I think that's just a cost we'll have to pay to being able to play with
> dynamic strings.
> >> >
> >> >
> >> > Hope to get feedback from someone!
> >> >
> >> > On Thu, Dec 16, 2010 at 1:11 AM, Alan Burlison <
> > wrote:
> >> > On 15/12/2010 16:19, David A. Mellis wrote:
> >> >
> >> > I think you're right, but I also don't think that telling people to
> >> > use the standard C library functions is a solution either. Trying out
> >> > this String class seems like one way of pushing forwards towards a
> >> > compromise that provides both an easy-to-use API and a robust
> >> > implementation. For example, perhaps the buffer sizes need to be
> >> > specified or provided when the String is instantiated. Or we need an
> >> > alternative implementation that does more reliable memory allocation
> >> > (since we're not assuming that the internal buffer is continuous).
> >> > Other ideas welcome.
> >> >
> >> > I think the problem is that the failure modes are not benign. I
> haven't been through all the use cases so this might not work, but perhaps
> using a statically-allocated string ("NOMEM" ?) as a sentinel value instead
> of null when malloc fails might be one way? Also, there might be some
> benefit in making String immutable a la Java - overloaded operators in C++
> have a tendency to generate anonymous temporaries, which is going to lead to
> heap fragmentation as well.
> >> >
> >> > --
> >> > Alan Burlison
> >> > --
> >> >
> >> > _______________________________________________
___________________________________________________

Posted on the Developers mailing list. Go to http://arduino.cc/mailman/listinfo/developers_arduino.cc to subscribe. Is this test suite any different than the one in the github repo?

t.

On Jan 4, 2011, at 12:53 PM, Rick Anderson wrote:

> I just created a test and unpacked and tested it. I also created a
> test based on Tom's code. Not sure I caught the maximum value error
> for 0xFF.
>
> I also ran the tests for bug 411. All the tests compile, but there is
> still memory loss.
>
> I'm attaching the Arduino Test suite, and the test code so you can run
> them as you debug. Let me know if this was helpful.
>
> --Rick
>
> Test run results:
> Example: ATS_StringAssignmentTest.pde
> info.MANUFACTURER = Arduino
> info.CPU-NAME = ATmega328P
> info.GCC-Version = 4.3.2
> info.AVR-LibC-Ver = 1.6.4
> info.Compiled-date = Jan 4 2011
> info.Test-Suite-Name = ATS_StringAssignmentTest
> info.Free-memory = 1110 bytes
> Memory Usage (lost 59 bytes) ... FAIL
> --------------------------
> Ran 1 tests in 1.378s
>
> FAILED (failures=1)
>
>
> Example: ATS_StringMemoryTestPassByReference.pde
>
> info.MANUFACTURER = Arduino
> info.CPU-NAME = ATmega328P
> info.GCC-Version = 4.3.2
> info.AVR-LibC-Ver = 1.6.4
> info.Compiled-date = Jan 4 2011
> info.Test-Suite-Name = ATS_StringMemoryTestPassByReference
> info.Free-memory = 1120 bytes
> Memory Usage (lost 59 bytes) ... FAIL
> --------------------------
> Ran 1 tests in 1.389s
>
> FAILED (failures=1)
>
>
> Example: Tom Igoe Memory Test
> info.MANUFACTURER = Arduino
> info.CPU-NAME = ATmega328P
> info.GCC-Version = 4.3.2
> info.AVR-LibC-Ver = 1.6.4
> info.Compiled-date = Jan 4 2011
> info.Test-Suite-Name = Tom Igoe Memory Test
> info.Free-memory = 1328 bytes
> Memory Usage (lost 9 bytes) ... FAIL
> --------------------------
> Ran 1 tests in 1.374s
>
> FAILED (failures=1)
>
>
>
> --Rick
>
> Tom, rewrote your example as a test.
>
> //************************************************************************
> //* Arduino Tom Igoe Memory Test
> //* (C) 2010 by Rick Anderson
> //* Open source as per standard Arduino code
> //*
> //************************************************************************
> //* Jan 4, 2011 Started on Tom Igoe Memory Test
> //************************************************************************
>
> #include "WProgram.h"
> #include "HardwareSerial.h"
> #include
>
> //************************************************************************
> void setup()
> {
> int startMemoryUsage;
> /*
> * Create variable for the tests.
> */
>
> String webColor = "#000000";
>
> int red = 1023/4;
> int blue = 512/4;
> int green = 128/4;
>
> /*
> * initiate the test run
> */
> //Record starting memory amount
> startMemoryUsage = ATS_GetFreeMemory();
> //Begin test run
> ATS_begin("Arduino", "Tom Igoe Memory Test");
>
> webColor = "#";
> webColor += String(red, HEX);
> webColor += String(green, HEX);
> webColor += String(blue, HEX);
>
> ATS_ReportMemoryUsage(startMemoryUsage);
>
> /*
> * Test complete
> */
>
> ATS_end();
> }
>
>
> //************************************************************************
> void loop()
> {
>
>
> }
>
>
>
>
> On Mon, Jan 3, 2011 at 9:35 PM, Tom Igoe <> wrote:
>> It broke in the non-SDM version too, but it took longer to break. In the SDM version it breaks immediately. So it looks like whatever you did highlights the faults sooner, which is good. It also points to a need for an error response of some sort, in answer to your question last mail.
>>
>> t.
>>
>> On Jan 3, 2011, at 4:44 PM, Alexander Brevig wrote:
>>
>>> That breaking of String, does it only occur with the SDM version?
>>>
>>> If not, did you find any way to break it? Maybe any of the old faults related to memory?
>>>
>>>
>>> I actually have no time to check this myself right now, so I opted to just ask you.
>>>
>>> On Mon, Jan 3, 2011 at 10:35 PM, Tom Igoe <> wrote:
>>> Thanks, Alexander, and sorry for the delay.
>>>
>>> A few tests:
>>>
>>> For code that doesn't change the strings much, there's not a big difference, a couple dozen bytes' difference in code size. However, when you start to do dynamic things, it does add up. For example, the StringAppendOperator example is 4910 bytes in 0022, and 5148 bytes with the StaticDynamicMemory version. So it does start to take its toll, memory-wise.
>>>
>>> On some sketches it actually takes less memory. For example, the one below is 3738 bytes using the StaticDynamicMemory version, and 3986 bytes in 0022. However, it fails entirely on upload. When the value of (analog 0)/4 is high (0xFF), it never gets out of the setup(). So there's still a pretty easy way to break String, even with these improvements.
>>>
>>>
>>> void setup() {
>>> Serial.begin(9600);
>>> Serial.println("Beginning");
>>> }
>>>
>>> void loop() {
>>>
>>> String webColor = "#";
>>>
>>> int red = analogRead(A0)/4;
>>> webColor += String(red, HEX);
>>> int green = analogRead(A1)/4;
>>> webColor += String(green, HEX);
>>> int blue = analogRead(A2)/4;
>>>
>>> webColor += String(blue, HEX);
>>> Serial.println(webColor);
>>> }
>>>
>>>
>>>
>>>
>>>
>>> On Dec 16, 2010, at 1:27 AM, Alexander Brevig wrote:
>>>
>>>> Attached is a zip containing WString.h and .cpp plus StaticDynamicMemory.h.
>>>> Take a backup of the original WString files, and extract this zip into the hardware/arduino/cores/arduino folder.
>>>>
>>>> Now you're ready to test the modified String library, that does not fragment the heap.
>>>>
>>>>
>>>> In the WString header there is a #define called STRING_BUFFER which is set to 100 for now, change this to suit your test needs.
>>>>
>>>>
>>>> No error handling is implemented, what do you think we need?
>>>>
>>>> I plan to add an availableMemory():int method to the SDM library, and maybe some error flags and checks like hasError():int error
>>>>
>>>> I also suspect that this library is a bit slower performance wise, but I think that's just a cost we'll have to pay to being able to play with dynamic strings.
>>>>
>>>>
>>>> Hope to get feedback from someone!
>>>>
>>>> On Thu, Dec 16, 2010 at 1:11 AM, Alan Burlison <> wrote:
>>>> On 15/12/2010 16:19, David A. Mellis wrote:
>>>>
>>>> I think you're right, but I also don't think that telling people to
>>>> use the standard C library functions is a solution either. Trying out
>>>> this String class seems like one way of pushing forwards towards a
>>>> compromise that provides both an easy-to-use API and a robust
>>>> implementation. For example, perhaps the buffer sizes need to be
>>>> specified or provided when the String is instantiated. Or we need an
>>>> alternative implementation that does more reliable memory allocation
>>>> (since we're not assuming that the internal buffer is continuous).
>>>> Other ideas welcome.
>>>>
>>>> I think the problem is that the failure modes are not benign. I haven't been through all the use cases so this might not work, but perhaps using a statically-allocated string ("NOMEM" ?) as a sentinel value instead of null when malloc fails might be one way? Also, there might be some benefit in making String immutable a la Java - overloaded operators in C++ have a tendency to generate anonymous temporaries, which is going to lead to heap fragmentation as well.
>>>>
>>>> --
>>>> Alan Burlison
>>>> --
>>>>
>>>> _______________________________________________
___________________________________________________

Posted on the Developers mailing list. Go to http://arduino.cc/mailman/listinfo/developers_arduino.cc to subscribe. Same exact one. I just included it just in case.

--Rick

On Tue, Jan 4, 2011 at 9:01 PM, Tom Igoe <> wrote:
> Is this test suite any different than the one in the github repo?
>
> t.
>
> On Jan 4, 2011, at 12:53 PM, Rick Anderson wrote:
>
>> I just created a test and unpacked and tested it. I also created a
>> test based on Tom's code. Not sure I caught the maximum value error
>> for 0xFF.
>>
>> I also ran the tests for bug 411. All the tests compile, but there is
>> still memory loss.
>>
>> I'm attaching the Arduino Test suite, and the test code so you can run
>> them as you debug. Let me know if this was helpful.
>>
>> --Rick
>>
>> Test run results:
>> Example:  ATS_StringAssignmentTest.pde
>> info.MANUFACTURER    = Arduino
>> info.CPU-NAME        = ATmega328P
>> info.GCC-Version     = 4.3.2
>> info.AVR-LibC-Ver    = 1.6.4
>> info.Compiled-date   = Jan  4 2011
>> info.Test-Suite-Name = ATS_StringAssignmentTest
>> info.Free-memory     = 1110 bytes
>> Memory Usage (lost 59 bytes)                                ... FAIL
>> --------------------------
>> Ran 1 tests in 1.378s
>>
>> FAILED (failures=1)
>>
>>
>> Example: ATS_StringMemoryTestPassByReference.pde
>>
>> info.MANUFACTURER    = Arduino
>> info.CPU-NAME        = ATmega328P
>> info.GCC-Version     = 4.3.2
>> info.AVR-LibC-Ver    = 1.6.4
>> info.Compiled-date   = Jan  4 2011
>> info.Test-Suite-Name = ATS_StringMemoryTestPassByReference
>> info.Free-memory     = 1120 bytes
>> Memory Usage (lost 59 bytes)                                ... FAIL
>> --------------------------
>> Ran 1 tests in 1.389s
>>
>> FAILED (failures=1)
>>
>>
>> Example: Tom Igoe Memory Test
>> info.MANUFACTURER    = Arduino
>> info.CPU-NAME        = ATmega328P
>> info.GCC-Version     = 4.3.2
>> info.AVR-LibC-Ver    = 1.6.4
>> info.Compiled-date   = Jan  4 2011
>> info.Test-Suite-Name = Tom Igoe Memory Test
>> info.Free-memory     = 1328 bytes
>> Memory Usage (lost 9 bytes)                                 ... FAIL
>> --------------------------
>> Ran 1 tests in 1.374s
>>
>> FAILED (failures=1)
>>
>>
>>
>> --Rick
>>
>> Tom, rewrote your example as a test.
>>
>> //************************************************************************
>> //*   Arduino Tom Igoe Memory Test
>> //*           (C) 2010 by Rick Anderson
>> //*           Open source as per standard Arduino code
>> //*
>> //************************************************************************
>> //*   Jan 4,  2011     Started on Tom Igoe Memory Test
>> //************************************************************************
>>
>> #include      "WProgram.h"
>> #include      "HardwareSerial.h"
>> #include      
>>
>> //************************************************************************
>> void setup()
>> {
>>  int          startMemoryUsage;
>>  /*
>>    * Create variable for the tests.
>>   */
>>
>>  String webColor = "#000000";
>>
>>  int red = 1023/4;
>>  int blue = 512/4;
>>  int green = 128/4;
>>
>>  /*
>>  * initiate the test run
>>   */
>>  //Record starting memory amount
>>  startMemoryUsage     =       ATS_GetFreeMemory();
>>  //Begin test run
>>  ATS_begin("Arduino", "Tom Igoe Memory Test");
>>
>>  webColor = "#";
>>  webColor += String(red, HEX);
>>  webColor += String(green, HEX);
>>  webColor += String(blue, HEX);
>>
>>  ATS_ReportMemoryUsage(startMemoryUsage);
>>
>>  /*
>>   * Test complete
>>   */
>>
>>  ATS_end();
>> }
>>
>>
>> //************************************************************************
>> void loop()
>> {
>>
>>
>> }
>>
>>
>>
>>
>> On Mon, Jan 3, 2011 at 9:35 PM, Tom Igoe <> wrote:
>>> It broke in the non-SDM version too, but it took longer to break. In the SDM version it breaks immediately. So it looks like whatever you did highlights the faults sooner, which is good. It also points to a need for an error response of some sort, in answer to your question last mail.
>>>
>>> t.
>>>
>>> On Jan 3, 2011, at 4:44 PM, Alexander Brevig wrote:
>>>
>>>> That breaking of String, does it only occur with the SDM version?
>>>>
>>>> If not, did you find any way to break it? Maybe any of the old faults related to memory?
>>>>
>>>>
>>>> I actually have no time to check this myself right now, so I opted to just ask you.
>>>>
>>>> On Mon, Jan 3, 2011 at 10:35 PM, Tom Igoe <> wrote:
>>>> Thanks, Alexander, and sorry for the delay.
>>>>
>>>> A few tests:
>>>>
>>>> For code that doesn't change the strings much, there's not a big difference, a couple dozen bytes' difference in code size.  However, when you start to do dynamic things, it does add up.  For example, the StringAppendOperator example is  4910 bytes in 0022, and 5148 bytes with the StaticDynamicMemory version. So it does start to take its toll, memory-wise.
>>>>
>>>> On some sketches it actually takes less memory.  For example, the one below is 3738 bytes using the StaticDynamicMemory version, and 3986 bytes in 0022.  However, it fails entirely on upload.  When the value of (analog 0)/4 is high (0xFF), it never gets out of the setup(). So there's still a pretty easy way to break String, even with these improvements.
>>>>
>>>>
>>>> void setup() {
>>>>  Serial.begin(9600);
>>>>  Serial.println("Beginning");
>>>> }
>>>>
>>>> void loop() {
>>>>
>>>>  String webColor = "#";
>>>>
>>>>  int red = analogRead(A0)/4;
>>>>  webColor += String(red, HEX);
>>>>  int green = analogRead(A1)/4;
>>>>  webColor += String(green, HEX);
>>>>  int blue = analogRead(A2)/4;
>>>>
>>>>  webColor += String(blue, HEX);
>>>>  Serial.println(webColor);
>>>> }
>>>>
>>>>
>>>>
>>>>
>>>>
>>>> On Dec 16, 2010, at 1:27 AM, Alexander Brevig wrote:
>>>>
>>>>> Attached is a zip containing WString.h and .cpp plus StaticDynamicMemory.h.
>>>>> Take a backup of the original WString files, and extract this zip into the hardware/arduino/cores/arduino folder.
>>>>>
>>>>> Now you're ready to test the modified String library, that does not fragment the heap.
>>>>>
>>>>>
>>>>> In the WString header there is a #define called STRING_BUFFER which is set to 100 for now, change this to suit your test needs.
>>>>>
>>>>>
>>>>> No error handling is implemented, what do you think we need?
>>>>>
>>>>> I plan to add an availableMemory():int method to the SDM library, and maybe some error flags and checks like hasError():int error
>>>>>
>>>>> I also suspect that this library is a bit slower performance wise, but I think that's just a cost we'll have to pay to being able to play with dynamic strings.
>>>>>
>>>>>
>>>>> Hope to  get feedback from someone!
>>>>>
>>>>> On Thu, Dec 16, 2010 at 1:11 AM, Alan Burlison <> wrote:
>>>>> On 15/12/2010 16:19, David A. Mellis wrote:
>>>>>
>>>>> I think you're right, but I also don't think that telling people to
>>>>> use the standard C library functions is a solution either.  Trying out
>>>>> this String class seems like one way of pushing forwards towards a
>>>>> compromise that provides both an easy-to-use API and a robust
>>>>> implementation.  For example, perhaps the buffer sizes need to be
>>>>> specified or provided when the String is instantiated.  Or we need an
>>>>> alternative implementation that does more reliable memory allocation
>>>>> (since we're not assuming that the internal buffer is continuous).
>>>>> Other ideas welcome.
>>>>>
>>>>> I think the problem is that the failure modes are not benign.  I haven't been through all the use cases so this might not work, but perhaps using a statically-allocated string ("NOMEM" ?) as a sentinel value instead of null when malloc fails might be one way?  Also, there might be some benefit in making String immutable a la Java - overloaded operators in C++ have a tendency to generate anonymous temporaries, which is going to lead to heap fragmentation as well.
>>>>>
>>>>> --
>>>>> Alan Burlison
>>>>> --
>>>>>
>>>>> _______________________________________________
___________________________________________________

Posted on the Developers mailing list. Go to http://arduino.cc/mailman/listinfo/developers_arduino.cc to subscribe. On 04/01/2011 17:53, Rick Anderson wrote:

> I also ran the tests for bug 411. All the tests compile, but there is
> still memory loss.

Most of the assumptions made by the test harness and test case code are
wrong, any reports of 'lost' memory are therefore likely to be wrong as
well. If you want to do leak detection you can't do it in the naive way
it is being done at present.

--
Alan Burlison
--

_______________________________________________
___________________________________________________

Posted on the Developers mailing list. Go to http://arduino.cc/mailman/listinfo/developers_arduino.cc to subscribe. Alan,

The tests themselves are quick and dirty, and not strategic or
comprehensive. I'd like your input to create a good procedure for
memory testing. I also have feedback from Paul Stoffregen for the test
suite:
----
Another problem involves gcc's optimizer ignoring the inline request
for ATS_ReportMemoryUsage. As the comment in the code explains, it
must be inline to avoid measuring its own stack frame. I believe
adding this line in ArduinoTestSuite.h fixes the problem by forcing
gcc to inline.

inline void ATS_ReportMemoryUsage(int _memoryUsageAtStart)
__attribute__((always_inline, unused));

The last problem is a tiny bit of dynamic memory permanently held for
the free list. To allow for this, the test really should call
malloc() and free() once, so the allocator is fully initialized before
testing.
----

I'd like to combine both sets of feedback, and set up some issues in
the system, then fix them. Is the above the problem you saw? Are their
other assumptions that would impact measuring memory? And updating the
memory test in the the test suite.

In terms of creating tests for memory leaks. It looks best to move all
the memory usage inside a function. What else could be done to
constrain the problem, and measuring more affectively.

I'm traveling back to NJ today, so I can't respond right away.

--Rick

On Wed, Jan 5, 2011 at 8:52 AM, Alan Burlison <> wrote:
> On 04/01/2011 17:53, Rick Anderson wrote:
>
>> I also ran the tests for bug 411. All the tests compile, but there is
>> still memory loss.
>
> Most of the assumptions made by the test harness and test case code are
> wrong, any reports of 'lost' memory are therefore likely to be wrong as
> well.  If you want to do leak detection you can't do it in the naive way it
> is being done at present.
>
> --
> Alan Burlison
> --
>



--
President
Fair Use Building and Research (****) Labs
http://fubarlabs.org

_______________________________________________
___________________________________________________

Posted on the Developers mailing list. Go to http://arduino.cc/mailman/listinfo/developers_arduino.cc to subscribe. On 05/01/2011 15:19, Rick Anderson wrote:

> ----
> Another problem involves gcc's optimizer ignoring the inline request
> for ATS_ReportMemoryUsage. As the comment in the code explains, it
> must be inline to avoid measuring its own stack frame. I believe
> adding this line in ArduinoTestSuite.h fixes the problem by forcing
> gcc to inline.
>
> inline void ATS_ReportMemoryUsage(int _memoryUsageAtStart)
> __attribute__((always_inline, unused));

Yes, that's one of the problems. And even the __attribute__
'workaround' is a fragile hack.

> The last problem is a tiny bit of dynamic memory permanently held for
> the free list. To allow for this, the test really should call
> malloc() and free() once, so the allocator is fully initialized before

That's part of a problem, but an initial call malloc/free call isn't
guaranteed to make all the issues go away either. From looking at the
avr-libc malloc implementation it does try to coalesce the heap, but
relying on multiple malloc implementation artefacts is a really bad idea
- there's no guarantee that future malloc implementations will always
coalesce on every free, and there's no guarantee that __bss_end or
__brkval will always be adjusted on each malloc/free call.

The other issue is that of object lifetimes. The test code has
instances of String objects which are allocated on the stack and that
are still in scope when the 'leak' memory check is performed. That
means the String destructors won't have been called and the dynamically
allocated part of the String will still be allocated.

A true memory leak is a block of allocated memory that has no references
to it. However that's not what the test code is checking for. If a
library routine used malloc to perform a one-time library-private buffer
allocation where the buffer is retained for the lifetime of the program,
the current leak checking would incorrectly report that as a leak. It
isn't a leak because there's still a reference to the block inside the
library.

The only semi-reliable way to do what you want is to use an instrumented
malloc implementation, and that's going to be very difficult to
implement on a constrained platform such as the AVR. If you want to
test the String implementation for leaks, my advice is to do it on a
more capable platform (e.g. *nix) and use one of the many instrumented
mallocs that are available.

--
Alan Burlison
--

_______________________________________________
___________________________________________________

Posted on the Developers mailing list. Go to http://arduino.cc/mailman/listinfo/developers_arduino.cc to subscribe. Slightly unrelated to what you guys are discussing now but:
I'm not sure if I've made this clear, but the new version of String that I'm
working on now does not use malloc or any other c function for dynamic
memory. What happens is that I allocate memory statically on the stack and
serve that memory dynamically to the instances of String.

I have some time on my hands now and have a look at getting the += not to
break the code

On Wed, Jan 5, 2011 at 7:10 PM, Alan Burlison <>wrote:

> On 05/01/2011 15:19, Rick Anderson wrote:
>
> ----
>> Another problem involves gcc's optimizer ignoring the inline request
>> for ATS_ReportMemoryUsage. As the comment in the code explains, it
>> must be inline to avoid measuring its own stack frame. I believe
>> adding this line in ArduinoTestSuite.h fixes the problem by forcing
>> gcc to inline.
>>
>> inline void ATS_ReportMemoryUsage(int _memoryUsageAtStart)
>> __attribute__((always_inline, unused));
>>
>
> Yes, that's one of the problems. And even the __attribute__ 'workaround'
> is a fragile hack.
>
>
> The last problem is a tiny bit of dynamic memory permanently held for
>> the free list. To allow for this, the test really should call
>> malloc() and free() once, so the allocator is fully initialized before
>>
>
> That's part of a problem, but an initial call malloc/free call isn't
> guaranteed to make all the issues go away either. From looking at the
> avr-libc malloc implementation it does try to coalesce the heap, but relying
> on multiple malloc implementation artefacts is a really bad idea - there's
> no guarantee that future malloc implementations will always coalesce on
> every free, and there's no guarantee that __bss_end or __brkval will always
> be adjusted on each malloc/free call.
>
> The other issue is that of object lifetimes. The test code has instances
> of String objects which are allocated on the stack and that are still in
> scope when the 'leak' memory check is performed. That means the String
> destructors won't have been called and the dynamically allocated part of the
> String will still be allocated.
>
> A true memory leak is a block of allocated memory that has no references to
> it. However that's not what the test code is checking for. If a library
> routine used malloc to perform a one-time library-private buffer allocation
> where the buffer is retained for the lifetime of the program, the current
> leak checking would incorrectly report that as a leak. It isn't a leak
> because there's still a reference to the block inside the library.
>
> The only semi-reliable way to do what you want is to use an instrumented
> malloc implementation, and that's going to be very difficult to implement on
> a constrained platform such as the AVR. If you want to test the String
> implementation for leaks, my advice is to do it on a more capable platform
> (e.g. *nix) and use one of the many instrumented mallocs that are available.
>
> --
> Alan Burlison
> --
>
>
> _______________________________________________
___________________________________________________

Posted on the Developers mailing list. Go to http://arduino.cc/mailman/listinfo/developers_arduino.cc to subscribe. On 05/01/2011 18:25, Alexander Brevig wrote:

> Slightly unrelated to what you guys are discussing now but:
> I'm not sure if I've made this clear, but the new version of String that I'm
> working on now does not use malloc or any other c function for dynamic
> memory. What happens is that I allocate memory statically on the stack and
> serve that memory dynamically to the instances of String.

Does that mean that the total space occupied by all Strings has to be
decided up front? If so, what is the behaviour when an allocation fails?

To be honest I don't really see the point of doing this - all you are
doing is re-implementing malloc.

--
Alan Burlison
--

_______________________________________________
___________________________________________________

Posted on the Developers mailing list. Go to http://arduino.cc/mailman/listinfo/developers_arduino.cc to subscribe.

  #11  
05-01-2011 06:42 PM
Developers member admin is online now
User
 

That breaking of String, does it only occur with the SDM version?

If not, did you find any way to break it? Maybe any of the old faults
related to memory?


I actually have no time to check this myself right now, so I opted to just
ask you.

On Mon, Jan 3, 2011 at 10:35 PM, Tom Igoe <> wrote:

> Thanks, Alexander, and sorry for the delay.
>
> A few tests:
>
> For code that doesn't change the strings much, there's not a big
> difference, a couple dozen bytes' difference in code size. However, when
> you start to do dynamic things, it does add up. For example, the
> StringAppendOperator example is 4910 bytes in 0022, and 5148 bytes with the
> StaticDynamicMemory version. So it does start to take its toll, memory-wise.
>
> On some sketches it actually takes less memory. For example, the one below
> is 3738 bytes using the StaticDynamicMemory version, and 3986 bytes in 0022.
> However, it fails entirely on upload. When the value of (analog 0)/4 is
> high (0xFF), it never gets out of the setup(). So there's still a pretty
> easy way to break String, even with these improvements.
>
>
> void setup() {
> Serial.begin(9600);
> Serial.println("Beginning");
> }
>
> void loop() {
>
> String webColor = "#";
>
> int red = analogRead(A0)/4;
> webColor += String(red, HEX);
> int green = analogRead(A1)/4;
> webColor += String(green, HEX);
> int blue = analogRead(A2)/4;
>
> webColor += String(blue, HEX);
> Serial.println(webColor);
> }
>
>
>
>
>
> On Dec 16, 2010, at 1:27 AM, Alexander Brevig wrote:
>
> > Attached is a zip containing WString.h and .cpp plus
> StaticDynamicMemory.h.
> > Take a backup of the original WString files, and extract this zip into
> the hardware/arduino/cores/arduino folder.
> >
> > Now you're ready to test the modified String library, that does not
> fragment the heap.
> >
> >
> > In the WString header there is a #define called STRING_BUFFER which is
> set to 100 for now, change this to suit your test needs.
> >
> >
> > No error handling is implemented, what do you think we need?
> >
> > I plan to add an availableMemory():int method to the SDM library, and
> maybe some error flags and checks like hasError():int error
> >
> > I also suspect that this library is a bit slower performance wise, but I
> think that's just a cost we'll have to pay to being able to play with
> dynamic strings.
> >
> >
> > Hope to get feedback from someone!
> >
> > On Thu, Dec 16, 2010 at 1:11 AM, Alan Burlison <>
> wrote:
> > On 15/12/2010 16:19, David A. Mellis wrote:
> >
> > I think you're right, but I also don't think that telling people to
> > use the standard C library functions is a solution either. Trying out
> > this String class seems like one way of pushing forwards towards a
> > compromise that provides both an easy-to-use API and a robust
> > implementation. For example, perhaps the buffer sizes need to be
> > specified or provided when the String is instantiated. Or we need an
> > alternative implementation that does more reliable memory allocation
> > (since we're not assuming that the internal buffer is continuous).
> > Other ideas welcome.
> >
> > I think the problem is that the failure modes are not benign. I haven't
> been through all the use cases so this might not work, but perhaps using a
> statically-allocated string ("NOMEM" ?) as a sentinel value instead of null
> when malloc fails might be one way? Also, there might be some benefit in
> making String immutable a la Java - overloaded operators in C++ have a
> tendency to generate anonymous temporaries, which is going to lead to heap
> fragmentation as well.
> >
> > --
> > Alan Burlison
> > --
> >
> > _______________________________________________
___________________________________________________

Posted on the Developers mailing list. Go to http://arduino.cc/mailman/listinfo/developers_arduino.cc to subscribe. It broke in the non-SDM version too, but it took longer to break. In the SDM version it breaks immediately. So it looks like whatever you did highlights the faults sooner, which is good. It also points to a need for an error response of some sort, in answer to your question last mail.

t.

On Jan 3, 2011, at 4:44 PM, Alexander Brevig wrote:

> That breaking of String, does it only occur with the SDM version?
>
> If not, did you find any way to break it? Maybe any of the old faults related to memory?
>
>
> I actually have no time to check this myself right now, so I opted to just ask you.
>
> On Mon, Jan 3, 2011 at 10:35 PM, Tom Igoe <> wrote:
> Thanks, Alexander, and sorry for the delay.
>
> A few tests:
>
> For code that doesn't change the strings much, there's not a big difference, a couple dozen bytes' difference in code size. However, when you start to do dynamic things, it does add up. For example, the StringAppendOperator example is 4910 bytes in 0022, and 5148 bytes with the StaticDynamicMemory version. So it does start to take its toll, memory-wise.
>
> On some sketches it actually takes less memory. For example, the one below is 3738 bytes using the StaticDynamicMemory version, and 3986 bytes in 0022. However, it fails entirely on upload. When the value of (analog 0)/4 is high (0xFF), it never gets out of the setup(). So there's still a pretty easy way to break String, even with these improvements.
>
>
> void setup() {
> Serial.begin(9600);
> Serial.println("Beginning");
> }
>
> void loop() {
>
> String webColor = "#";
>
> int red = analogRead(A0)/4;
> webColor += String(red, HEX);
> int green = analogRead(A1)/4;
> webColor += String(green, HEX);
> int blue = analogRead(A2)/4;
>
> webColor += String(blue, HEX);
> Serial.println(webColor);
> }
>
>
>
>
>
> On Dec 16, 2010, at 1:27 AM, Alexander Brevig wrote:
>
> > Attached is a zip containing WString.h and .cpp plus StaticDynamicMemory.h.
> > Take a backup of the original WString files, and extract this zip into the hardware/arduino/cores/arduino folder.
> >
> > Now you're ready to test the modified String library, that does not fragment the heap.
> >
> >
> > In the WString header there is a #define called STRING_BUFFER which is set to 100 for now, change this to suit your test needs.
> >
> >
> > No error handling is implemented, what do you think we need?
> >
> > I plan to add an availableMemory():int method to the SDM library, and maybe some error flags and checks like hasError():int error
> >
> > I also suspect that this library is a bit slower performance wise, but I think that's just a cost we'll have to pay to being able to play with dynamic strings.
> >
> >
> > Hope to get feedback from someone!
> >
> > On Thu, Dec 16, 2010 at 1:11 AM, Alan Burlison <> wrote:
> > On 15/12/2010 16:19, David A. Mellis wrote:
> >
> > I think you're right, but I also don't think that telling people to
> > use the standard C library functions is a solution either. Trying out
> > this String class seems like one way of pushing forwards towards a
> > compromise that provides both an easy-to-use API and a robust
> > implementation. For example, perhaps the buffer sizes need to be
> > specified or provided when the String is instantiated. Or we need an
> > alternative implementation that does more reliable memory allocation
> > (since we're not assuming that the internal buffer is continuous).
> > Other ideas welcome.
> >
> > I think the problem is that the failure modes are not benign. I haven't been through all the use cases so this might not work, but perhaps using a statically-allocated string ("NOMEM" ?) as a sentinel value instead of null when malloc fails might be one way? Also, there might be some benefit in making String immutable a la Java - overloaded operators in C++ have a tendency to generate anonymous temporaries, which is going to lead to heap fragmentation as well.
> >
> > --
> > Alan Burlison
> > --
> >
> > _______________________________________________
___________________________________________________

Posted on the Developers mailing list. Go to http://arduino.cc/mailman/listinfo/developers_arduino.cc to subscribe. There seems to be a bug with the assignment operator, I'm on it and I'll get
back to you as soon as I get something done.

Thank you for your tests and feedback.


I'll do some tests on my own before I repost it here.

On Tue, Jan 4, 2011 at 6:53 PM, Rick Anderson
<>wrote:

> I just created a test and unpacked and tested it. I also created a
> test based on Tom's code. Not sure I caught the maximum value error
> for 0xFF.
>
> I also ran the tests for bug 411. All the tests compile, but there is
> still memory loss.
>
> I'm attaching the Arduino Test suite, and the test code so you can run
> them as you debug. Let me know if this was helpful.
>
> --Rick
>
> Test run results:
> Example: ATS_StringAssignmentTest.pde
> info.MANUFACTURER = Arduino
> info.CPU-NAME = ATmega328P
> info.GCC-Version = 4.3.2
> info.AVR-LibC-Ver = 1.6.4
> info.Compiled-date = Jan 4 2011
> info.Test-Suite-Name = ATS_StringAssignmentTest
> info.Free-memory = 1110 bytes
> Memory Usage (lost 59 bytes) ... FAIL
> --------------------------
> Ran 1 tests in 1.378s
>
> FAILED (failures=1)
>
>
> Example: ATS_StringMemoryTestPassByReference.pde
>
> info.MANUFACTURER = Arduino
> info.CPU-NAME = ATmega328P
> info.GCC-Version = 4.3.2
> info.AVR-LibC-Ver = 1.6.4
> info.Compiled-date = Jan 4 2011
> info.Test-Suite-Name = ATS_StringMemoryTestPassByReference
> info.Free-memory = 1120 bytes
> Memory Usage (lost 59 bytes) ... FAIL
> --------------------------
> Ran 1 tests in 1.389s
>
> FAILED (failures=1)
>
>
> Example: Tom Igoe Memory Test
> info.MANUFACTURER = Arduino
> info.CPU-NAME = ATmega328P
> info.GCC-Version = 4.3.2
> info.AVR-LibC-Ver = 1.6.4
> info.Compiled-date = Jan 4 2011
> info.Test-Suite-Name = Tom Igoe Memory Test
> info.Free-memory = 1328 bytes
> Memory Usage (lost 9 bytes) ... FAIL
> --------------------------
> Ran 1 tests in 1.374s
>
> FAILED (failures=1)
>
>
>
> --Rick
>
> Tom, rewrote your example as a test.
>
> //************************************************************************
> //* Arduino Tom Igoe Memory Test
> //* (C) 2010 by Rick Anderson
> //* Open source as per standard Arduino code
> //*
> //************************************************************************
> //* Jan 4, 2011 Started on Tom Igoe Memory Test
> //************************************************************************
>
> #include "WProgram.h"
> #include "HardwareSerial.h"
> #include
>
> //************************************************************************
> void setup()
> {
> int startMemoryUsage;
> /*
> * Create variable for the tests.
> */
>
> String webColor = "#000000";
>
> int red = 1023/4;
> int blue = 512/4;
> int green = 128/4;
>
> /*
> * initiate the test run
> */
> //Record starting memory amount
> startMemoryUsage = ATS_GetFreeMemory();
> //Begin test run
> ATS_begin("Arduino", "Tom Igoe Memory Test");
>
> webColor = "#";
> webColor += String(red, HEX);
> webColor += String(green, HEX);
> webColor += String(blue, HEX);
>
> ATS_ReportMemoryUsage(startMemoryUsage);
>
> /*
> * Test complete
> */
>
> ATS_end();
> }
>
>
> //************************************************************************
> void loop()
> {
>
>
> }
>
>
>
>
> On Mon, Jan 3, 2011 at 9:35 PM, Tom Igoe <> wrote:
> > It broke in the non-SDM version too, but it took longer to break. In the
> SDM version it breaks immediately. So it looks like whatever you did
> highlights the faults sooner, which is good. It also points to a need for an
> error response of some sort, in answer to your question last mail.
> >
> > t.
> >
> > On Jan 3, 2011, at 4:44 PM, Alexander Brevig wrote:
> >
> >> That breaking of String, does it only occur with the SDM version?
> >>
> >> If not, did you find any way to break it? Maybe any of the old faults
> related to memory?
> >>
> >>
> >> I actually have no time to check this myself right now, so I opted to
> just ask you.
> >>
> >> On Mon, Jan 3, 2011 at 10:35 PM, Tom Igoe <> wrote:
> >> Thanks, Alexander, and sorry for the delay.
> >>
> >> A few tests:
> >>
> >> For code that doesn't change the strings much, there's not a big
> difference, a couple dozen bytes' difference in code size. However, when
> you start to do dynamic things, it does add up. For example, the
> StringAppendOperator example is 4910 bytes in 0022, and 5148 bytes with the
> StaticDynamicMemory version. So it does start to take its toll, memory-wise.
> >>
> >> On some sketches it actually takes less memory. For example, the one
> below is 3738 bytes using the StaticDynamicMemory version, and 3986 bytes in
> 0022. However, it fails entirely on upload. When the value of (analog 0)/4
> is high (0xFF), it never gets out of the setup(). So there's still a pretty
> easy way to break String, even with these improvements.
> >>
> >>
> >> void setup() {
> >> Serial.begin(9600);
> >> Serial.println("Beginning");
> >> }
> >>
> >> void loop() {
> >>
> >> String webColor = "#";
> >>
> >> int red = analogRead(A0)/4;
> >> webColor += String(red, HEX);
> >> int green = analogRead(A1)/4;
> >> webColor += String(green, HEX);
> >> int blue = analogRead(A2)/4;
> >>
> >> webColor += String(blue, HEX);
> >> Serial.println(webColor);
> >> }
> >>
> >>
> >>
> >>
> >>
> >> On Dec 16, 2010, at 1:27 AM, Alexander Brevig wrote:
> >>
> >> > Attached is a zip containing WString.h and .cpp plus
> StaticDynamicMemory.h.
> >> > Take a backup of the original WString files, and extract this zip into
> the hardware/arduino/cores/arduino folder.
> >> >
> >> > Now you're ready to test the modified String library, that does not
> fragment the heap.
> >> >
> >> >
> >> > In the WString header there is a #define called STRING_BUFFER which is
> set to 100 for now, change this to suit your test needs.
> >> >
> >> >
> >> > No error handling is implemented, what do you think we need?
> >> >
> >> > I plan to add an availableMemory():int method to the SDM library, and
> maybe some error flags and checks like hasError():int error
> >> >
> >> > I also suspect that this library is a bit slower performance wise, but
> I think that's just a cost we'll have to pay to being able to play with
> dynamic strings.
> >> >
> >> >
> >> > Hope to get feedback from someone!
> >> >
> >> > On Thu, Dec 16, 2010 at 1:11 AM, Alan Burlison <
> > wrote:
> >> > On 15/12/2010 16:19, David A. Mellis wrote:
> >> >
> >> > I think you're right, but I also don't think that telling people to
> >> > use the standard C library functions is a solution either. Trying out
> >> > this String class seems like one way of pushing forwards towards a
> >> > compromise that provides both an easy-to-use API and a robust
> >> > implementation. For example, perhaps the buffer sizes need to be
> >> > specified or provided when the String is instantiated. Or we need an
> >> > alternative implementation that does more reliable memory allocation
> >> > (since we're not assuming that the internal buffer is continuous).
> >> > Other ideas welcome.
> >> >
> >> > I think the problem is that the failure modes are not benign. I
> haven't been through all the use cases so this might not work, but perhaps
> using a statically-allocated string ("NOMEM" ?) as a sentinel value instead
> of null when malloc fails might be one way? Also, there might be some
> benefit in making String immutable a la Java - overloaded operators in C++
> have a tendency to generate anonymous temporaries, which is going to lead to
> heap fragmentation as well.
> >> >
> >> > --
> >> > Alan Burlison
> >> > --
> >> >
> >> > _______________________________________________
___________________________________________________

Posted on the Developers mailing list. Go to http://arduino.cc/mailman/listinfo/developers_arduino.cc to subscribe. Is this test suite any different than the one in the github repo?

t.

On Jan 4, 2011, at 12:53 PM, Rick Anderson wrote:

> I just created a test and unpacked and tested it. I also created a
> test based on Tom's code. Not sure I caught the maximum value error
> for 0xFF.
>
> I also ran the tests for bug 411. All the tests compile, but there is
> still memory loss.
>
> I'm attaching the Arduino Test suite, and the test code so you can run
> them as you debug. Let me know if this was helpful.
>
> --Rick
>
> Test run results:
> Example: ATS_StringAssignmentTest.pde
> info.MANUFACTURER = Arduino
> info.CPU-NAME = ATmega328P
> info.GCC-Version = 4.3.2
> info.AVR-LibC-Ver = 1.6.4
> info.Compiled-date = Jan 4 2011
> info.Test-Suite-Name = ATS_StringAssignmentTest
> info.Free-memory = 1110 bytes
> Memory Usage (lost 59 bytes) ... FAIL
> --------------------------
> Ran 1 tests in 1.378s
>
> FAILED (failures=1)
>
>
> Example: ATS_StringMemoryTestPassByReference.pde
>
> info.MANUFACTURER = Arduino
> info.CPU-NAME = ATmega328P
> info.GCC-Version = 4.3.2
> info.AVR-LibC-Ver = 1.6.4
> info.Compiled-date = Jan 4 2011
> info.Test-Suite-Name = ATS_StringMemoryTestPassByReference
> info.Free-memory = 1120 bytes
> Memory Usage (lost 59 bytes) ... FAIL
> --------------------------
> Ran 1 tests in 1.389s
>
> FAILED (failures=1)
>
>
> Example: Tom Igoe Memory Test
> info.MANUFACTURER = Arduino
> info.CPU-NAME = ATmega328P
> info.GCC-Version = 4.3.2
> info.AVR-LibC-Ver = 1.6.4
> info.Compiled-date = Jan 4 2011
> info.Test-Suite-Name = Tom Igoe Memory Test
> info.Free-memory = 1328 bytes
> Memory Usage (lost 9 bytes) ... FAIL
> --------------------------
> Ran 1 tests in 1.374s
>
> FAILED (failures=1)
>
>
>
> --Rick
>
> Tom, rewrote your example as a test.
>
> //************************************************************************
> //* Arduino Tom Igoe Memory Test
> //* (C) 2010 by Rick Anderson
> //* Open source as per standard Arduino code
> //*
> //************************************************************************
> //* Jan 4, 2011 Started on Tom Igoe Memory Test
> //************************************************************************
>
> #include "WProgram.h"
> #include "HardwareSerial.h"
> #include
>
> //************************************************************************
> void setup()
> {
> int startMemoryUsage;
> /*
> * Create variable for the tests.
> */
>
> String webColor = "#000000";
>
> int red = 1023/4;
> int blue = 512/4;
> int green = 128/4;
>
> /*
> * initiate the test run
> */
> //Record starting memory amount
> startMemoryUsage = ATS_GetFreeMemory();
> //Begin test run
> ATS_begin("Arduino", "Tom Igoe Memory Test");
>
> webColor = "#";
> webColor += String(red, HEX);
> webColor += String(green, HEX);
> webColor += String(blue, HEX);
>
> ATS_ReportMemoryUsage(startMemoryUsage);
>
> /*
> * Test complete
> */
>
> ATS_end();
> }
>
>
> //************************************************************************
> void loop()
> {
>
>
> }
>
>
>
>
> On Mon, Jan 3, 2011 at 9:35 PM, Tom Igoe <> wrote:
>> It broke in the non-SDM version too, but it took longer to break. In the SDM version it breaks immediately. So it looks like whatever you did highlights the faults sooner, which is good. It also points to a need for an error response of some sort, in answer to your question last mail.
>>
>> t.
>>
>> On Jan 3, 2011, at 4:44 PM, Alexander Brevig wrote:
>>
>>> That breaking of String, does it only occur with the SDM version?
>>>
>>> If not, did you find any way to break it? Maybe any of the old faults related to memory?
>>>
>>>
>>> I actually have no time to check this myself right now, so I opted to just ask you.
>>>
>>> On Mon, Jan 3, 2011 at 10:35 PM, Tom Igoe <> wrote:
>>> Thanks, Alexander, and sorry for the delay.
>>>
>>> A few tests:
>>>
>>> For code that doesn't change the strings much, there's not a big difference, a couple dozen bytes' difference in code size. However, when you start to do dynamic things, it does add up. For example, the StringAppendOperator example is 4910 bytes in 0022, and 5148 bytes with the StaticDynamicMemory version. So it does start to take its toll, memory-wise.
>>>
>>> On some sketches it actually takes less memory. For example, the one below is 3738 bytes using the StaticDynamicMemory version, and 3986 bytes in 0022. However, it fails entirely on upload. When the value of (analog 0)/4 is high (0xFF), it never gets out of the setup(). So there's still a pretty easy way to break String, even with these improvements.
>>>
>>>
>>> void setup() {
>>> Serial.begin(9600);
>>> Serial.println("Beginning");
>>> }
>>>
>>> void loop() {
>>>
>>> String webColor = "#";
>>>
>>> int red = analogRead(A0)/4;
>>> webColor += String(red, HEX);
>>> int green = analogRead(A1)/4;
>>> webColor += String(green, HEX);
>>> int blue = analogRead(A2)/4;
>>>
>>> webColor += String(blue, HEX);
>>> Serial.println(webColor);
>>> }
>>>
>>>
>>>
>>>
>>>
>>> On Dec 16, 2010, at 1:27 AM, Alexander Brevig wrote:
>>>
>>>> Attached is a zip containing WString.h and .cpp plus StaticDynamicMemory.h.
>>>> Take a backup of the original WString files, and extract this zip into the hardware/arduino/cores/arduino folder.
>>>>
>>>> Now you're ready to test the modified String library, that does not fragment the heap.
>>>>
>>>>
>>>> In the WString header there is a #define called STRING_BUFFER which is set to 100 for now, change this to suit your test needs.
>>>>
>>>>
>>>> No error handling is implemented, what do you think we need?
>>>>
>>>> I plan to add an availableMemory():int method to the SDM library, and maybe some error flags and checks like hasError():int error
>>>>
>>>> I also suspect that this library is a bit slower performance wise, but I think that's just a cost we'll have to pay to being able to play with dynamic strings.
>>>>
>>>>
>>>> Hope to get feedback from someone!
>>>>
>>>> On Thu, Dec 16, 2010 at 1:11 AM, Alan Burlison <> wrote:
>>>> On 15/12/2010 16:19, David A. Mellis wrote:
>>>>
>>>> I think you're right, but I also don't think that telling people to
>>>> use the standard C library functions is a solution either. Trying out
>>>> this String class seems like one way of pushing forwards towards a
>>>> compromise that provides both an easy-to-use API and a robust
>>>> implementation. For example, perhaps the buffer sizes need to be
>>>> specified or provided when the String is instantiated. Or we need an
>>>> alternative implementation that does more reliable memory allocation
>>>> (since we're not assuming that the internal buffer is continuous).
>>>> Other ideas welcome.
>>>>
>>>> I think the problem is that the failure modes are not benign. I haven't been through all the use cases so this might not work, but perhaps using a statically-allocated string ("NOMEM" ?) as a sentinel value instead of null when malloc fails might be one way? Also, there might be some benefit in making String immutable a la Java - overloaded operators in C++ have a tendency to generate anonymous temporaries, which is going to lead to heap fragmentation as well.
>>>>
>>>> --
>>>> Alan Burlison
>>>> --
>>>>
>>>> _______________________________________________
___________________________________________________

Posted on the Developers mailing list. Go to http://arduino.cc/mailman/listinfo/developers_arduino.cc to subscribe. Same exact one. I just included it just in case.

--Rick

On Tue, Jan 4, 2011 at 9:01 PM, Tom Igoe <> wrote:
> Is this test suite any different than the one in the github repo?
>
> t.
>
> On Jan 4, 2011, at 12:53 PM, Rick Anderson wrote:
>
>> I just created a test and unpacked and tested it. I also created a
>> test based on Tom's code. Not sure I caught the maximum value error
>> for 0xFF.
>>
>> I also ran the tests for bug 411. All the tests compile, but there is
>> still memory loss.
>>
>> I'm attaching the Arduino Test suite, and the test code so you can run
>> them as you debug. Let me know if this was helpful.
>>
>> --Rick
>>
>> Test run results:
>> Example:  ATS_StringAssignmentTest.pde
>> info.MANUFACTURER    = Arduino
>> info.CPU-NAME        = ATmega328P
>> info.GCC-Version     = 4.3.2
>> info.AVR-LibC-Ver    = 1.6.4
>> info.Compiled-date   = Jan  4 2011
>> info.Test-Suite-Name = ATS_StringAssignmentTest
>> info.Free-memory     = 1110 bytes
>> Memory Usage (lost 59 bytes)                                ... FAIL
>> --------------------------
>> Ran 1 tests in 1.378s
>>
>> FAILED (failures=1)
>>
>>
>> Example: ATS_StringMemoryTestPassByReference.pde
>>
>> info.MANUFACTURER    = Arduino
>> info.CPU-NAME        = ATmega328P
>> info.GCC-Version     = 4.3.2
>> info.AVR-LibC-Ver    = 1.6.4
>> info.Compiled-date   = Jan  4 2011
>> info.Test-Suite-Name = ATS_StringMemoryTestPassByReference
>> info.Free-memory     = 1120 bytes
>> Memory Usage (lost 59 bytes)                                ... FAIL
>> --------------------------
>> Ran 1 tests in 1.389s
>>
>> FAILED (failures=1)
>>
>>
>> Example: Tom Igoe Memory Test
>> info.MANUFACTURER    = Arduino
>> info.CPU-NAME        = ATmega328P
>> info.GCC-Version     = 4.3.2
>> info.AVR-LibC-Ver    = 1.6.4
>> info.Compiled-date   = Jan  4 2011
>> info.Test-Suite-Name = Tom Igoe Memory Test
>> info.Free-memory     = 1328 bytes
>> Memory Usage (lost 9 bytes)                                 ... FAIL
>> --------------------------
>> Ran 1 tests in 1.374s
>>
>> FAILED (failures=1)
>>
>>
>>
>> --Rick
>>
>> Tom, rewrote your example as a test.
>>
>> //************************************************************************
>> //*   Arduino Tom Igoe Memory Test
>> //*           (C) 2010 by Rick Anderson
>> //*           Open source as per standard Arduino code
>> //*
>> //************************************************************************
>> //*   Jan 4,  2011     Started on Tom Igoe Memory Test
>> //************************************************************************
>>
>> #include      "WProgram.h"
>> #include      "HardwareSerial.h"
>> #include      
>>
>> //************************************************************************
>> void setup()
>> {
>>  int          startMemoryUsage;
>>  /*
>>    * Create variable for the tests.
>>   */
>>
>>  String webColor = "#000000";
>>
>>  int red = 1023/4;
>>  int blue = 512/4;
>>  int green = 128/4;
>>
>>  /*
>>  * initiate the test run
>>   */
>>  //Record starting memory amount
>>  startMemoryUsage     =       ATS_GetFreeMemory();
>>  //Begin test run
>>  ATS_begin("Arduino", "Tom Igoe Memory Test");
>>
>>  webColor = "#";
>>  webColor += String(red, HEX);
>>  webColor += String(green, HEX);
>>  webColor += String(blue, HEX);
>>
>>  ATS_ReportMemoryUsage(startMemoryUsage);
>>
>>  /*
>>   * Test complete
>>   */
>>
>>  ATS_end();
>> }
>>
>>
>> //************************************************************************
>> void loop()
>> {
>>
>>
>> }
>>
>>
>>
>>
>> On Mon, Jan 3, 2011 at 9:35 PM, Tom Igoe <> wrote:
>>> It broke in the non-SDM version too, but it took longer to break. In the SDM version it breaks immediately. So it looks like whatever you did highlights the faults sooner, which is good. It also points to a need for an error response of some sort, in answer to your question last mail.
>>>
>>> t.
>>>
>>> On Jan 3, 2011, at 4:44 PM, Alexander Brevig wrote:
>>>
>>>> That breaking of String, does it only occur with the SDM version?
>>>>
>>>> If not, did you find any way to break it? Maybe any of the old faults related to memory?
>>>>
>>>>
>>>> I actually have no time to check this myself right now, so I opted to just ask you.
>>>>
>>>> On Mon, Jan 3, 2011 at 10:35 PM, Tom Igoe <> wrote:
>>>> Thanks, Alexander, and sorry for the delay.
>>>>
>>>> A few tests:
>>>>
>>>> For code that doesn't change the strings much, there's not a big difference, a couple dozen bytes' difference in code size.  However, when you start to do dynamic things, it does add up.  For example, the StringAppendOperator example is  4910 bytes in 0022, and 5148 bytes with the StaticDynamicMemory version. So it does start to take its toll, memory-wise.
>>>>
>>>> On some sketches it actually takes less memory.  For example, the one below is 3738 bytes using the StaticDynamicMemory version, and 3986 bytes in 0022.  However, it fails entirely on upload.  When the value of (analog 0)/4 is high (0xFF), it never gets out of the setup(). So there's still a pretty easy way to break String, even with these improvements.
>>>>
>>>>
>>>> void setup() {
>>>>  Serial.begin(9600);
>>>>  Serial.println("Beginning");
>>>> }
>>>>
>>>> void loop() {
>>>>
>>>>  String webColor = "#";
>>>>
>>>>  int red = analogRead(A0)/4;
>>>>  webColor += String(red, HEX);
>>>>  int green = analogRead(A1)/4;
>>>>  webColor += String(green, HEX);
>>>>  int blue = analogRead(A2)/4;
>>>>
>>>>  webColor += String(blue, HEX);
>>>>  Serial.println(webColor);
>>>> }
>>>>
>>>>
>>>>
>>>>
>>>>
>>>> On Dec 16, 2010, at 1:27 AM, Alexander Brevig wrote:
>>>>
>>>>> Attached is a zip containing WString.h and .cpp plus StaticDynamicMemory.h.
>>>>> Take a backup of the original WString files, and extract this zip into the hardware/arduino/cores/arduino folder.
>>>>>
>>>>> Now you're ready to test the modified String library, that does not fragment the heap.
>>>>>
>>>>>
>>>>> In the WString header there is a #define called STRING_BUFFER which is set to 100 for now, change this to suit your test needs.
>>>>>
>>>>>
>>>>> No error handling is implemented, what do you think we need?
>>>>>
>>>>> I plan to add an availableMemory():int method to the SDM library, and maybe some error flags and checks like hasError():int error
>>>>>
>>>>> I also suspect that this library is a bit slower performance wise, but I think that's just a cost we'll have to pay to being able to play with dynamic strings.
>>>>>
>>>>>
>>>>> Hope to  get feedback from someone!
>>>>>
>>>>> On Thu, Dec 16, 2010 at 1:11 AM, Alan Burlison <> wrote:
>>>>> On 15/12/2010 16:19, David A. Mellis wrote:
>>>>>
>>>>> I think you're right, but I also don't think that telling people to
>>>>> use the standard C library functions is a solution either.  Trying out
>>>>> this String class seems like one way of pushing forwards towards a
>>>>> compromise that provides both an easy-to-use API and a robust
>>>>> implementation.  For example, perhaps the buffer sizes need to be
>>>>> specified or provided when the String is instantiated.  Or we need an
>>>>> alternative implementation that does more reliable memory allocation
>>>>> (since we're not assuming that the internal buffer is continuous).
>>>>> Other ideas welcome.
>>>>>
>>>>> I think the problem is that the failure modes are not benign.  I haven't been through all the use cases so this might not work, but perhaps using a statically-allocated string ("NOMEM" ?) as a sentinel value instead of null when malloc fails might be one way?  Also, there might be some benefit in making String immutable a la Java - overloaded operators in C++ have a tendency to generate anonymous temporaries, which is going to lead to heap fragmentation as well.
>>>>>
>>>>> --
>>>>> Alan Burlison
>>>>> --
>>>>>
>>>>> _______________________________________________
___________________________________________________

Posted on the Developers mailing list. Go to http://arduino.cc/mailman/listinfo/developers_arduino.cc to subscribe. On 04/01/2011 17:53, Rick Anderson wrote:

> I also ran the tests for bug 411. All the tests compile, but there is
> still memory loss.

Most of the assumptions made by the test harness and test case code are
wrong, any reports of 'lost' memory are therefore likely to be wrong as
well. If you want to do leak detection you can't do it in the naive way
it is being done at present.

--
Alan Burlison
--

_______________________________________________
___________________________________________________

Posted on the Developers mailing list. Go to http://arduino.cc/mailman/listinfo/developers_arduino.cc to subscribe. Alan,

The tests themselves are quick and dirty, and not strategic or
comprehensive. I'd like your input to create a good procedure for
memory testing. I also have feedback from Paul Stoffregen for the test
suite:
----
Another problem involves gcc's optimizer ignoring the inline request
for ATS_ReportMemoryUsage. As the comment in the code explains, it
must be inline to avoid measuring its own stack frame. I believe
adding this line in ArduinoTestSuite.h fixes the problem by forcing
gcc to inline.

inline void ATS_ReportMemoryUsage(int _memoryUsageAtStart)
__attribute__((always_inline, unused));

The last problem is a tiny bit of dynamic memory permanently held for
the free list. To allow for this, the test really should call
malloc() and free() once, so the allocator is fully initialized before
testing.
----

I'd like to combine both sets of feedback, and set up some issues in
the system, then fix them. Is the above the problem you saw? Are their
other assumptions that would impact measuring memory? And updating the
memory test in the the test suite.

In terms of creating tests for memory leaks. It looks best to move all
the memory usage inside a function. What else could be done to
constrain the problem, and measuring more affectively.

I'm traveling back to NJ today, so I can't respond right away.

--Rick

On Wed, Jan 5, 2011 at 8:52 AM, Alan Burlison <> wrote:
> On 04/01/2011 17:53, Rick Anderson wrote:
>
>> I also ran the tests for bug 411. All the tests compile, but there is
>> still memory loss.
>
> Most of the assumptions made by the test harness and test case code are
> wrong, any reports of 'lost' memory are therefore likely to be wrong as
> well.  If you want to do leak detection you can't do it in the naive way it
> is being done at present.
>
> --
> Alan Burlison
> --
>



--
President
Fair Use Building and Research (****) Labs
http://fubarlabs.org

_______________________________________________
___________________________________________________

Posted on the Developers mailing list. Go to http://arduino.cc/mailman/listinfo/developers_arduino.cc to subscribe. On 05/01/2011 15:19, Rick Anderson wrote:

> ----
> Another problem involves gcc's optimizer ignoring the inline request
> for ATS_ReportMemoryUsage. As the comment in the code explains, it
> must be inline to avoid measuring its own stack frame. I believe
> adding this line in ArduinoTestSuite.h fixes the problem by forcing
> gcc to inline.
>
> inline void ATS_ReportMemoryUsage(int _memoryUsageAtStart)
> __attribute__((always_inline, unused));

Yes, that's one of the problems. And even the __attribute__
'workaround' is a fragile hack.

> The last problem is a tiny bit of dynamic memory permanently held for
> the free list. To allow for this, the test really should call
> malloc() and free() once, so the allocator is fully initialized before

That's part of a problem, but an initial call malloc/free call isn't
guaranteed to make all the issues go away either. From looking at the
avr-libc malloc implementation it does try to coalesce the heap, but
relying on multiple malloc implementation artefacts is a really bad idea
- there's no guarantee that future malloc implementations will always
coalesce on every free, and there's no guarantee that __bss_end or
__brkval will always be adjusted on each malloc/free call.

The other issue is that of object lifetimes. The test code has
instances of String objects which are allocated on the stack and that
are still in scope when the 'leak' memory check is performed. That
means the String destructors won't have been called and the dynamically
allocated part of the String will still be allocated.

A true memory leak is a block of allocated memory that has no references
to it. However that's not what the test code is checking for. If a
library routine used malloc to perform a one-time library-private buffer
allocation where the buffer is retained for the lifetime of the program,
the current leak checking would incorrectly report that as a leak. It
isn't a leak because there's still a reference to the block inside the
library.

The only semi-reliable way to do what you want is to use an instrumented
malloc implementation, and that's going to be very difficult to
implement on a constrained platform such as the AVR. If you want to
test the String implementation for leaks, my advice is to do it on a
more capable platform (e.g. *nix) and use one of the many instrumented
mallocs that are available.

--
Alan Burlison
--

_______________________________________________
___________________________________________________

Posted on the Developers mailing list. Go to http://arduino.cc/mailman/listinfo/developers_arduino.cc to subscribe. Slightly unrelated to what you guys are discussing now but:
I'm not sure if I've made this clear, but the new version of String that I'm
working on now does not use malloc or any other c function for dynamic
memory. What happens is that I allocate memory statically on the stack and
serve that memory dynamically to the instances of String.

I have some time on my hands now and have a look at getting the += not to
break the code

On Wed, Jan 5, 2011 at 7:10 PM, Alan Burlison <>wrote:

> On 05/01/2011 15:19, Rick Anderson wrote:
>
> ----
>> Another problem involves gcc's optimizer ignoring the inline request
>> for ATS_ReportMemoryUsage. As the comment in the code explains, it
>> must be inline to avoid measuring its own stack frame. I believe
>> adding this line in ArduinoTestSuite.h fixes the problem by forcing
>> gcc to inline.
>>
>> inline void ATS_ReportMemoryUsage(int _memoryUsageAtStart)
>> __attribute__((always_inline, unused));
>>
>
> Yes, that's one of the problems. And even the __attribute__ 'workaround'
> is a fragile hack.
>
>
> The last problem is a tiny bit of dynamic memory permanently held for
>> the free list. To allow for this, the test really should call
>> malloc() and free() once, so the allocator is fully initialized before
>>
>
> That's part of a problem, but an initial call malloc/free call isn't
> guaranteed to make all the issues go away either. From looking at the
> avr-libc malloc implementation it does try to coalesce the heap, but relying
> on multiple malloc implementation artefacts is a really bad idea - there's
> no guarantee that future malloc implementations will always coalesce on
> every free, and there's no guarantee that __bss_end or __brkval will always
> be adjusted on each malloc/free call.
>
> The other issue is that of object lifetimes. The test code has instances
> of String objects which are allocated on the stack and that are still in
> scope when the 'leak' memory check is performed. That means the String
> destructors won't have been called and the dynamically allocated part of the
> String will still be allocated.
>
> A true memory leak is a block of allocated memory that has no references to
> it. However that's not what the test code is checking for. If a library
> routine used malloc to perform a one-time library-private buffer allocation
> where the buffer is retained for the lifetime of the program, the current
> leak checking would incorrectly report that as a leak. It isn't a leak
> because there's still a reference to the block inside the library.
>
> The only semi-reliable way to do what you want is to use an instrumented
> malloc implementation, and that's going to be very difficult to implement on
> a constrained platform such as the AVR. If you want to test the String
> implementation for leaks, my advice is to do it on a more capable platform
> (e.g. *nix) and use one of the many instrumented mallocs that are available.
>
> --
> Alan Burlison
> --
>
>
> _______________________________________________
___________________________________________________

Posted on the Developers mailing list. Go to http://arduino.cc/mailman/listinfo/developers_arduino.cc to subscribe. On 05/01/2011 18:25, Alexander Brevig wrote:

> Slightly unrelated to what you guys are discussing now but:
> I'm not sure if I've made this clear, but the new version of String that I'm
> working on now does not use malloc or any other c function for dynamic
> memory. What happens is that I allocate memory statically on the stack and
> serve that memory dynamically to the instances of String.

Does that mean that the total space occupied by all Strings has to be
decided up front? If so, what is the behaviour when an allocation fails?

To be honest I don't really see the point of doing this - all you are
doing is re-implementing malloc.

--
Alan Burlison
--

_______________________________________________
___________________________________________________

Posted on the Developers mailing list. Go to http://arduino.cc/mailman/listinfo/developers_arduino.cc to subscribe. No, actually I am not reimplementing malloc, because my algorithm guarantees
no fragmentation and always 100% effective use of the allocated memory.

"Does that mean that the total space occupied by all Strings has to be
decided up front? "
Yes, just like the buffer for the serial ++

I know I would opt to have the restriction for a predetermined allocated
space WITH error reporting (how we do is up to you guys, feed me with ideas
I'll implement whatever we agree is best) than having
seemingly infinite memory that crashes and burns.

On Wed, Jan 5, 2011 at 7:33 PM, Alan Burlison <>wrote:

> On 05/01/2011 18:25, Alexander Brevig wrote:
>
> Slightly unrelated to what you guys are discussing now but:
>> I'm not sure if I've made this clear, but the new version of String that
>> I'm
>> working on now does not use malloc or any other c function for dynamic
>> memory. What happens is that I allocate memory statically on the stack and
>> serve that memory dynamically to the instances of String.
>>
>
> Does that mean that the total space occupied by all Strings has to be
> decided up front? If so, what is the behaviour when an allocation fails?
>
> To be honest I don't really see the point of doing this - all you are doing
> is re-implementing malloc.
>
> --
> Alan Burlison
> --
>

  #12  
05-01-2011 07:01 PM
Developers member admin is online now
User
 

That breaking of String, does it only occur with the SDM version?

If not, did you find any way to break it? Maybe any of the old faults
related to memory?


I actually have no time to check this myself right now, so I opted to just
ask you.

On Mon, Jan 3, 2011 at 10:35 PM, Tom Igoe <> wrote:

> Thanks, Alexander, and sorry for the delay.
>
> A few tests:
>
> For code that doesn't change the strings much, there's not a big
> difference, a couple dozen bytes' difference in code size. However, when
> you start to do dynamic things, it does add up. For example, the
> StringAppendOperator example is 4910 bytes in 0022, and 5148 bytes with the
> StaticDynamicMemory version. So it does start to take its toll, memory-wise.
>
> On some sketches it actually takes less memory. For example, the one below
> is 3738 bytes using the StaticDynamicMemory version, and 3986 bytes in 0022.
> However, it fails entirely on upload. When the value of (analog 0)/4 is
> high (0xFF), it never gets out of the setup(). So there's still a pretty
> easy way to break String, even with these improvements.
>
>
> void setup() {
> Serial.begin(9600);
> Serial.println("Beginning");
> }
>
> void loop() {
>
> String webColor = "#";
>
> int red = analogRead(A0)/4;
> webColor += String(red, HEX);
> int green = analogRead(A1)/4;
> webColor += String(green, HEX);
> int blue = analogRead(A2)/4;
>
> webColor += String(blue, HEX);
> Serial.println(webColor);
> }
>
>
>
>
>
> On Dec 16, 2010, at 1:27 AM, Alexander Brevig wrote:
>
> > Attached is a zip containing WString.h and .cpp plus
> StaticDynamicMemory.h.
> > Take a backup of the original WString files, and extract this zip into
> the hardware/arduino/cores/arduino folder.
> >
> > Now you're ready to test the modified String library, that does not
> fragment the heap.
> >
> >
> > In the WString header there is a #define called STRING_BUFFER which is
> set to 100 for now, change this to suit your test needs.
> >
> >
> > No error handling is implemented, what do you think we need?
> >
> > I plan to add an availableMemory():int method to the SDM library, and
> maybe some error flags and checks like hasError():int error
> >
> > I also suspect that this library is a bit slower performance wise, but I
> think that's just a cost we'll have to pay to being able to play with
> dynamic strings.
> >
> >
> > Hope to get feedback from someone!
> >
> > On Thu, Dec 16, 2010 at 1:11 AM, Alan Burlison <>
> wrote:
> > On 15/12/2010 16:19, David A. Mellis wrote:
> >
> > I think you're right, but I also don't think that telling people to
> > use the standard C library functions is a solution either. Trying out
> > this String class seems like one way of pushing forwards towards a
> > compromise that provides both an easy-to-use API and a robust
> > implementation. For example, perhaps the buffer sizes need to be
> > specified or provided when the String is instantiated. Or we need an
> > alternative implementation that does more reliable memory allocation
> > (since we're not assuming that the internal buffer is continuous).
> > Other ideas welcome.
> >
> > I think the problem is that the failure modes are not benign. I haven't
> been through all the use cases so this might not work, but perhaps using a
> statically-allocated string ("NOMEM" ?) as a sentinel value instead of null
> when malloc fails might be one way? Also, there might be some benefit in
> making String immutable a la Java - overloaded operators in C++ have a
> tendency to generate anonymous temporaries, which is going to lead to heap
> fragmentation as well.
> >
> > --
> > Alan Burlison
> > --
> >
> > _______________________________________________
___________________________________________________

Posted on the Developers mailing list. Go to http://arduino.cc/mailman/listinfo/developers_arduino.cc to subscribe. It broke in the non-SDM version too, but it took longer to break. In the SDM version it breaks immediately. So it looks like whatever you did highlights the faults sooner, which is good. It also points to a need for an error response of some sort, in answer to your question last mail.

t.

On Jan 3, 2011, at 4:44 PM, Alexander Brevig wrote:

> That breaking of String, does it only occur with the SDM version?
>
> If not, did you find any way to break it? Maybe any of the old faults related to memory?
>
>
> I actually have no time to check this myself right now, so I opted to just ask you.
>
> On Mon, Jan 3, 2011 at 10:35 PM, Tom Igoe <> wrote:
> Thanks, Alexander, and sorry for the delay.
>
> A few tests:
>
> For code that doesn't change the strings much, there's not a big difference, a couple dozen bytes' difference in code size. However, when you start to do dynamic things, it does add up. For example, the StringAppendOperator example is 4910 bytes in 0022, and 5148 bytes with the StaticDynamicMemory version. So it does start to take its toll, memory-wise.
>
> On some sketches it actually takes less memory. For example, the one below is 3738 bytes using the StaticDynamicMemory version, and 3986 bytes in 0022. However, it fails entirely on upload. When the value of (analog 0)/4 is high (0xFF), it never gets out of the setup(). So there's still a pretty easy way to break String, even with these improvements.
>
>
> void setup() {
> Serial.begin(9600);
> Serial.println("Beginning");
> }
>
> void loop() {
>
> String webColor = "#";
>
> int red = analogRead(A0)/4;
> webColor += String(red, HEX);
> int green = analogRead(A1)/4;
> webColor += String(green, HEX);
> int blue = analogRead(A2)/4;
>
> webColor += String(blue, HEX);
> Serial.println(webColor);
> }
>
>
>
>
>
> On Dec 16, 2010, at 1:27 AM, Alexander Brevig wrote:
>
> > Attached is a zip containing WString.h and .cpp plus StaticDynamicMemory.h.
> > Take a backup of the original WString files, and extract this zip into the hardware/arduino/cores/arduino folder.
> >
> > Now you're ready to test the modified String library, that does not fragment the heap.
> >
> >
> > In the WString header there is a #define called STRING_BUFFER which is set to 100 for now, change this to suit your test needs.
> >
> >
> > No error handling is implemented, what do you think we need?
> >
> > I plan to add an availableMemory():int method to the SDM library, and maybe some error flags and checks like hasError():int error
> >
> > I also suspect that this library is a bit slower performance wise, but I think that's just a cost we'll have to pay to being able to play with dynamic strings.
> >
> >
> > Hope to get feedback from someone!
> >
> > On Thu, Dec 16, 2010 at 1:11 AM, Alan Burlison <> wrote:
> > On 15/12/2010 16:19, David A. Mellis wrote:
> >
> > I think you're right, but I also don't think that telling people to
> > use the standard C library functions is a solution either. Trying out
> > this String class seems like one way of pushing forwards towards a
> > compromise that provides both an easy-to-use API and a robust
> > implementation. For example, perhaps the buffer sizes need to be
> > specified or provided when the String is instantiated. Or we need an
> > alternative implementation that does more reliable memory allocation
> > (since we're not assuming that the internal buffer is continuous).
> > Other ideas welcome.
> >
> > I think the problem is that the failure modes are not benign. I haven't been through all the use cases so this might not work, but perhaps using a statically-allocated string ("NOMEM" ?) as a sentinel value instead of null when malloc fails might be one way? Also, there might be some benefit in making String immutable a la Java - overloaded operators in C++ have a tendency to generate anonymous temporaries, which is going to lead to heap fragmentation as well.
> >
> > --
> > Alan Burlison
> > --
> >
> > _______________________________________________
___________________________________________________

Posted on the Developers mailing list. Go to http://arduino.cc/mailman/listinfo/developers_arduino.cc to subscribe. There seems to be a bug with the assignment operator, I'm on it and I'll get
back to you as soon as I get something done.

Thank you for your tests and feedback.


I'll do some tests on my own before I repost it here.

On Tue, Jan 4, 2011 at 6:53 PM, Rick Anderson
<>wrote:

> I just created a test and unpacked and tested it. I also created a
> test based on Tom's code. Not sure I caught the maximum value error
> for 0xFF.
>
> I also ran the tests for bug 411. All the tests compile, but there is
> still memory loss.
>
> I'm attaching the Arduino Test suite, and the test code so you can run
> them as you debug. Let me know if this was helpful.
>
> --Rick
>
> Test run results:
> Example: ATS_StringAssignmentTest.pde
> info.MANUFACTURER = Arduino
> info.CPU-NAME = ATmega328P
> info.GCC-Version = 4.3.2
> info.AVR-LibC-Ver = 1.6.4
> info.Compiled-date = Jan 4 2011
> info.Test-Suite-Name = ATS_StringAssignmentTest
> info.Free-memory = 1110 bytes
> Memory Usage (lost 59 bytes) ... FAIL
> --------------------------
> Ran 1 tests in 1.378s
>
> FAILED (failures=1)
>
>
> Example: ATS_StringMemoryTestPassByReference.pde
>
> info.MANUFACTURER = Arduino
> info.CPU-NAME = ATmega328P
> info.GCC-Version = 4.3.2
> info.AVR-LibC-Ver = 1.6.4
> info.Compiled-date = Jan 4 2011
> info.Test-Suite-Name = ATS_StringMemoryTestPassByReference
> info.Free-memory = 1120 bytes
> Memory Usage (lost 59 bytes) ... FAIL
> --------------------------
> Ran 1 tests in 1.389s
>
> FAILED (failures=1)
>
>
> Example: Tom Igoe Memory Test
> info.MANUFACTURER = Arduino
> info.CPU-NAME = ATmega328P
> info.GCC-Version = 4.3.2
> info.AVR-LibC-Ver = 1.6.4
> info.Compiled-date = Jan 4 2011
> info.Test-Suite-Name = Tom Igoe Memory Test
> info.Free-memory = 1328 bytes
> Memory Usage (lost 9 bytes) ... FAIL
> --------------------------
> Ran 1 tests in 1.374s
>
> FAILED (failures=1)
>
>
>
> --Rick
>
> Tom, rewrote your example as a test.
>
> //************************************************************************
> //* Arduino Tom Igoe Memory Test
> //* (C) 2010 by Rick Anderson
> //* Open source as per standard Arduino code
> //*
> //************************************************************************
> //* Jan 4, 2011 Started on Tom Igoe Memory Test
> //************************************************************************
>
> #include "WProgram.h"
> #include "HardwareSerial.h"
> #include
>
> //************************************************************************
> void setup()
> {
> int startMemoryUsage;
> /*
> * Create variable for the tests.
> */
>
> String webColor = "#000000";
>
> int red = 1023/4;
> int blue = 512/4;
> int green = 128/4;
>
> /*
> * initiate the test run
> */
> //Record starting memory amount
> startMemoryUsage = ATS_GetFreeMemory();
> //Begin test run
> ATS_begin("Arduino", "Tom Igoe Memory Test");
>
> webColor = "#";
> webColor += String(red, HEX);
> webColor += String(green, HEX);
> webColor += String(blue, HEX);
>
> ATS_ReportMemoryUsage(startMemoryUsage);
>
> /*
> * Test complete
> */
>
> ATS_end();
> }
>
>
> //************************************************************************
> void loop()
> {
>
>
> }
>
>
>
>
> On Mon, Jan 3, 2011 at 9:35 PM, Tom Igoe <> wrote:
> > It broke in the non-SDM version too, but it took longer to break. In the
> SDM version it breaks immediately. So it looks like whatever you did
> highlights the faults sooner, which is good. It also points to a need for an
> error response of some sort, in answer to your question last mail.
> >
> > t.
> >
> > On Jan 3, 2011, at 4:44 PM, Alexander Brevig wrote:
> >
> >> That breaking of String, does it only occur with the SDM version?
> >>
> >> If not, did you find any way to break it? Maybe any of the old faults
> related to memory?
> >>
> >>
> >> I actually have no time to check this myself right now, so I opted to
> just ask you.
> >>
> >> On Mon, Jan 3, 2011 at 10:35 PM, Tom Igoe <> wrote:
> >> Thanks, Alexander, and sorry for the delay.
> >>
> >> A few tests:
> >>
> >> For code that doesn't change the strings much, there's not a big
> difference, a couple dozen bytes' difference in code size. However, when
> you start to do dynamic things, it does add up. For example, the
> StringAppendOperator example is 4910 bytes in 0022, and 5148 bytes with the
> StaticDynamicMemory version. So it does start to take its toll, memory-wise.
> >>
> >> On some sketches it actually takes less memory. For example, the one
> below is 3738 bytes using the StaticDynamicMemory version, and 3986 bytes in
> 0022. However, it fails entirely on upload. When the value of (analog 0)/4
> is high (0xFF), it never gets out of the setup(). So there's still a pretty
> easy way to break String, even with these improvements.
> >>
> >>
> >> void setup() {
> >> Serial.begin(9600);
> >> Serial.println("Beginning");
> >> }
> >>
> >> void loop() {
> >>
> >> String webColor = "#";
> >>
> >> int red = analogRead(A0)/4;
> >> webColor += String(red, HEX);
> >> int green = analogRead(A1)/4;
> >> webColor += String(green, HEX);
> >> int blue = analogRead(A2)/4;
> >>
> >> webColor += String(blue, HEX);
> >> Serial.println(webColor);
> >> }
> >>
> >>
> >>
> >>
> >>
> >> On Dec 16, 2010, at 1:27 AM, Alexander Brevig wrote:
> >>
> >> > Attached is a zip containing WString.h and .cpp plus
> StaticDynamicMemory.h.
> >> > Take a backup of the original WString files, and extract this zip into
> the hardware/arduino/cores/arduino folder.
> >> >
> >> > Now you're ready to test the modified String library, that does not
> fragment the heap.
> >> >
> >> >
> >> > In the WString header there is a #define called STRING_BUFFER which is
> set to 100 for now, change this to suit your test needs.
> >> >
> >> >
> >> > No error handling is implemented, what do you think we need?
> >> >
> >> > I plan to add an availableMemory():int method to the SDM library, and
> maybe some error flags and checks like hasError():int error
> >> >
> >> > I also suspect that this library is a bit slower performance wise, but
> I think that's just a cost we'll have to pay to being able to play with
> dynamic strings.
> >> >
> >> >
> >> > Hope to get feedback from someone!
> >> >
> >> > On Thu, Dec 16, 2010 at 1:11 AM, Alan Burlison <
> > wrote:
> >> > On 15/12/2010 16:19, David A. Mellis wrote:
> >> >
> >> > I think you're right, but I also don't think that telling people to
> >> > use the standard C library functions is a solution either. Trying out
> >> > this String class seems like one way of pushing forwards towards a
> >> > compromise that provides both an easy-to-use API and a robust
> >> > implementation. For example, perhaps the buffer sizes need to be
> >> > specified or provided when the String is instantiated. Or we need an
> >> > alternative implementation that does more reliable memory allocation
> >> > (since we're not assuming that the internal buffer is continuous).
> >> > Other ideas welcome.
> >> >
> >> > I think the problem is that the failure modes are not benign. I
> haven't been through all the use cases so this might not work, but perhaps
> using a statically-allocated string ("NOMEM" ?) as a sentinel value instead
> of null when malloc fails might be one way? Also, there might be some
> benefit in making String immutable a la Java - overloaded operators in C++
> have a tendency to generate anonymous temporaries, which is going to lead to
> heap fragmentation as well.
> >> >
> >> > --
> >> > Alan Burlison
> >> > --
> >> >
> >> > _______________________________________________
___________________________________________________

Posted on the Developers mailing list. Go to http://arduino.cc/mailman/listinfo/developers_arduino.cc to subscribe. Is this test suite any different than the one in the github repo?

t.

On Jan 4, 2011, at 12:53 PM, Rick Anderson wrote:

> I just created a test and unpacked and tested it. I also created a
> test based on Tom's code. Not sure I caught the maximum value error
> for 0xFF.
>
> I also ran the tests for bug 411. All the tests compile, but there is
> still memory loss.
>
> I'm attaching the Arduino Test suite, and the test code so you can run
> them as you debug. Let me know if this was helpful.
>
> --Rick
>
> Test run results:
> Example: ATS_StringAssignmentTest.pde
> info.MANUFACTURER = Arduino
> info.CPU-NAME = ATmega328P
> info.GCC-Version = 4.3.2
> info.AVR-LibC-Ver = 1.6.4
> info.Compiled-date = Jan 4 2011
> info.Test-Suite-Name = ATS_StringAssignmentTest
> info.Free-memory = 1110 bytes
> Memory Usage (lost 59 bytes) ... FAIL
> --------------------------
> Ran 1 tests in 1.378s
>
> FAILED (failures=1)
>
>
> Example: ATS_StringMemoryTestPassByReference.pde
>
> info.MANUFACTURER = Arduino
> info.CPU-NAME = ATmega328P
> info.GCC-Version = 4.3.2
> info.AVR-LibC-Ver = 1.6.4
> info.Compiled-date = Jan 4 2011
> info.Test-Suite-Name = ATS_StringMemoryTestPassByReference
> info.Free-memory = 1120 bytes
> Memory Usage (lost 59 bytes) ... FAIL
> --------------------------
> Ran 1 tests in 1.389s
>
> FAILED (failures=1)
>
>
> Example: Tom Igoe Memory Test
> info.MANUFACTURER = Arduino
> info.CPU-NAME = ATmega328P
> info.GCC-Version = 4.3.2
> info.AVR-LibC-Ver = 1.6.4
> info.Compiled-date = Jan 4 2011
> info.Test-Suite-Name = Tom Igoe Memory Test
> info.Free-memory = 1328 bytes
> Memory Usage (lost 9 bytes) ... FAIL
> --------------------------
> Ran 1 tests in 1.374s
>
> FAILED (failures=1)
>
>
>
> --Rick
>
> Tom, rewrote your example as a test.
>
> //************************************************************************
> //* Arduino Tom Igoe Memory Test
> //* (C) 2010 by Rick Anderson
> //* Open source as per standard Arduino code
> //*
> //************************************************************************
> //* Jan 4, 2011 Started on Tom Igoe Memory Test
> //************************************************************************
>
> #include "WProgram.h"
> #include "HardwareSerial.h"
> #include
>
> //************************************************************************
> void setup()
> {
> int startMemoryUsage;
> /*
> * Create variable for the tests.
> */
>
> String webColor = "#000000";
>
> int red = 1023/4;
> int blue = 512/4;
> int green = 128/4;
>
> /*
> * initiate the test run
> */
> //Record starting memory amount
> startMemoryUsage = ATS_GetFreeMemory();
> //Begin test run
> ATS_begin("Arduino", "Tom Igoe Memory Test");
>
> webColor = "#";
> webColor += String(red, HEX);
> webColor += String(green, HEX);
> webColor += String(blue, HEX);
>
> ATS_ReportMemoryUsage(startMemoryUsage);
>
> /*
> * Test complete
> */
>
> ATS_end();
> }
>
>
> //************************************************************************
> void loop()
> {
>
>
> }
>
>
>
>
> On Mon, Jan 3, 2011 at 9:35 PM, Tom Igoe <> wrote:
>> It broke in the non-SDM version too, but it took longer to break. In the SDM version it breaks immediately. So it looks like whatever you did highlights the faults sooner, which is good. It also points to a need for an error response of some sort, in answer to your question last mail.
>>
>> t.
>>
>> On Jan 3, 2011, at 4:44 PM, Alexander Brevig wrote:
>>
>>> That breaking of String, does it only occur with the SDM version?
>>>
>>> If not, did you find any way to break it? Maybe any of the old faults related to memory?
>>>
>>>
>>> I actually have no time to check this myself right now, so I opted to just ask you.
>>>
>>> On Mon, Jan 3, 2011 at 10:35 PM, Tom Igoe <> wrote:
>>> Thanks, Alexander, and sorry for the delay.
>>>
>>> A few tests:
>>>
>>> For code that doesn't change the strings much, there's not a big difference, a couple dozen bytes' difference in code size. However, when you start to do dynamic things, it does add up. For example, the StringAppendOperator example is 4910 bytes in 0022, and 5148 bytes with the StaticDynamicMemory version. So it does start to take its toll, memory-wise.
>>>
>>> On some sketches it actually takes less memory. For example, the one below is 3738 bytes using the StaticDynamicMemory version, and 3986 bytes in 0022. However, it fails entirely on upload. When the value of (analog 0)/4 is high (0xFF), it never gets out of the setup(). So there's still a pretty easy way to break String, even with these improvements.
>>>
>>>
>>> void setup() {
>>> Serial.begin(9600);
>>> Serial.println("Beginning");
>>> }
>>>
>>> void loop() {
>>>
>>> String webColor = "#";
>>>
>>> int red = analogRead(A0)/4;
>>> webColor += String(red, HEX);
>>> int green = analogRead(A1)/4;
>>> webColor += String(green, HEX);
>>> int blue = analogRead(A2)/4;
>>>
>>> webColor += String(blue, HEX);
>>> Serial.println(webColor);
>>> }
>>>
>>>
>>>
>>>
>>>
>>> On Dec 16, 2010, at 1:27 AM, Alexander Brevig wrote:
>>>
>>>> Attached is a zip containing WString.h and .cpp plus StaticDynamicMemory.h.
>>>> Take a backup of the original WString files, and extract this zip into the hardware/arduino/cores/arduino folder.
>>>>
>>>> Now you're ready to test the modified String library, that does not fragment the heap.
>>>>
>>>>
>>>> In the WString header there is a #define called STRING_BUFFER which is set to 100 for now, change this to suit your test needs.
>>>>
>>>>
>>>> No error handling is implemented, what do you think we need?
>>>>
>>>> I plan to add an availableMemory():int method to the SDM library, and maybe some error flags and checks like hasError():int error
>>>>
>>>> I also suspect that this library is a bit slower performance wise, but I think that's just a cost we'll have to pay to being able to play with dynamic strings.
>>>>
>>>>
>>>> Hope to get feedback from someone!
>>>>
>>>> On Thu, Dec 16, 2010 at 1:11 AM, Alan Burlison <> wrote:
>>>> On 15/12/2010 16:19, David A. Mellis wrote:
>>>>
>>>> I think you're right, but I also don't think that telling people to
>>>> use the standard C library functions is a solution either. Trying out
>>>> this String class seems like one way of pushing forwards towards a
>>>> compromise that provides both an easy-to-use API and a robust
>>>> implementation. For example, perhaps the buffer sizes need to be
>>>> specified or provided when the String is instantiated. Or we need an
>>>> alternative implementation that does more reliable memory allocation
>>>> (since we're not assuming that the internal buffer is continuous).
>>>> Other ideas welcome.
>>>>
>>>> I think the problem is that the failure modes are not benign. I haven't been through all the use cases so this might not work, but perhaps using a statically-allocated string ("NOMEM" ?) as a sentinel value instead of null when malloc fails might be one way? Also, there might be some benefit in making String immutable a la Java - overloaded operators in C++ have a tendency to generate anonymous temporaries, which is going to lead to heap fragmentation as well.
>>>>
>>>> --
>>>> Alan Burlison
>>>> --
>>>>
>>>> _______________________________________________
___________________________________________________

Posted on the Developers mailing list. Go to http://arduino.cc/mailman/listinfo/developers_arduino.cc to subscribe. Same exact one. I just included it just in case.

--Rick

On Tue, Jan 4, 2011 at 9:01 PM, Tom Igoe <> wrote:
> Is this test suite any different than the one in the github repo?
>
> t.
>
> On Jan 4, 2011, at 12:53 PM, Rick Anderson wrote:
>
>> I just created a test and unpacked and tested it. I also created a
>> test based on Tom's code. Not sure I caught the maximum value error
>> for 0xFF.
>>
>> I also ran the tests for bug 411. All the tests compile, but there is
>> still memory loss.
>>
>> I'm attaching the Arduino Test suite, and the test code so you can run
>> them as you debug. Let me know if this was helpful.
>>
>> --Rick
>>
>> Test run results:
>> Example:  ATS_StringAssignmentTest.pde
>> info.MANUFACTURER    = Arduino
>> info.CPU-NAME        = ATmega328P
>> info.GCC-Version     = 4.3.2
>> info.AVR-LibC-Ver    = 1.6.4
>> info.Compiled-date   = Jan  4 2011
>> info.Test-Suite-Name = ATS_StringAssignmentTest
>> info.Free-memory     = 1110 bytes
>> Memory Usage (lost 59 bytes)                                ... FAIL
>> --------------------------
>> Ran 1 tests in 1.378s
>>
>> FAILED (failures=1)
>>
>>
>> Example: ATS_StringMemoryTestPassByReference.pde
>>
>> info.MANUFACTURER    = Arduino
>> info.CPU-NAME        = ATmega328P
>> info.GCC-Version     = 4.3.2
>> info.AVR-LibC-Ver    = 1.6.4
>> info.Compiled-date   = Jan  4 2011
>> info.Test-Suite-Name = ATS_StringMemoryTestPassByReference
>> info.Free-memory     = 1120 bytes
>> Memory Usage (lost 59 bytes)                                ... FAIL
>> --------------------------
>> Ran 1 tests in 1.389s
>>
>> FAILED (failures=1)
>>
>>
>> Example: Tom Igoe Memory Test
>> info.MANUFACTURER    = Arduino
>> info.CPU-NAME        = ATmega328P
>> info.GCC-Version     = 4.3.2
>> info.AVR-LibC-Ver    = 1.6.4
>> info.Compiled-date   = Jan  4 2011
>> info.Test-Suite-Name = Tom Igoe Memory Test
>> info.Free-memory     = 1328 bytes
>> Memory Usage (lost 9 bytes)                                 ... FAIL
>> --------------------------
>> Ran 1 tests in 1.374s
>>
>> FAILED (failures=1)
>>
>>
>>
>> --Rick
>>
>> Tom, rewrote your example as a test.
>>
>> //************************************************************************
>> //*   Arduino Tom Igoe Memory Test
>> //*           (C) 2010 by Rick Anderson
>> //*           Open source as per standard Arduino code
>> //*
>> //************************************************************************
>> //*   Jan 4,  2011     Started on Tom Igoe Memory Test
>> //************************************************************************
>>
>> #include      "WProgram.h"
>> #include      "HardwareSerial.h"
>> #include      
>>
>> //************************************************************************
>> void setup()
>> {
>>  int          startMemoryUsage;
>>  /*
>>    * Create variable for the tests.
>>   */
>>
>>  String webColor = "#000000";
>>
>>  int red = 1023/4;
>>  int blue = 512/4;
>>  int green = 128/4;
>>
>>  /*
>>  * initiate the test run
>>   */
>>  //Record starting memory amount
>>  startMemoryUsage     =       ATS_GetFreeMemory();
>>  //Begin test run
>>  ATS_begin("Arduino", "Tom Igoe Memory Test");
>>
>>  webColor = "#";
>>  webColor += String(red, HEX);
>>  webColor += String(green, HEX);
>>  webColor += String(blue, HEX);
>>
>>  ATS_ReportMemoryUsage(startMemoryUsage);
>>
>>  /*
>>   * Test complete
>>   */
>>
>>  ATS_end();
>> }
>>
>>
>> //************************************************************************
>> void loop()
>> {
>>
>>
>> }
>>
>>
>>
>>
>> On Mon, Jan 3, 2011 at 9:35 PM, Tom Igoe <> wrote:
>>> It broke in the non-SDM version too, but it took longer to break. In the SDM version it breaks immediately. So it looks like whatever you did highlights the faults sooner, which is good. It also points to a need for an error response of some sort, in answer to your question last mail.
>>>
>>> t.
>>>
>>> On Jan 3, 2011, at 4:44 PM, Alexander Brevig wrote:
>>>
>>>> That breaking of String, does it only occur with the SDM version?
>>>>
>>>> If not, did you find any way to break it? Maybe any of the old faults related to memory?
>>>>
>>>>
>>>> I actually have no time to check this myself right now, so I opted to just ask you.
>>>>
>>>> On Mon, Jan 3, 2011 at 10:35 PM, Tom Igoe <> wrote:
>>>> Thanks, Alexander, and sorry for the delay.
>>>>
>>>> A few tests:
>>>>
>>>> For code that doesn't change the strings much, there's not a big difference, a couple dozen bytes' difference in code size.  However, when you start to do dynamic things, it does add up.  For example, the StringAppendOperator example is  4910 bytes in 0022, and 5148 bytes with the StaticDynamicMemory version. So it does start to take its toll, memory-wise.
>>>>
>>>> On some sketches it actually takes less memory.  For example, the one below is 3738 bytes using the StaticDynamicMemory version, and 3986 bytes in 0022.  However, it fails entirely on upload.  When the value of (analog 0)/4 is high (0xFF), it never gets out of the setup(). So there's still a pretty easy way to break String, even with these improvements.
>>>>
>>>>
>>>> void setup() {
>>>>  Serial.begin(9600);
>>>>  Serial.println("Beginning");
>>>> }
>>>>
>>>> void loop() {
>>>>
>>>>  String webColor = "#";
>>>>
>>>>  int red = analogRead(A0)/4;
>>>>  webColor += String(red, HEX);
>>>>  int green = analogRead(A1)/4;
>>>>  webColor += String(green, HEX);
>>>>  int blue = analogRead(A2)/4;
>>>>
>>>>  webColor += String(blue, HEX);
>>>>  Serial.println(webColor);
>>>> }
>>>>
>>>>
>>>>
>>>>
>>>>
>>>> On Dec 16, 2010, at 1:27 AM, Alexander Brevig wrote:
>>>>
>>>>> Attached is a zip containing WString.h and .cpp plus StaticDynamicMemory.h.
>>>>> Take a backup of the original WString files, and extract this zip into the hardware/arduino/cores/arduino folder.
>>>>>
>>>>> Now you're ready to test the modified String library, that does not fragment the heap.
>>>>>
>>>>>
>>>>> In the WString header there is a #define called STRING_BUFFER which is set to 100 for now, change this to suit your test needs.
>>>>>
>>>>>
>>>>> No error handling is implemented, what do you think we need?
>>>>>
>>>>> I plan to add an availableMemory():int method to the SDM library, and maybe some error flags and checks like hasError():int error
>>>>>
>>>>> I also suspect that this library is a bit slower performance wise, but I think that's just a cost we'll have to pay to being able to play with dynamic strings.
>>>>>
>>>>>
>>>>> Hope to  get feedback from someone!
>>>>>
>>>>> On Thu, Dec 16, 2010 at 1:11 AM, Alan Burlison <> wrote:
>>>>> On 15/12/2010 16:19, David A. Mellis wrote:
>>>>>
>>>>> I think you're right, but I also don't think that telling people to
>>>>> use the standard C library functions is a solution either.  Trying out
>>>>> this String class seems like one way of pushing forwards towards a
>>>>> compromise that provides both an easy-to-use API and a robust
>>>>> implementation.  For example, perhaps the buffer sizes need to be
>>>>> specified or provided when the String is instantiated.  Or we need an
>>>>> alternative implementation that does more reliable memory allocation
>>>>> (since we're not assuming that the internal buffer is continuous).
>>>>> Other ideas welcome.
>>>>>
>>>>> I think the problem is that the failure modes are not benign.  I haven't been through all the use cases so this might not work, but perhaps using a statically-allocated string ("NOMEM" ?) as a sentinel value instead of null when malloc fails might be one way?  Also, there might be some benefit in making String immutable a la Java - overloaded operators in C++ have a tendency to generate anonymous temporaries, which is going to lead to heap fragmentation as well.
>>>>>
>>>>> --
>>>>> Alan Burlison
>>>>> --
>>>>>
>>>>> _______________________________________________
___________________________________________________

Posted on the Developers mailing list. Go to http://arduino.cc/mailman/listinfo/developers_arduino.cc to subscribe. On 04/01/2011 17:53, Rick Anderson wrote:

> I also ran the tests for bug 411. All the tests compile, but there is
> still memory loss.

Most of the assumptions made by the test harness and test case code are
wrong, any reports of 'lost' memory are therefore likely to be wrong as
well. If you want to do leak detection you can't do it in the naive way
it is being done at present.

--
Alan Burlison
--

_______________________________________________
___________________________________________________

Posted on the Developers mailing list. Go to http://arduino.cc/mailman/listinfo/developers_arduino.cc to subscribe. Alan,

The tests themselves are quick and dirty, and not strategic or
comprehensive. I'd like your input to create a good procedure for
memory testing. I also have feedback from Paul Stoffregen for the test
suite:
----
Another problem involves gcc's optimizer ignoring the inline request
for ATS_ReportMemoryUsage. As the comment in the code explains, it
must be inline to avoid measuring its own stack frame. I believe
adding this line in ArduinoTestSuite.h fixes the problem by forcing
gcc to inline.

inline void ATS_ReportMemoryUsage(int _memoryUsageAtStart)
__attribute__((always_inline, unused));

The last problem is a tiny bit of dynamic memory permanently held for
the free list. To allow for this, the test really should call
malloc() and free() once, so the allocator is fully initialized before
testing.
----

I'd like to combine both sets of feedback, and set up some issues in
the system, then fix them. Is the above the problem you saw? Are their
other assumptions that would impact measuring memory? And updating the
memory test in the the test suite.

In terms of creating tests for memory leaks. It looks best to move all
the memory usage inside a function. What else could be done to
constrain the problem, and measuring more affectively.

I'm traveling back to NJ today, so I can't respond right away.

--Rick

On Wed, Jan 5, 2011 at 8:52 AM, Alan Burlison <> wrote:
> On 04/01/2011 17:53, Rick Anderson wrote:
>
>> I also ran the tests for bug 411. All the tests compile, but there is
>> still memory loss.
>
> Most of the assumptions made by the test harness and test case code are
> wrong, any reports of 'lost' memory are therefore likely to be wrong as
> well.  If you want to do leak detection you can't do it in the naive way it
> is being done at present.
>
> --
> Alan Burlison
> --
>



--
President
Fair Use Building and Research (****) Labs
http://fubarlabs.org

_______________________________________________
___________________________________________________

Posted on the Developers mailing list. Go to http://arduino.cc/mailman/listinfo/developers_arduino.cc to subscribe. On 05/01/2011 15:19, Rick Anderson wrote:

> ----
> Another problem involves gcc's optimizer ignoring the inline request
> for ATS_ReportMemoryUsage. As the comment in the code explains, it
> must be inline to avoid measuring its own stack frame. I believe
> adding this line in ArduinoTestSuite.h fixes the problem by forcing
> gcc to inline.
>
> inline void ATS_ReportMemoryUsage(int _memoryUsageAtStart)
> __attribute__((always_inline, unused));

Yes, that's one of the problems. And even the __attribute__
'workaround' is a fragile hack.

> The last problem is a tiny bit of dynamic memory permanently held for
> the free list. To allow for this, the test really should call
> malloc() and free() once, so the allocator is fully initialized before

That's part of a problem, but an initial call malloc/free call isn't
guaranteed to make all the issues go away either. From looking at the
avr-libc malloc implementation it does try to coalesce the heap, but
relying on multiple malloc implementation artefacts is a really bad idea
- there's no guarantee that future malloc implementations will always
coalesce on every free, and there's no guarantee that __bss_end or
__brkval will always be adjusted on each malloc/free call.

The other issue is that of object lifetimes. The test code has
instances of String objects which are allocated on the stack and that
are still in scope when the 'leak' memory check is performed. That
means the String destructors won't have been called and the dynamically
allocated part of the String will still be allocated.

A true memory leak is a block of allocated memory that has no references
to it. However that's not what the test code is checking for. If a
library routine used malloc to perform a one-time library-private buffer
allocation where the buffer is retained for the lifetime of the program,
the current leak checking would incorrectly report that as a leak. It
isn't a leak because there's still a reference to the block inside the
library.

The only semi-reliable way to do what you want is to use an instrumented
malloc implementation, and that's going to be very difficult to
implement on a constrained platform such as the AVR. If you want to
test the String implementation for leaks, my advice is to do it on a
more capable platform (e.g. *nix) and use one of the many instrumented
mallocs that are available.

--
Alan Burlison
--

_______________________________________________
___________________________________________________

Posted on the Developers mailing list. Go to http://arduino.cc/mailman/listinfo/developers_arduino.cc to subscribe. Slightly unrelated to what you guys are discussing now but:
I'm not sure if I've made this clear, but the new version of String that I'm
working on now does not use malloc or any other c function for dynamic
memory. What happens is that I allocate memory statically on the stack and
serve that memory dynamically to the instances of String.

I have some time on my hands now and have a look at getting the += not to
break the code

On Wed, Jan 5, 2011 at 7:10 PM, Alan Burlison <>wrote:

> On 05/01/2011 15:19, Rick Anderson wrote:
>
> ----
>> Another problem involves gcc's optimizer ignoring the inline request
>> for ATS_ReportMemoryUsage. As the comment in the code explains, it
>> must be inline to avoid measuring its own stack frame. I believe
>> adding this line in ArduinoTestSuite.h fixes the problem by forcing
>> gcc to inline.
>>
>> inline void ATS_ReportMemoryUsage(int _memoryUsageAtStart)
>> __attribute__((always_inline, unused));
>>
>
> Yes, that's one of the problems. And even the __attribute__ 'workaround'
> is a fragile hack.
>
>
> The last problem is a tiny bit of dynamic memory permanently held for
>> the free list. To allow for this, the test really should call
>> malloc() and free() once, so the allocator is fully initialized before
>>
>
> That's part of a problem, but an initial call malloc/free call isn't
> guaranteed to make all the issues go away either. From looking at the
> avr-libc malloc implementation it does try to coalesce the heap, but relying
> on multiple malloc implementation artefacts is a really bad idea - there's
> no guarantee that future malloc implementations will always coalesce on
> every free, and there's no guarantee that __bss_end or __brkval will always
> be adjusted on each malloc/free call.
>
> The other issue is that of object lifetimes. The test code has instances
> of String objects which are allocated on the stack and that are still in
> scope when the 'leak' memory check is performed. That means the String
> destructors won't have been called and the dynamically allocated part of the
> String will still be allocated.
>
> A true memory leak is a block of allocated memory that has no references to
> it. However that's not what the test code is checking for. If a library
> routine used malloc to perform a one-time library-private buffer allocation
> where the buffer is retained for the lifetime of the program, the current
> leak checking would incorrectly report that as a leak. It isn't a leak
> because there's still a reference to the block inside the library.
>
> The only semi-reliable way to do what you want is to use an instrumented
> malloc implementation, and that's going to be very difficult to implement on
> a constrained platform such as the AVR. If you want to test the String
> implementation for leaks, my advice is to do it on a more capable platform
> (e.g. *nix) and use one of the many instrumented mallocs that are available.
>
> --
> Alan Burlison
> --
>
>
> _______________________________________________
___________________________________________________

Posted on the Developers mailing list. Go to http://arduino.cc/mailman/listinfo/developers_arduino.cc to subscribe. On 05/01/2011 18:25, Alexander Brevig wrote:

> Slightly unrelated to what you guys are discussing now but:
> I'm not sure if I've made this clear, but the new version of String that I'm
> working on now does not use malloc or any other c function for dynamic
> memory. What happens is that I allocate memory statically on the stack and
> serve that memory dynamically to the instances of String.

Does that mean that the total space occupied by all Strings has to be
decided up front? If so, what is the behaviour when an allocation fails?

To be honest I don't really see the point of doing this - all you are
doing is re-implementing malloc.

--
Alan Burlison
--

_______________________________________________
___________________________________________________

Posted on the Developers mailing list. Go to http://arduino.cc/mailman/listinfo/developers_arduino.cc to subscribe. No, actually I am not reimplementing malloc, because my algorithm guarantees
no fragmentation and always 100% effective use of the allocated memory.

"Does that mean that the total space occupied by all Strings has to be
decided up front? "
Yes, just like the buffer for the serial ++

I know I would opt to have the restriction for a predetermined allocated
space WITH error reporting (how we do is up to you guys, feed me with ideas
I'll implement whatever we agree is best) than having
seemingly infinite memory that crashes and burns.

On Wed, Jan 5, 2011 at 7:33 PM, Alan Burlison <>wrote:

> On 05/01/2011 18:25, Alexander Brevig wrote:
>
> Slightly unrelated to what you guys are discussing now but:
>> I'm not sure if I've made this clear, but the new version of String that
>> I'm
>> working on now does not use malloc or any other c function for dynamic
>> memory. What happens is that I allocate memory statically on the stack and
>> serve that memory dynamically to the instances of String.
>>
>
> Does that mean that the total space occupied by all Strings has to be
> decided up front? If so, what is the behaviour when an allocation fails?
>
> To be honest I don't really see the point of doing this - all you are doing
> is re-implementing malloc.
>
> --
> Alan Burlison
> --
> Well, that was easy (seemingly, probably just jinxed myself...) but here the
test does no longer break, and the usage of memory never exceeds 11 bytes.

It would be awesome if someone would test it.


Also, please tell me now if this effort will lead to nowhere. Is the cost of
being constrained to a buffer size a deal-breaker?

On Wed, Jan 5, 2011 at 7:42 PM, Alexander Brevig
<>wrote:

> No, actually I am not reimplementing malloc, because my algorithm
> guarantees no fragmentation and always 100% effective use of the allocated
> memory.
>
> "Does that mean that the total space occupied by all Strings has to be
> decided up front? "
> Yes, just like the buffer for the serial ++
>
> I know I would opt to have the restriction for a predetermined allocated
> space WITH error reporting (how we do is up to you guys, feed me with ideas
> I'll implement whatever we agree is best) than having
> seemingly infinite memory that crashes and burns.
>
> On Wed, Jan 5, 2011 at 7:33 PM, Alan Burlison <>wrote:
>
>> On 05/01/2011 18:25, Alexander Brevig wrote:
>>
>> Slightly unrelated to what you guys are discussing now but:
>>> I'm not sure if I've made this clear, but the new version of String that
>>> I'm
>>> working on now does not use malloc or any other c function for dynamic
>>> memory. What happens is that I allocate memory statically on the stack
>>> and
>>> serve that memory dynamically to the instances of String.
>>>
>>
>> Does that mean that the total space occupied by all Strings has to be
>> decided up front? If so, what is the behaviour when an allocation fails?
>>
>> To be honest I don't really see the point of doing this - all you are
>> doing is re-implementing malloc.
>>
>> --
>> Alan Burlison
>> --
>>
>
>

  #13  
05-01-2011 07:02 PM
Developers member admin is online now
User
 

That breaking of String, does it only occur with the SDM version?

If not, did you find any way to break it? Maybe any of the old faults
related to memory?


I actually have no time to check this myself right now, so I opted to just
ask you.

On Mon, Jan 3, 2011 at 10:35 PM, Tom Igoe <> wrote:

> Thanks, Alexander, and sorry for the delay.
>
> A few tests:
>
> For code that doesn't change the strings much, there's not a big
> difference, a couple dozen bytes' difference in code size. However, when
> you start to do dynamic things, it does add up. For example, the
> StringAppendOperator example is 4910 bytes in 0022, and 5148 bytes with the
> StaticDynamicMemory version. So it does start to take its toll, memory-wise.
>
> On some sketches it actually takes less memory. For example, the one below
> is 3738 bytes using the StaticDynamicMemory version, and 3986 bytes in 0022.
> However, it fails entirely on upload. When the value of (analog 0)/4 is
> high (0xFF), it never gets out of the setup(). So there's still a pretty
> easy way to break String, even with these improvements.
>
>
> void setup() {
> Serial.begin(9600);
> Serial.println("Beginning");
> }
>
> void loop() {
>
> String webColor = "#";
>
> int red = analogRead(A0)/4;
> webColor += String(red, HEX);
> int green = analogRead(A1)/4;
> webColor += String(green, HEX);
> int blue = analogRead(A2)/4;
>
> webColor += String(blue, HEX);
> Serial.println(webColor);
> }
>
>
>
>
>
> On Dec 16, 2010, at 1:27 AM, Alexander Brevig wrote:
>
> > Attached is a zip containing WString.h and .cpp plus
> StaticDynamicMemory.h.
> > Take a backup of the original WString files, and extract this zip into
> the hardware/arduino/cores/arduino folder.
> >
> > Now you're ready to test the modified String library, that does not
> fragment the heap.
> >
> >
> > In the WString header there is a #define called STRING_BUFFER which is
> set to 100 for now, change this to suit your test needs.
> >
> >
> > No error handling is implemented, what do you think we need?
> >
> > I plan to add an availableMemory():int method to the SDM library, and
> maybe some error flags and checks like hasError():int error
> >
> > I also suspect that this library is a bit slower performance wise, but I
> think that's just a cost we'll have to pay to being able to play with
> dynamic strings.
> >
> >
> > Hope to get feedback from someone!
> >
> > On Thu, Dec 16, 2010 at 1:11 AM, Alan Burlison <>
> wrote:
> > On 15/12/2010 16:19, David A. Mellis wrote:
> >
> > I think you're right, but I also don't think that telling people to
> > use the standard C library functions is a solution either. Trying out
> > this String class seems like one way of pushing forwards towards a
> > compromise that provides both an easy-to-use API and a robust
> > implementation. For example, perhaps the buffer sizes need to be
> > specified or provided when the String is instantiated. Or we need an
> > alternative implementation that does more reliable memory allocation
> > (since we're not assuming that the internal buffer is continuous).
> > Other ideas welcome.
> >
> > I think the problem is that the failure modes are not benign. I haven't
> been through all the use cases so this might not work, but perhaps using a
> statically-allocated string ("NOMEM" ?) as a sentinel value instead of null
> when malloc fails might be one way? Also, there might be some benefit in
> making String immutable a la Java - overloaded operators in C++ have a
> tendency to generate anonymous temporaries, which is going to lead to heap
> fragmentation as well.
> >
> > --
> > Alan Burlison
> > --
> >
> > _______________________________________________
___________________________________________________

Posted on the Developers mailing list. Go to http://arduino.cc/mailman/listinfo/developers_arduino.cc to subscribe. It broke in the non-SDM version too, but it took longer to break. In the SDM version it breaks immediately. So it looks like whatever you did highlights the faults sooner, which is good. It also points to a need for an error response of some sort, in answer to your question last mail.

t.

On Jan 3, 2011, at 4:44 PM, Alexander Brevig wrote:

> That breaking of String, does it only occur with the SDM version?
>
> If not, did you find any way to break it? Maybe any of the old faults related to memory?
>
>
> I actually have no time to check this myself right now, so I opted to just ask you.
>
> On Mon, Jan 3, 2011 at 10:35 PM, Tom Igoe <> wrote:
> Thanks, Alexander, and sorry for the delay.
>
> A few tests:
>
> For code that doesn't change the strings much, there's not a big difference, a couple dozen bytes' difference in code size. However, when you start to do dynamic things, it does add up. For example, the StringAppendOperator example is 4910 bytes in 0022, and 5148 bytes with the StaticDynamicMemory version. So it does start to take its toll, memory-wise.
>
> On some sketches it actually takes less memory. For example, the one below is 3738 bytes using the StaticDynamicMemory version, and 3986 bytes in 0022. However, it fails entirely on upload. When the value of (analog 0)/4 is high (0xFF), it never gets out of the setup(). So there's still a pretty easy way to break String, even with these improvements.
>
>
> void setup() {
> Serial.begin(9600);
> Serial.println("Beginning");
> }
>
> void loop() {
>
> String webColor = "#";
>
> int red = analogRead(A0)/4;
> webColor += String(red, HEX);
> int green = analogRead(A1)/4;
> webColor += String(green, HEX);
> int blue = analogRead(A2)/4;
>
> webColor += String(blue, HEX);
> Serial.println(webColor);
> }
>
>
>
>
>
> On Dec 16, 2010, at 1:27 AM, Alexander Brevig wrote:
>
> > Attached is a zip containing WString.h and .cpp plus StaticDynamicMemory.h.
> > Take a backup of the original WString files, and extract this zip into the hardware/arduino/cores/arduino folder.
> >
> > Now you're ready to test the modified String library, that does not fragment the heap.
> >
> >
> > In the WString header there is a #define called STRING_BUFFER which is set to 100 for now, change this to suit your test needs.
> >
> >
> > No error handling is implemented, what do you think we need?
> >
> > I plan to add an availableMemory():int method to the SDM library, and maybe some error flags and checks like hasError():int error
> >
> > I also suspect that this library is a bit slower performance wise, but I think that's just a cost we'll have to pay to being able to play with dynamic strings.
> >
> >
> > Hope to get feedback from someone!
> >
> > On Thu, Dec 16, 2010 at 1:11 AM, Alan Burlison <> wrote:
> > On 15/12/2010 16:19, David A. Mellis wrote:
> >
> > I think you're right, but I also don't think that telling people to
> > use the standard C library functions is a solution either. Trying out
> > this String class seems like one way of pushing forwards towards a
> > compromise that provides both an easy-to-use API and a robust
> > implementation. For example, perhaps the buffer sizes need to be
> > specified or provided when the String is instantiated. Or we need an
> > alternative implementation that does more reliable memory allocation
> > (since we're not assuming that the internal buffer is continuous).
> > Other ideas welcome.
> >
> > I think the problem is that the failure modes are not benign. I haven't been through all the use cases so this might not work, but perhaps using a statically-allocated string ("NOMEM" ?) as a sentinel value instead of null when malloc fails might be one way? Also, there might be some benefit in making String immutable a la Java - overloaded operators in C++ have a tendency to generate anonymous temporaries, which is going to lead to heap fragmentation as well.
> >
> > --
> > Alan Burlison
> > --
> >
> > _______________________________________________
___________________________________________________

Posted on the Developers mailing list. Go to http://arduino.cc/mailman/listinfo/developers_arduino.cc to subscribe. There seems to be a bug with the assignment operator, I'm on it and I'll get
back to you as soon as I get something done.

Thank you for your tests and feedback.


I'll do some tests on my own before I repost it here.

On Tue, Jan 4, 2011 at 6:53 PM, Rick Anderson
<>wrote:

> I just created a test and unpacked and tested it. I also created a
> test based on Tom's code. Not sure I caught the maximum value error
> for 0xFF.
>
> I also ran the tests for bug 411. All the tests compile, but there is
> still memory loss.
>
> I'm attaching the Arduino Test suite, and the test code so you can run
> them as you debug. Let me know if this was helpful.
>
> --Rick
>
> Test run results:
> Example: ATS_StringAssignmentTest.pde
> info.MANUFACTURER = Arduino
> info.CPU-NAME = ATmega328P
> info.GCC-Version = 4.3.2
> info.AVR-LibC-Ver = 1.6.4
> info.Compiled-date = Jan 4 2011
> info.Test-Suite-Name = ATS_StringAssignmentTest
> info.Free-memory = 1110 bytes
> Memory Usage (lost 59 bytes) ... FAIL
> --------------------------
> Ran 1 tests in 1.378s
>
> FAILED (failures=1)
>
>
> Example: ATS_StringMemoryTestPassByReference.pde
>
> info.MANUFACTURER = Arduino
> info.CPU-NAME = ATmega328P
> info.GCC-Version = 4.3.2
> info.AVR-LibC-Ver = 1.6.4
> info.Compiled-date = Jan 4 2011
> info.Test-Suite-Name = ATS_StringMemoryTestPassByReference
> info.Free-memory = 1120 bytes
> Memory Usage (lost 59 bytes) ... FAIL
> --------------------------
> Ran 1 tests in 1.389s
>
> FAILED (failures=1)
>
>
> Example: Tom Igoe Memory Test
> info.MANUFACTURER = Arduino
> info.CPU-NAME = ATmega328P
> info.GCC-Version = 4.3.2
> info.AVR-LibC-Ver = 1.6.4
> info.Compiled-date = Jan 4 2011
> info.Test-Suite-Name = Tom Igoe Memory Test
> info.Free-memory = 1328 bytes
> Memory Usage (lost 9 bytes) ... FAIL
> --------------------------
> Ran 1 tests in 1.374s
>
> FAILED (failures=1)
>
>
>
> --Rick
>
> Tom, rewrote your example as a test.
>
> //************************************************************************
> //* Arduino Tom Igoe Memory Test
> //* (C) 2010 by Rick Anderson
> //* Open source as per standard Arduino code
> //*
> //************************************************************************
> //* Jan 4, 2011 Started on Tom Igoe Memory Test
> //************************************************************************
>
> #include "WProgram.h"
> #include "HardwareSerial.h"
> #include
>
> //************************************************************************
> void setup()
> {
> int startMemoryUsage;
> /*
> * Create variable for the tests.
> */
>
> String webColor = "#000000";
>
> int red = 1023/4;
> int blue = 512/4;
> int green = 128/4;
>
> /*
> * initiate the test run
> */
> //Record starting memory amount
> startMemoryUsage = ATS_GetFreeMemory();
> //Begin test run
> ATS_begin("Arduino", "Tom Igoe Memory Test");
>
> webColor = "#";
> webColor += String(red, HEX);
> webColor += String(green, HEX);
> webColor += String(blue, HEX);
>
> ATS_ReportMemoryUsage(startMemoryUsage);
>
> /*
> * Test complete
> */
>
> ATS_end();
> }
>
>
> //************************************************************************
> void loop()
> {
>
>
> }
>
>
>
>
> On Mon, Jan 3, 2011 at 9:35 PM, Tom Igoe <> wrote:
> > It broke in the non-SDM version too, but it took longer to break. In the
> SDM version it breaks immediately. So it looks like whatever you did
> highlights the faults sooner, which is good. It also points to a need for an
> error response of some sort, in answer to your question last mail.
> >
> > t.
> >
> > On Jan 3, 2011, at 4:44 PM, Alexander Brevig wrote:
> >
> >> That breaking of String, does it only occur with the SDM version?
> >>
> >> If not, did you find any way to break it? Maybe any of the old faults
> related to memory?
> >>
> >>
> >> I actually have no time to check this myself right now, so I opted to
> just ask you.
> >>
> >> On Mon, Jan 3, 2011 at 10:35 PM, Tom Igoe <> wrote:
> >> Thanks, Alexander, and sorry for the delay.
> >>
> >> A few tests:
> >>
> >> For code that doesn't change the strings much, there's not a big
> difference, a couple dozen bytes' difference in code size. However, when
> you start to do dynamic things, it does add up. For example, the
> StringAppendOperator example is 4910 bytes in 0022, and 5148 bytes with the
> StaticDynamicMemory version. So it does start to take its toll, memory-wise.
> >>
> >> On some sketches it actually takes less memory. For example, the one
> below is 3738 bytes using the StaticDynamicMemory version, and 3986 bytes in
> 0022. However, it fails entirely on upload. When the value of (analog 0)/4
> is high (0xFF), it never gets out of the setup(). So there's still a pretty
> easy way to break String, even with these improvements.
> >>
> >>
> >> void setup() {
> >> Serial.begin(9600);
> >> Serial.println("Beginning");
> >> }
> >>
> >> void loop() {
> >>
> >> String webColor = "#";
> >>
> >> int red = analogRead(A0)/4;
> >> webColor += String(red, HEX);
> >> int green = analogRead(A1)/4;
> >> webColor += String(green, HEX);
> >> int blue = analogRead(A2)/4;
> >>
> >> webColor += String(blue, HEX);
> >> Serial.println(webColor);
> >> }
> >>
> >>
> >>
> >>
> >>
> >> On Dec 16, 2010, at 1:27 AM, Alexander Brevig wrote:
> >>
> >> > Attached is a zip containing WString.h and .cpp plus
> StaticDynamicMemory.h.
> >> > Take a backup of the original WString files, and extract this zip into
> the hardware/arduino/cores/arduino folder.
> >> >
> >> > Now you're ready to test the modified String library, that does not
> fragment the heap.
> >> >
> >> >
> >> > In the WString header there is a #define called STRING_BUFFER which is
> set to 100 for now, change this to suit your test needs.
> >> >
> >> >
> >> > No error handling is implemented, what do you think we need?
> >> >
> >> > I plan to add an availableMemory():int method to the SDM library, and
> maybe some error flags and checks like hasError():int error
> >> >
> >> > I also suspect that this library is a bit slower performance wise, but
> I think that's just a cost we'll have to pay to being able to play with
> dynamic strings.
> >> >
> >> >
> >> > Hope to get feedback from someone!
> >> >
> >> > On Thu, Dec 16, 2010 at 1:11 AM, Alan Burlison <
> > wrote:
> >> > On 15/12/2010 16:19, David A. Mellis wrote:
> >> >
> >> > I think you're right, but I also don't think that telling people to
> >> > use the standard C library functions is a solution either. Trying out
> >> > this String class seems like one way of pushing forwards towards a
> >> > compromise that provides both an easy-to-use API and a robust
> >> > implementation. For example, perhaps the buffer sizes need to be
> >> > specified or provided when the String is instantiated. Or we need an
> >> > alternative implementation that does more reliable memory allocation
> >> > (since we're not assuming that the internal buffer is continuous).
> >> > Other ideas welcome.
> >> >
> >> > I think the problem is that the failure modes are not benign. I
> haven't been through all the use cases so this might not work, but perhaps
> using a statically-allocated string ("NOMEM" ?) as a sentinel value instead
> of null when malloc fails might be one way? Also, there might be some
> benefit in making String immutable a la Java - overloaded operators in C++
> have a tendency to generate anonymous temporaries, which is going to lead to
> heap fragmentation as well.
> >> >
> >> > --
> >> > Alan Burlison
> >> > --
> >> >
> >> > _______________________________________________
___________________________________________________

Posted on the Developers mailing list. Go to http://arduino.cc/mailman/listinfo/developers_arduino.cc to subscribe. Is this test suite any different than the one in the github repo?

t.

On Jan 4, 2011, at 12:53 PM, Rick Anderson wrote:

> I just created a test and unpacked and tested it. I also created a
> test based on Tom's code. Not sure I caught the maximum value error
> for 0xFF.
>
> I also ran the tests for bug 411. All the tests compile, but there is
> still memory loss.
>
> I'm attaching the Arduino Test suite, and the test code so you can run
> them as you debug. Let me know if this was helpful.
>
> --Rick
>
> Test run results:
> Example: ATS_StringAssignmentTest.pde
> info.MANUFACTURER = Arduino
> info.CPU-NAME = ATmega328P
> info.GCC-Version = 4.3.2
> info.AVR-LibC-Ver = 1.6.4
> info.Compiled-date = Jan 4 2011
> info.Test-Suite-Name = ATS_StringAssignmentTest
> info.Free-memory = 1110 bytes
> Memory Usage (lost 59 bytes) ... FAIL
> --------------------------
> Ran 1 tests in 1.378s
>
> FAILED (failures=1)
>
>
> Example: ATS_StringMemoryTestPassByReference.pde
>
> info.MANUFACTURER = Arduino
> info.CPU-NAME = ATmega328P
> info.GCC-Version = 4.3.2
> info.AVR-LibC-Ver = 1.6.4
> info.Compiled-date = Jan 4 2011
> info.Test-Suite-Name = ATS_StringMemoryTestPassByReference
> info.Free-memory = 1120 bytes
> Memory Usage (lost 59 bytes) ... FAIL
> --------------------------
> Ran 1 tests in 1.389s
>
> FAILED (failures=1)
>
>
> Example: Tom Igoe Memory Test
> info.MANUFACTURER = Arduino
> info.CPU-NAME = ATmega328P
> info.GCC-Version = 4.3.2
> info.AVR-LibC-Ver = 1.6.4
> info.Compiled-date = Jan 4 2011
> info.Test-Suite-Name = Tom Igoe Memory Test
> info.Free-memory = 1328 bytes
> Memory Usage (lost 9 bytes) ... FAIL
> --------------------------
> Ran 1 tests in 1.374s
>
> FAILED (failures=1)
>
>
>
> --Rick
>
> Tom, rewrote your example as a test.
>
> //************************************************************************
> //* Arduino Tom Igoe Memory Test
> //* (C) 2010 by Rick Anderson
> //* Open source as per standard Arduino code
> //*
> //************************************************************************
> //* Jan 4, 2011 Started on Tom Igoe Memory Test
> //************************************************************************
>
> #include "WProgram.h"
> #include "HardwareSerial.h"
> #include
>
> //************************************************************************
> void setup()
> {
> int startMemoryUsage;
> /*
> * Create variable for the tests.
> */
>
> String webColor = "#000000";
>
> int red = 1023/4;
> int blue = 512/4;
> int green = 128/4;
>
> /*
> * initiate the test run
> */
> //Record starting memory amount
> startMemoryUsage = ATS_GetFreeMemory();
> //Begin test run
> ATS_begin("Arduino", "Tom Igoe Memory Test");
>
> webColor = "#";
> webColor += String(red, HEX);
> webColor += String(green, HEX);
> webColor += String(blue, HEX);
>
> ATS_ReportMemoryUsage(startMemoryUsage);
>
> /*
> * Test complete
> */
>
> ATS_end();
> }
>
>
> //************************************************************************
> void loop()
> {
>
>
> }
>
>
>
>
> On Mon, Jan 3, 2011 at 9:35 PM, Tom Igoe <> wrote:
>> It broke in the non-SDM version too, but it took longer to break. In the SDM version it breaks immediately. So it looks like whatever you did highlights the faults sooner, which is good. It also points to a need for an error response of some sort, in answer to your question last mail.
>>
>> t.
>>
>> On Jan 3, 2011, at 4:44 PM, Alexander Brevig wrote:
>>
>>> That breaking of String, does it only occur with the SDM version?
>>>
>>> If not, did you find any way to break it? Maybe any of the old faults related to memory?
>>>
>>>
>>> I actually have no time to check this myself right now, so I opted to just ask you.
>>>
>>> On Mon, Jan 3, 2011 at 10:35 PM, Tom Igoe <> wrote:
>>> Thanks, Alexander, and sorry for the delay.
>>>
>>> A few tests:
>>>
>>> For code that doesn't change the strings much, there's not a big difference, a couple dozen bytes' difference in code size. However, when you start to do dynamic things, it does add up. For example, the StringAppendOperator example is 4910 bytes in 0022, and 5148 bytes with the StaticDynamicMemory version. So it does start to take its toll, memory-wise.
>>>
>>> On some sketches it actually takes less memory. For example, the one below is 3738 bytes using the StaticDynamicMemory version, and 3986 bytes in 0022. However, it fails entirely on upload. When the value of (analog 0)/4 is high (0xFF), it never gets out of the setup(). So there's still a pretty easy way to break String, even with these improvements.
>>>
>>>
>>> void setup() {
>>> Serial.begin(9600);
>>> Serial.println("Beginning");
>>> }
>>>
>>> void loop() {
>>>
>>> String webColor = "#";
>>>
>>> int red = analogRead(A0)/4;
>>> webColor += String(red, HEX);
>>> int green = analogRead(A1)/4;
>>> webColor += String(green, HEX);
>>> int blue = analogRead(A2)/4;
>>>
>>> webColor += String(blue, HEX);
>>> Serial.println(webColor);
>>> }
>>>
>>>
>>>
>>>
>>>
>>> On Dec 16, 2010, at 1:27 AM, Alexander Brevig wrote:
>>>
>>>> Attached is a zip containing WString.h and .cpp plus StaticDynamicMemory.h.
>>>> Take a backup of the original WString files, and extract this zip into the hardware/arduino/cores/arduino folder.
>>>>
>>>> Now you're ready to test the modified String library, that does not fragment the heap.
>>>>
>>>>
>>>> In the WString header there is a #define called STRING_BUFFER which is set to 100 for now, change this to suit your test needs.
>>>>
>>>>
>>>> No error handling is implemented, what do you think we need?
>>>>
>>>> I plan to add an availableMemory():int method to the SDM library, and maybe some error flags and checks like hasError():int error
>>>>
>>>> I also suspect that this library is a bit slower performance wise, but I think that's just a cost we'll have to pay to being able to play with dynamic strings.
>>>>
>>>>
>>>> Hope to get feedback from someone!
>>>>
>>>> On Thu, Dec 16, 2010 at 1:11 AM, Alan Burlison <> wrote:
>>>> On 15/12/2010 16:19, David A. Mellis wrote:
>>>>
>>>> I think you're right, but I also don't think that telling people to
>>>> use the standard C library functions is a solution either. Trying out
>>>> this String class seems like one way of pushing forwards towards a
>>>> compromise that provides both an easy-to-use API and a robust
>>>> implementation. For example, perhaps the buffer sizes need to be
>>>> specified or provided when the String is instantiated. Or we need an
>>>> alternative implementation that does more reliable memory allocation
>>>> (since we're not assuming that the internal buffer is continuous).
>>>> Other ideas welcome.
>>>>
>>>> I think the problem is that the failure modes are not benign. I haven't been through all the use cases so this might not work, but perhaps using a statically-allocated string ("NOMEM" ?) as a sentinel value instead of null when malloc fails might be one way? Also, there might be some benefit in making String immutable a la Java - overloaded operators in C++ have a tendency to generate anonymous temporaries, which is going to lead to heap fragmentation as well.
>>>>
>>>> --
>>>> Alan Burlison
>>>> --
>>>>
>>>> _______________________________________________
___________________________________________________

Posted on the Developers mailing list. Go to http://arduino.cc/mailman/listinfo/developers_arduino.cc to subscribe. Same exact one. I just included it just in case.

--Rick

On Tue, Jan 4, 2011 at 9:01 PM, Tom Igoe <> wrote:
> Is this test suite any different than the one in the github repo?
>
> t.
>
> On Jan 4, 2011, at 12:53 PM, Rick Anderson wrote:
>
>> I just created a test and unpacked and tested it. I also created a
>> test based on Tom's code. Not sure I caught the maximum value error
>> for 0xFF.
>>
>> I also ran the tests for bug 411. All the tests compile, but there is
>> still memory loss.
>>
>> I'm attaching the Arduino Test suite, and the test code so you can run
>> them as you debug. Let me know if this was helpful.
>>
>> --Rick
>>
>> Test run results:
>> Example:  ATS_StringAssignmentTest.pde
>> info.MANUFACTURER    = Arduino
>> info.CPU-NAME        = ATmega328P
>> info.GCC-Version     = 4.3.2
>> info.AVR-LibC-Ver    = 1.6.4
>> info.Compiled-date   = Jan  4 2011
>> info.Test-Suite-Name = ATS_StringAssignmentTest
>> info.Free-memory     = 1110 bytes
>> Memory Usage (lost 59 bytes)                                ... FAIL
>> --------------------------
>> Ran 1 tests in 1.378s
>>
>> FAILED (failures=1)
>>
>>
>> Example: ATS_StringMemoryTestPassByReference.pde
>>
>> info.MANUFACTURER    = Arduino
>> info.CPU-NAME        = ATmega328P
>> info.GCC-Version     = 4.3.2
>> info.AVR-LibC-Ver    = 1.6.4
>> info.Compiled-date   = Jan  4 2011
>> info.Test-Suite-Name = ATS_StringMemoryTestPassByReference
>> info.Free-memory     = 1120 bytes
>> Memory Usage (lost 59 bytes)                                ... FAIL
>> --------------------------
>> Ran 1 tests in 1.389s
>>
>> FAILED (failures=1)
>>
>>
>> Example: Tom Igoe Memory Test
>> info.MANUFACTURER    = Arduino
>> info.CPU-NAME        = ATmega328P
>> info.GCC-Version     = 4.3.2
>> info.AVR-LibC-Ver    = 1.6.4
>> info.Compiled-date   = Jan  4 2011
>> info.Test-Suite-Name = Tom Igoe Memory Test
>> info.Free-memory     = 1328 bytes
>> Memory Usage (lost 9 bytes)                                 ... FAIL
>> --------------------------
>> Ran 1 tests in 1.374s
>>
>> FAILED (failures=1)
>>
>>
>>
>> --Rick
>>
>> Tom, rewrote your example as a test.
>>
>> //************************************************************************
>> //*   Arduino Tom Igoe Memory Test
>> //*           (C) 2010 by Rick Anderson
>> //*           Open source as per standard Arduino code
>> //*
>> //************************************************************************
>> //*   Jan 4,  2011     Started on Tom Igoe Memory Test
>> //************************************************************************
>>
>> #include      "WProgram.h"
>> #include      "HardwareSerial.h"
>> #include      
>>
>> //************************************************************************
>> void setup()
>> {
>>  int          startMemoryUsage;
>>  /*
>>    * Create variable for the tests.
>>   */
>>
>>  String webColor = "#000000";
>>
>>  int red = 1023/4;
>>  int blue = 512/4;
>>  int green = 128/4;
>>
>>  /*
>>  * initiate the test run
>>   */
>>  //Record starting memory amount
>>  startMemoryUsage     =       ATS_GetFreeMemory();
>>  //Begin test run
>>  ATS_begin("Arduino", "Tom Igoe Memory Test");
>>
>>  webColor = "#";
>>  webColor += String(red, HEX);
>>  webColor += String(green, HEX);
>>  webColor += String(blue, HEX);
>>
>>  ATS_ReportMemoryUsage(startMemoryUsage);
>>
>>  /*
>>   * Test complete
>>   */
>>
>>  ATS_end();
>> }
>>
>>
>> //************************************************************************
>> void loop()
>> {
>>
>>
>> }
>>
>>
>>
>>
>> On Mon, Jan 3, 2011 at 9:35 PM, Tom Igoe <> wrote:
>>> It broke in the non-SDM version too, but it took longer to break. In the SDM version it breaks immediately. So it looks like whatever you did highlights the faults sooner, which is good. It also points to a need for an error response of some sort, in answer to your question last mail.
>>>
>>> t.
>>>
>>> On Jan 3, 2011, at 4:44 PM, Alexander Brevig wrote:
>>>
>>>> That breaking of String, does it only occur with the SDM version?
>>>>
>>>> If not, did you find any way to break it? Maybe any of the old faults related to memory?
>>>>
>>>>
>>>> I actually have no time to check this myself right now, so I opted to just ask you.
>>>>
>>>> On Mon, Jan 3, 2011 at 10:35 PM, Tom Igoe <> wrote:
>>>> Thanks, Alexander, and sorry for the delay.
>>>>
>>>> A few tests:
>>>>
>>>> For code that doesn't change the strings much, there's not a big difference, a couple dozen bytes' difference in code size.  However, when you start to do dynamic things, it does add up.  For example, the StringAppendOperator example is  4910 bytes in 0022, and 5148 bytes with the StaticDynamicMemory version. So it does start to take its toll, memory-wise.
>>>>
>>>> On some sketches it actually takes less memory.  For example, the one below is 3738 bytes using the StaticDynamicMemory version, and 3986 bytes in 0022.  However, it fails entirely on upload.  When the value of (analog 0)/4 is high (0xFF), it never gets out of the setup(). So there's still a pretty easy way to break String, even with these improvements.
>>>>
>>>>
>>>> void setup() {
>>>>  Serial.begin(9600);
>>>>  Serial.println("Beginning");
>>>> }
>>>>
>>>> void loop() {
>>>>
>>>>  String webColor = "#";
>>>>
>>>>  int red = analogRead(A0)/4;
>>>>  webColor += String(red, HEX);
>>>>  int green = analogRead(A1)/4;
>>>>  webColor += String(green, HEX);
>>>>  int blue = analogRead(A2)/4;
>>>>
>>>>  webColor += String(blue, HEX);
>>>>  Serial.println(webColor);
>>>> }
>>>>
>>>>
>>>>
>>>>
>>>>
>>>> On Dec 16, 2010, at 1:27 AM, Alexander Brevig wrote:
>>>>
>>>>> Attached is a zip containing WString.h and .cpp plus StaticDynamicMemory.h.
>>>>> Take a backup of the original WString files, and extract this zip into the hardware/arduino/cores/arduino folder.
>>>>>
>>>>> Now you're ready to test the modified String library, that does not fragment the heap.
>>>>>
>>>>>
>>>>> In the WString header there is a #define called STRING_BUFFER which is set to 100 for now, change this to suit your test needs.
>>>>>
>>>>>
>>>>> No error handling is implemented, what do you think we need?
>>>>>
>>>>> I plan to add an availableMemory():int method to the SDM library, and maybe some error flags and checks like hasError():int error
>>>>>
>>>>> I also suspect that this library is a bit slower performance wise, but I think that's just a cost we'll have to pay to being able to play with dynamic strings.
>>>>>
>>>>>
>>>>> Hope to  get feedback from someone!
>>>>>
>>>>> On Thu, Dec 16, 2010 at 1:11 AM, Alan Burlison <> wrote:
>>>>> On 15/12/2010 16:19, David A. Mellis wrote:
>>>>>
>>>>> I think you're right, but I also don't think that telling people to
>>>>> use the standard C library functions is a solution either.  Trying out
>>>>> this String class seems like one way of pushing forwards towards a
>>>>> compromise that provides both an easy-to-use API and a robust
>>>>> implementation.  For example, perhaps the buffer sizes need to be
>>>>> specified or provided when the String is instantiated.  Or we need an
>>>>> alternative implementation that does more reliable memory allocation
>>>>> (since we're not assuming that the internal buffer is continuous).
>>>>> Other ideas welcome.
>>>>>
>>>>> I think the problem is that the failure modes are not benign.  I haven't been through all the use cases so this might not work, but perhaps using a statically-allocated string ("NOMEM" ?) as a sentinel value instead of null when malloc fails might be one way?  Also, there might be some benefit in making String immutable a la Java - overloaded operators in C++ have a tendency to generate anonymous temporaries, which is going to lead to heap fragmentation as well.
>>>>>
>>>>> --
>>>>> Alan Burlison
>>>>> --
>>>>>
>>>>> _______________________________________________
___________________________________________________

Posted on the Developers mailing list. Go to http://arduino.cc/mailman/listinfo/developers_arduino.cc to subscribe. On 04/01/2011 17:53, Rick Anderson wrote:

> I also ran the tests for bug 411. All the tests compile, but there is
> still memory loss.

Most of the assumptions made by the test harness and test case code are
wrong, any reports of 'lost' memory are therefore likely to be wrong as
well. If you want to do leak detection you can't do it in the naive way
it is being done at present.

--
Alan Burlison
--

_______________________________________________
___________________________________________________

Posted on the Developers mailing list. Go to http://arduino.cc/mailman/listinfo/developers_arduino.cc to subscribe. Alan,

The tests themselves are quick and dirty, and not strategic or
comprehensive. I'd like your input to create a good procedure for
memory testing. I also have feedback from Paul Stoffregen for the test
suite:
----
Another problem involves gcc's optimizer ignoring the inline request
for ATS_ReportMemoryUsage. As the comment in the code explains, it
must be inline to avoid measuring its own stack frame. I believe
adding this line in ArduinoTestSuite.h fixes the problem by forcing
gcc to inline.

inline void ATS_ReportMemoryUsage(int _memoryUsageAtStart)
__attribute__((always_inline, unused));

The last problem is a tiny bit of dynamic memory permanently held for
the free list. To allow for this, the test really should call
malloc() and free() once, so the allocator is fully initialized before
testing.
----

I'd like to combine both sets of feedback, and set up some issues in
the system, then fix them. Is the above the problem you saw? Are their
other assumptions that would impact measuring memory? And updating the
memory test in the the test suite.

In terms of creating tests for memory leaks. It looks best to move all
the memory usage inside a function. What else could be done to
constrain the problem, and measuring more affectively.

I'm traveling back to NJ today, so I can't respond right away.

--Rick

On Wed, Jan 5, 2011 at 8:52 AM, Alan Burlison <> wrote:
> On 04/01/2011 17:53, Rick Anderson wrote:
>
>> I also ran the tests for bug 411. All the tests compile, but there is
>> still memory loss.
>
> Most of the assumptions made by the test harness and test case code are
> wrong, any reports of 'lost' memory are therefore likely to be wrong as
> well.  If you want to do leak detection you can't do it in the naive way it
> is being done at present.
>
> --
> Alan Burlison
> --
>



--
President
Fair Use Building and Research (****) Labs
http://fubarlabs.org

_______________________________________________
___________________________________________________

Posted on the Developers mailing list. Go to http://arduino.cc/mailman/listinfo/developers_arduino.cc to subscribe. On 05/01/2011 15:19, Rick Anderson wrote:

> ----
> Another problem involves gcc's optimizer ignoring the inline request
> for ATS_ReportMemoryUsage. As the comment in the code explains, it
> must be inline to avoid measuring its own stack frame. I believe
> adding this line in ArduinoTestSuite.h fixes the problem by forcing
> gcc to inline.
>
> inline void ATS_ReportMemoryUsage(int _memoryUsageAtStart)
> __attribute__((always_inline, unused));

Yes, that's one of the problems. And even the __attribute__
'workaround' is a fragile hack.

> The last problem is a tiny bit of dynamic memory permanently held for
> the free list. To allow for this, the test really should call
> malloc() and free() once, so the allocator is fully initialized before

That's part of a problem, but an initial call malloc/free call isn't
guaranteed to make all the issues go away either. From looking at the
avr-libc malloc implementation it does try to coalesce the heap, but
relying on multiple malloc implementation artefacts is a really bad idea
- there's no guarantee that future malloc implementations will always
coalesce on every free, and there's no guarantee that __bss_end or
__brkval will always be adjusted on each malloc/free call.

The other issue is that of object lifetimes. The test code has
instances of String objects which are allocated on the stack and that
are still in scope when the 'leak' memory check is performed. That
means the String destructors won't have been called and the dynamically
allocated part of the String will still be allocated.

A true memory leak is a block of allocated memory that has no references
to it. However that's not what the test code is checking for. If a
library routine used malloc to perform a one-time library-private buffer
allocation where the buffer is retained for the lifetime of the program,
the current leak checking would incorrectly report that as a leak. It
isn't a leak because there's still a reference to the block inside the
library.

The only semi-reliable way to do what you want is to use an instrumented
malloc implementation, and that's going to be very difficult to
implement on a constrained platform such as the AVR. If you want to
test the String implementation for leaks, my advice is to do it on a
more capable platform (e.g. *nix) and use one of the many instrumented
mallocs that are available.

--
Alan Burlison
--

_______________________________________________
___________________________________________________

Posted on the Developers mailing list. Go to http://arduino.cc/mailman/listinfo/developers_arduino.cc to subscribe. Slightly unrelated to what you guys are discussing now but:
I'm not sure if I've made this clear, but the new version of String that I'm
working on now does not use malloc or any other c function for dynamic
memory. What happens is that I allocate memory statically on the stack and
serve that memory dynamically to the instances of String.

I have some time on my hands now and have a look at getting the += not to
break the code

On Wed, Jan 5, 2011 at 7:10 PM, Alan Burlison <>wrote:

> On 05/01/2011 15:19, Rick Anderson wrote:
>
> ----
>> Another problem involves gcc's optimizer ignoring the inline request
>> for ATS_ReportMemoryUsage. As the comment in the code explains, it
>> must be inline to avoid measuring its own stack frame. I believe
>> adding this line in ArduinoTestSuite.h fixes the problem by forcing
>> gcc to inline.
>>
>> inline void ATS_ReportMemoryUsage(int _memoryUsageAtStart)
>> __attribute__((always_inline, unused));
>>
>
> Yes, that's one of the problems. And even the __attribute__ 'workaround'
> is a fragile hack.
>
>
> The last problem is a tiny bit of dynamic memory permanently held for
>> the free list. To allow for this, the test really should call
>> malloc() and free() once, so the allocator is fully initialized before
>>
>
> That's part of a problem, but an initial call malloc/free call isn't
> guaranteed to make all the issues go away either. From looking at the
> avr-libc malloc implementation it does try to coalesce the heap, but relying
> on multiple malloc implementation artefacts is a really bad idea - there's
> no guarantee that future malloc implementations will always coalesce on
> every free, and there's no guarantee that __bss_end or __brkval will always
> be adjusted on each malloc/free call.
>
> The other issue is that of object lifetimes. The test code has instances
> of String objects which are allocated on the stack and that are still in
> scope when the 'leak' memory check is performed. That means the String
> destructors won't have been called and the dynamically allocated part of the
> String will still be allocated.
>
> A true memory leak is a block of allocated memory that has no references to
> it. However that's not what the test code is checking for. If a library
> routine used malloc to perform a one-time library-private buffer allocation
> where the buffer is retained for the lifetime of the program, the current
> leak checking would incorrectly report that as a leak. It isn't a leak
> because there's still a reference to the block inside the library.
>
> The only semi-reliable way to do what you want is to use an instrumented
> malloc implementation, and that's going to be very difficult to implement on
> a constrained platform such as the AVR. If you want to test the String
> implementation for leaks, my advice is to do it on a more capable platform
> (e.g. *nix) and use one of the many instrumented mallocs that are available.
>
> --
> Alan Burlison
> --
>
>
> _______________________________________________
___________________________________________________

Posted on the Developers mailing list. Go to http://arduino.cc/mailman/listinfo/developers_arduino.cc to subscribe. On 05/01/2011 18:25, Alexander Brevig wrote:

> Slightly unrelated to what you guys are discussing now but:
> I'm not sure if I've made this clear, but the new version of String that I'm
> working on now does not use malloc or any other c function for dynamic
> memory. What happens is that I allocate memory statically on the stack and
> serve that memory dynamically to the instances of String.

Does that mean that the total space occupied by all Strings has to be
decided up front? If so, what is the behaviour when an allocation fails?

To be honest I don't really see the point of doing this - all you are
doing is re-implementing malloc.

--
Alan Burlison
--

_______________________________________________
___________________________________________________

Posted on the Developers mailing list. Go to http://arduino.cc/mailman/listinfo/developers_arduino.cc to subscribe. No, actually I am not reimplementing malloc, because my algorithm guarantees
no fragmentation and always 100% effective use of the allocated memory.

"Does that mean that the total space occupied by all Strings has to be
decided up front? "
Yes, just like the buffer for the serial ++

I know I would opt to have the restriction for a predetermined allocated
space WITH error reporting (how we do is up to you guys, feed me with ideas
I'll implement whatever we agree is best) than having
seemingly infinite memory that crashes and burns.

On Wed, Jan 5, 2011 at 7:33 PM, Alan Burlison <>wrote:

> On 05/01/2011 18:25, Alexander Brevig wrote:
>
> Slightly unrelated to what you guys are discussing now but:
>> I'm not sure if I've made this clear, but the new version of String that
>> I'm
>> working on now does not use malloc or any other c function for dynamic
>> memory. What happens is that I allocate memory statically on the stack and
>> serve that memory dynamically to the instances of String.
>>
>
> Does that mean that the total space occupied by all Strings has to be
> decided up front? If so, what is the behaviour when an allocation fails?
>
> To be honest I don't really see the point of doing this - all you are doing
> is re-implementing malloc.
>
> --
> Alan Burlison
> --
> Well, that was easy (seemingly, probably just jinxed myself...) but here the
test does no longer break, and the usage of memory never exceeds 11 bytes.

It would be awesome if someone would test it.


Also, please tell me now if this effort will lead to nowhere. Is the cost of
being constrained to a buffer size a deal-breaker?

On Wed, Jan 5, 2011 at 7:42 PM, Alexander Brevig
<>wrote:

> No, actually I am not reimplementing malloc, because my algorithm
> guarantees no fragmentation and always 100% effective use of the allocated
> memory.
>
> "Does that mean that the total space occupied by all Strings has to be
> decided up front? "
> Yes, just like the buffer for the serial ++
>
> I know I would opt to have the restriction for a predetermined allocated
> space WITH error reporting (how we do is up to you guys, feed me with ideas
> I'll implement whatever we agree is best) than having
> seemingly infinite memory that crashes and burns.
>
> On Wed, Jan 5, 2011 at 7:33 PM, Alan Burlison <>wrote:
>
>> On 05/01/2011 18:25, Alexander Brevig wrote:
>>
>> Slightly unrelated to what you guys are discussing now but:
>>> I'm not sure if I've made this clear, but the new version of String that
>>> I'm
>>> working on now does not use malloc or any other c function for dynamic
>>> memory. What happens is that I allocate memory statically on the stack
>>> and
>>> serve that memory dynamically to the instances of String.
>>>
>>
>> Does that mean that the total space occupied by all Strings has to be
>> decided up front? If so, what is the behaviour when an allocation fails?
>>
>> To be honest I don't really see the point of doing this - all you are
>> doing is re-implementing malloc.
>>
>> --
>> Alan Burlison
>> --
>>
>
> So sorry you all! I shipped my test code (for msvc++ compiler) in five
minutes I'll post an arduino compatible version. So sorry for this spam!

On Wed, Jan 5, 2011 at 8:01 PM, Alexander Brevig
<>wrote:

> Well, that was easy (seemingly, probably just jinxed myself...) but here
> the test does no longer break, and the usage of memory never exceeds 11
> bytes.
>
> It would be awesome if someone would test it.
>
>
> Also, please tell me now if this effort will lead to nowhere. Is the cost
> of being constrained to a buffer size a deal-breaker?
>
>
> On Wed, Jan 5, 2011 at 7:42 PM, Alexander Brevig <
> > wrote:
>
>> No, actually I am not reimplementing malloc, because my algorithm
>> guarantees no fragmentation and always 100% effective use of the allocated
>> memory.
>>
>> "Does that mean that the total space occupied by all Strings has to be
>> decided up front? "
>> Yes, just like the buffer for the serial ++
>>
>> I know I would opt to have the restriction for a predetermined allocated
>> space WITH error reporting (how we do is up to you guys, feed me with ideas
>> I'll implement whatever we agree is best) than having
>> seemingly infinite memory that crashes and burns.
>>
>> On Wed, Jan 5, 2011 at 7:33 PM, Alan Burlison <>wrote:
>>
>>> On 05/01/2011 18:25, Alexander Brevig wrote:
>>>
>>> Slightly unrelated to what you guys are discussing now but:
>>>> I'm not sure if I've made this clear, but the new version of String that
>>>> I'm
>>>> working on now does not use malloc or any other c function for dynamic
>>>> memory. What happens is that I allocate memory statically on the stack
>>>> and
>>>> serve that memory dynamically to the instances of String.
>>>>
>>>
>>> Does that mean that the total space occupied by all Strings has to be
>>> decided up front? If so, what is the behaviour when an allocation fails?
>>>
>>> To be honest I don't really see the point of doing this - all you are
>>> doing is re-implementing malloc.
>>>
>>> --
>>> Alan Burlison
>>> --
>>>
>>
>>
>

  #14  
05-01-2011 07:09 PM
Developers member admin is online now
User
 

That breaking of String, does it only occur with the SDM version?

If not, did you find any way to break it? Maybe any of the old faults
related to memory?


I actually have no time to check this myself right now, so I opted to just
ask you.

On Mon, Jan 3, 2011 at 10:35 PM, Tom Igoe <> wrote:

> Thanks, Alexander, and sorry for the delay.
>
> A few tests:
>
> For code that doesn't change the strings much, there's not a big
> difference, a couple dozen bytes' difference in code size. However, when
> you start to do dynamic things, it does add up. For example, the
> StringAppendOperator example is 4910 bytes in 0022, and 5148 bytes with the
> StaticDynamicMemory version. So it does start to take its toll, memory-wise.
>
> On some sketches it actually takes less memory. For example, the one below
> is 3738 bytes using the StaticDynamicMemory version, and 3986 bytes in 0022.
> However, it fails entirely on upload. When the value of (analog 0)/4 is
> high (0xFF), it never gets out of the setup(). So there's still a pretty
> easy way to break String, even with these improvements.
>
>
> void setup() {
> Serial.begin(9600);
> Serial.println("Beginning");
> }
>
> void loop() {
>
> String webColor = "#";
>
> int red = analogRead(A0)/4;
> webColor += String(red, HEX);
> int green = analogRead(A1)/4;
> webColor += String(green, HEX);
> int blue = analogRead(A2)/4;
>
> webColor += String(blue, HEX);
> Serial.println(webColor);
> }
>
>
>
>
>
> On Dec 16, 2010, at 1:27 AM, Alexander Brevig wrote:
>
> > Attached is a zip containing WString.h and .cpp plus
> StaticDynamicMemory.h.
> > Take a backup of the original WString files, and extract this zip into
> the hardware/arduino/cores/arduino folder.
> >
> > Now you're ready to test the modified String library, that does not
> fragment the heap.
> >
> >
> > In the WString header there is a #define called STRING_BUFFER which is
> set to 100 for now, change this to suit your test needs.
> >
> >
> > No error handling is implemented, what do you think we need?
> >
> > I plan to add an availableMemory():int method to the SDM library, and
> maybe some error flags and checks like hasError():int error
> >
> > I also suspect that this library is a bit slower performance wise, but I
> think that's just a cost we'll have to pay to being able to play with
> dynamic strings.
> >
> >
> > Hope to get feedback from someone!
> >
> > On Thu, Dec 16, 2010 at 1:11 AM, Alan Burlison <>
> wrote:
> > On 15/12/2010 16:19, David A. Mellis wrote:
> >
> > I think you're right, but I also don't think that telling people to
> > use the standard C library functions is a solution either. Trying out
> > this String class seems like one way of pushing forwards towards a
> > compromise that provides both an easy-to-use API and a robust
> > implementation. For example, perhaps the buffer sizes need to be
> > specified or provided when the String is instantiated. Or we need an
> > alternative implementation that does more reliable memory allocation
> > (since we're not assuming that the internal buffer is continuous).
> > Other ideas welcome.
> >
> > I think the problem is that the failure modes are not benign. I haven't
> been through all the use cases so this might not work, but perhaps using a
> statically-allocated string ("NOMEM" ?) as a sentinel value instead of null
> when malloc fails might be one way? Also, there might be some benefit in
> making String immutable a la Java - overloaded operators in C++ have a
> tendency to generate anonymous temporaries, which is going to lead to heap
> fragmentation as well.
> >
> > --
> > Alan Burlison
> > --
> >
> > _______________________________________________
___________________________________________________

Posted on the Developers mailing list. Go to http://arduino.cc/mailman/listinfo/developers_arduino.cc to subscribe. It broke in the non-SDM version too, but it took longer to break. In the SDM version it breaks immediately. So it looks like whatever you did highlights the faults sooner, which is good. It also points to a need for an error response of some sort, in answer to your question last mail.

t.

On Jan 3, 2011, at 4:44 PM, Alexander Brevig wrote:

> That breaking of String, does it only occur with the SDM version?
>
> If not, did you find any way to break it? Maybe any of the old faults related to memory?
>
>
> I actually have no time to check this myself right now, so I opted to just ask you.
>
> On Mon, Jan 3, 2011 at 10:35 PM, Tom Igoe <> wrote:
> Thanks, Alexander, and sorry for the delay.
>
> A few tests:
>
> For code that doesn't change the strings much, there's not a big difference, a couple dozen bytes' difference in code size. However, when you start to do dynamic things, it does add up. For example, the StringAppendOperator example is 4910 bytes in 0022, and 5148 bytes with the StaticDynamicMemory version. So it does start to take its toll, memory-wise.
>
> On some sketches it actually takes less memory. For example, the one below is 3738 bytes using the StaticDynamicMemory version, and 3986 bytes in 0022. However, it fails entirely on upload. When the value of (analog 0)/4 is high (0xFF), it never gets out of the setup(). So there's still a pretty easy way to break String, even with these improvements.
>
>
> void setup() {
> Serial.begin(9600);
> Serial.println("Beginning");
> }
>
> void loop() {
>
> String webColor = "#";
>
> int red = analogRead(A0)/4;
> webColor += String(red, HEX);
> int green = analogRead(A1)/4;
> webColor += String(green, HEX);
> int blue = analogRead(A2)/4;
>
> webColor += String(blue, HEX);
> Serial.println(webColor);
> }
>
>
>
>
>
> On Dec 16, 2010, at 1:27 AM, Alexander Brevig wrote:
>
> > Attached is a zip containing WString.h and .cpp plus StaticDynamicMemory.h.
> > Take a backup of the original WString files, and extract this zip into the hardware/arduino/cores/arduino folder.
> >
> > Now you're ready to test the modified String library, that does not fragment the heap.
> >
> >
> > In the WString header there is a #define called STRING_BUFFER which is set to 100 for now, change this to suit your test needs.
> >
> >
> > No error handling is implemented, what do you think we need?
> >
> > I plan to add an availableMemory():int method to the SDM library, and maybe some error flags and checks like hasError():int error
> >
> > I also suspect that this library is a bit slower performance wise, but I think that's just a cost we'll have to pay to being able to play with dynamic strings.
> >
> >
> > Hope to get feedback from someone!
> >
> > On Thu, Dec 16, 2010 at 1:11 AM, Alan Burlison <> wrote:
> > On 15/12/2010 16:19, David A. Mellis wrote:
> >
> > I think you're right, but I also don't think that telling people to
> > use the standard C library functions is a solution either. Trying out
> > this String class seems like one way of pushing forwards towards a
> > compromise that provides both an easy-to-use API and a robust
> > implementation. For example, perhaps the buffer sizes need to be
> > specified or provided when the String is instantiated. Or we need an
> > alternative implementation that does more reliable memory allocation
> > (since we're not assuming that the internal buffer is continuous).
> > Other ideas welcome.
> >
> > I think the problem is that the failure modes are not benign. I haven't been through all the use cases so this might not work, but perhaps using a statically-allocated string ("NOMEM" ?) as a sentinel value instead of null when malloc fails might be one way? Also, there might be some benefit in making String immutable a la Java - overloaded operators in C++ have a tendency to generate anonymous temporaries, which is going to lead to heap fragmentation as well.
> >
> > --
> > Alan Burlison
> > --
> >
> > _______________________________________________
___________________________________________________

Posted on the Developers mailing list. Go to http://arduino.cc/mailman/listinfo/developers_arduino.cc to subscribe. There seems to be a bug with the assignment operator, I'm on it and I'll get
back to you as soon as I get something done.

Thank you for your tests and feedback.


I'll do some tests on my own before I repost it here.

On Tue, Jan 4, 2011 at 6:53 PM, Rick Anderson
<>wrote:

> I just created a test and unpacked and tested it. I also created a
> test based on Tom's code. Not sure I caught the maximum value error
> for 0xFF.
>
> I also ran the tests for bug 411. All the tests compile, but there is
> still memory loss.
>
> I'm attaching the Arduino Test suite, and the test code so you can run
> them as you debug. Let me know if this was helpful.
>
> --Rick
>
> Test run results:
> Example: ATS_StringAssignmentTest.pde
> info.MANUFACTURER = Arduino
> info.CPU-NAME = ATmega328P
> info.GCC-Version = 4.3.2
> info.AVR-LibC-Ver = 1.6.4
> info.Compiled-date = Jan 4 2011
> info.Test-Suite-Name = ATS_StringAssignmentTest
> info.Free-memory = 1110 bytes
> Memory Usage (lost 59 bytes) ... FAIL
> --------------------------
> Ran 1 tests in 1.378s
>
> FAILED (failures=1)
>
>
> Example: ATS_StringMemoryTestPassByReference.pde
>
> info.MANUFACTURER = Arduino
> info.CPU-NAME = ATmega328P
> info.GCC-Version = 4.3.2
> info.AVR-LibC-Ver = 1.6.4
> info.Compiled-date = Jan 4 2011
> info.Test-Suite-Name = ATS_StringMemoryTestPassByReference
> info.Free-memory = 1120 bytes
> Memory Usage (lost 59 bytes) ... FAIL
> --------------------------
> Ran 1 tests in 1.389s
>
> FAILED (failures=1)
>
>
> Example: Tom Igoe Memory Test
> info.MANUFACTURER = Arduino
> info.CPU-NAME = ATmega328P
> info.GCC-Version = 4.3.2
> info.AVR-LibC-Ver = 1.6.4
> info.Compiled-date = Jan 4 2011
> info.Test-Suite-Name = Tom Igoe Memory Test
> info.Free-memory = 1328 bytes
> Memory Usage (lost 9 bytes) ... FAIL
> --------------------------
> Ran 1 tests in 1.374s
>
> FAILED (failures=1)
>
>
>
> --Rick
>
> Tom, rewrote your example as a test.
>
> //************************************************************************
> //* Arduino Tom Igoe Memory Test
> //* (C) 2010 by Rick Anderson
> //* Open source as per standard Arduino code
> //*
> //************************************************************************
> //* Jan 4, 2011 Started on Tom Igoe Memory Test
> //************************************************************************
>
> #include "WProgram.h"
> #include "HardwareSerial.h"
> #include
>
> //************************************************************************
> void setup()
> {
> int startMemoryUsage;
> /*
> * Create variable for the tests.
> */
>
> String webColor = "#000000";
>
> int red = 1023/4;
> int blue = 512/4;
> int green = 128/4;
>
> /*
> * initiate the test run
> */
> //Record starting memory amount
> startMemoryUsage = ATS_GetFreeMemory();
> //Begin test run
> ATS_begin("Arduino", "Tom Igoe Memory Test");
>
> webColor = "#";
> webColor += String(red, HEX);
> webColor += String(green, HEX);
> webColor += String(blue, HEX);
>
> ATS_ReportMemoryUsage(startMemoryUsage);
>
> /*
> * Test complete
> */
>
> ATS_end();
> }
>
>
> //************************************************************************
> void loop()
> {
>
>
> }
>
>
>
>
> On Mon, Jan 3, 2011 at 9:35 PM, Tom Igoe <> wrote:
> > It broke in the non-SDM version too, but it took longer to break. In the
> SDM version it breaks immediately. So it looks like whatever you did
> highlights the faults sooner, which is good. It also points to a need for an
> error response of some sort, in answer to your question last mail.
> >
> > t.
> >
> > On Jan 3, 2011, at 4:44 PM, Alexander Brevig wrote:
> >
> >> That breaking of String, does it only occur with the SDM version?
> >>
> >> If not, did you find any way to break it? Maybe any of the old faults
> related to memory?
> >>
> >>
> >> I actually have no time to check this myself right now, so I opted to
> just ask you.
> >>
> >> On Mon, Jan 3, 2011 at 10:35 PM, Tom Igoe <> wrote:
> >> Thanks, Alexander, and sorry for the delay.
> >>
> >> A few tests:
> >>
> >> For code that doesn't change the strings much, there's not a big
> difference, a couple dozen bytes' difference in code size. However, when
> you start to do dynamic things, it does add up. For example, the
> StringAppendOperator example is 4910 bytes in 0022, and 5148 bytes with the
> StaticDynamicMemory version. So it does start to take its toll, memory-wise.
> >>
> >> On some sketches it actually takes less memory. For example, the one
> below is 3738 bytes using the StaticDynamicMemory version, and 3986 bytes in
> 0022. However, it fails entirely on upload. When the value of (analog 0)/4
> is high (0xFF), it never gets out of the setup(). So there's still a pretty
> easy way to break String, even with these improvements.
> >>
> >>
> >> void setup() {
> >> Serial.begin(9600);
> >> Serial.println("Beginning");
> >> }
> >>
> >> void loop() {
> >>
> >> String webColor = "#";
> >>
> >> int red = analogRead(A0)/4;
> >> webColor += String(red, HEX);
> >> int green = analogRead(A1)/4;
> >> webColor += String(green, HEX);
> >> int blue = analogRead(A2)/4;
> >>
> >> webColor += String(blue, HEX);
> >> Serial.println(webColor);
> >> }
> >>
> >>
> >>
> >>
> >>
> >> On Dec 16, 2010, at 1:27 AM, Alexander Brevig wrote:
> >>
> >> > Attached is a zip containing WString.h and .cpp plus
> StaticDynamicMemory.h.
> >> > Take a backup of the original WString files, and extract this zip into
> the hardware/arduino/cores/arduino folder.
> >> >
> >> > Now you're ready to test the modified String library, that does not
> fragment the heap.
> >> >
> >> >
> >> > In the WString header there is a #define called STRING_BUFFER which is
> set to 100 for now, change this to suit your test needs.
> >> >
> >> >
> >> > No error handling is implemented, what do you think we need?
> >> >
> >> > I plan to add an availableMemory():int method to the SDM library, and
> maybe some error flags and checks like hasError():int error
> >> >
> >> > I also suspect that this library is a bit slower performance wise, but
> I think that's just a cost we'll have to pay to being able to play with
> dynamic strings.
> >> >
> >> >
> >> > Hope to get feedback from someone!
> >> >
> >> > On Thu, Dec 16, 2010 at 1:11 AM, Alan Burlison <
> > wrote:
> >> > On 15/12/2010 16:19, David A. Mellis wrote:
> >> >
> >> > I think you're right, but I also don't think that telling people to
> >> > use the standard C library functions is a solution either. Trying out
> >> > this String class seems like one way of pushing forwards towards a
> >> > compromise that provides both an easy-to-use API and a robust
> >> > implementation. For example, perhaps the buffer sizes need to be
> >> > specified or provided when the String is instantiated. Or we need an
> >> > alternative implementation that does more reliable memory allocation
> >> > (since we're not assuming that the internal buffer is continuous).
> >> > Other ideas welcome.
> >> >
> >> > I think the problem is that the failure modes are not benign. I
> haven't been through all the use cases so this might not work, but perhaps
> using a statically-allocated string ("NOMEM" ?) as a sentinel value instead
> of null when malloc fails might be one way? Also, there might be some
> benefit in making String immutable a la Java - overloaded operators in C++
> have a tendency to generate anonymous temporaries, which is going to lead to
> heap fragmentation as well.
> >> >
> >> > --
> >> > Alan Burlison
> >> > --
> >> >
> >> > _______________________________________________
___________________________________________________

Posted on the Developers mailing list. Go to http://arduino.cc/mailman/listinfo/developers_arduino.cc to subscribe. Is this test suite any different than the one in the github repo?

t.

On Jan 4, 2011, at 12:53 PM, Rick Anderson wrote:

> I just created a test and unpacked and tested it. I also created a
> test based on Tom's code. Not sure I caught the maximum value error
> for 0xFF.
>
> I also ran the tests for bug 411. All the tests compile, but there is
> still memory loss.
>
> I'm attaching the Arduino Test suite, and the test code so you can run
> them as you debug. Let me know if this was helpful.
>
> --Rick
>
> Test run results:
> Example: ATS_StringAssignmentTest.pde
> info.MANUFACTURER = Arduino
> info.CPU-NAME = ATmega328P
> info.GCC-Version = 4.3.2
> info.AVR-LibC-Ver = 1.6.4
> info.Compiled-date = Jan 4 2011
> info.Test-Suite-Name = ATS_StringAssignmentTest
> info.Free-memory = 1110 bytes
> Memory Usage (lost 59 bytes) ... FAIL
> --------------------------
> Ran 1 tests in 1.378s
>
> FAILED (failures=1)
>
>
> Example: ATS_StringMemoryTestPassByReference.pde
>
> info.MANUFACTURER = Arduino
> info.CPU-NAME = ATmega328P
> info.GCC-Version = 4.3.2
> info.AVR-LibC-Ver = 1.6.4
> info.Compiled-date = Jan 4 2011
> info.Test-Suite-Name = ATS_StringMemoryTestPassByReference
> info.Free-memory = 1120 bytes
> Memory Usage (lost 59 bytes) ... FAIL
> --------------------------
> Ran 1 tests in 1.389s
>
> FAILED (failures=1)
>
>
> Example: Tom Igoe Memory Test
> info.MANUFACTURER = Arduino
> info.CPU-NAME = ATmega328P
> info.GCC-Version = 4.3.2
> info.AVR-LibC-Ver = 1.6.4
> info.Compiled-date = Jan 4 2011
> info.Test-Suite-Name = Tom Igoe Memory Test
> info.Free-memory = 1328 bytes
> Memory Usage (lost 9 bytes) ... FAIL
> --------------------------
> Ran 1 tests in 1.374s
>
> FAILED (failures=1)
>
>
>
> --Rick
>
> Tom, rewrote your example as a test.
>
> //************************************************************************
> //* Arduino Tom Igoe Memory Test
> //* (C) 2010 by Rick Anderson
> //* Open source as per standard Arduino code
> //*
> //************************************************************************
> //* Jan 4, 2011 Started on Tom Igoe Memory Test
> //************************************************************************
>
> #include "WProgram.h"
> #include "HardwareSerial.h"
> #include
>
> //************************************************************************
> void setup()
> {
> int startMemoryUsage;
> /*
> * Create variable for the tests.
> */
>
> String webColor = "#000000";
>
> int red = 1023/4;
> int blue = 512/4;
> int green = 128/4;
>
> /*
> * initiate the test run
> */
> //Record starting memory amount
> startMemoryUsage = ATS_GetFreeMemory();
> //Begin test run
> ATS_begin("Arduino", "Tom Igoe Memory Test");
>
> webColor = "#";
> webColor += String(red, HEX);
> webColor += String(green, HEX);
> webColor += String(blue, HEX);
>
> ATS_ReportMemoryUsage(startMemoryUsage);
>
> /*
> * Test complete
> */
>
> ATS_end();
> }
>
>
> //************************************************************************
> void loop()
> {
>
>
> }
>
>
>
>
> On Mon, Jan 3, 2011 at 9:35 PM, Tom Igoe <> wrote:
>> It broke in the non-SDM version too, but it took longer to break. In the SDM version it breaks immediately. So it looks like whatever you did highlights the faults sooner, which is good. It also points to a need for an error response of some sort, in answer to your question last mail.
>>
>> t.
>>
>> On Jan 3, 2011, at 4:44 PM, Alexander Brevig wrote:
>>
>>> That breaking of String, does it only occur with the SDM version?
>>>
>>> If not, did you find any way to break it? Maybe any of the old faults related to memory?
>>>
>>>
>>> I actually have no time to check this myself right now, so I opted to just ask you.
>>>
>>> On Mon, Jan 3, 2011 at 10:35 PM, Tom Igoe <> wrote:
>>> Thanks, Alexander, and sorry for the delay.
>>>
>>> A few tests:
>>>
>>> For code that doesn't change the strings much, there's not a big difference, a couple dozen bytes' difference in code size. However, when you start to do dynamic things, it does add up. For example, the StringAppendOperator example is 4910 bytes in 0022, and 5148 bytes with the StaticDynamicMemory version. So it does start to take its toll, memory-wise.
>>>
>>> On some sketches it actually takes less memory. For example, the one below is 3738 bytes using the StaticDynamicMemory version, and 3986 bytes in 0022. However, it fails entirely on upload. When the value of (analog 0)/4 is high (0xFF), it never gets out of the setup(). So there's still a pretty easy way to break String, even with these improvements.
>>>
>>>
>>> void setup() {
>>> Serial.begin(9600);
>>> Serial.println("Beginning");
>>> }
>>>
>>> void loop() {
>>>
>>> String webColor = "#";
>>>
>>> int red = analogRead(A0)/4;
>>> webColor += String(red, HEX);
>>> int green = analogRead(A1)/4;
>>> webColor += String(green, HEX);
>>> int blue = analogRead(A2)/4;
>>>
>>> webColor += String(blue, HEX);
>>> Serial.println(webColor);
>>> }
>>>
>>>
>>>
>>>
>>>
>>> On Dec 16, 2010, at 1:27 AM, Alexander Brevig wrote:
>>>
>>>> Attached is a zip containing WString.h and .cpp plus StaticDynamicMemory.h.
>>>> Take a backup of the original WString files, and extract this zip into the hardware/arduino/cores/arduino folder.
>>>>
>>>> Now you're ready to test the modified String library, that does not fragment the heap.
>>>>
>>>>
>>>> In the WString header there is a #define called STRING_BUFFER which is set to 100 for now, change this to suit your test needs.
>>>>
>>>>
>>>> No error handling is implemented, what do you think we need?
>>>>
>>>> I plan to add an availableMemory():int method to the SDM library, and maybe some error flags and checks like hasError():int error
>>>>
>>>> I also suspect that this library is a bit slower performance wise, but I think that's just a cost we'll have to pay to being able to play with dynamic strings.
>>>>
>>>>
>>>> Hope to get feedback from someone!
>>>>
>>>> On Thu, Dec 16, 2010 at 1:11 AM, Alan Burlison <> wrote:
>>>> On 15/12/2010 16:19, David A. Mellis wrote:
>>>>
>>>> I think you're right, but I also don't think that telling people to
>>>> use the standard C library functions is a solution either. Trying out
>>>> this String class seems like one way of pushing forwards towards a
>>>> compromise that provides both an easy-to-use API and a robust
>>>> implementation. For example, perhaps the buffer sizes need to be
>>>> specified or provided when the String is instantiated. Or we need an
>>>> alternative implementation that does more reliable memory allocation
>>>> (since we're not assuming that the internal buffer is continuous).
>>>> Other ideas welcome.
>>>>
>>>> I think the problem is that the failure modes are not benign. I haven't been through all the use cases so this might not work, but perhaps using a statically-allocated string ("NOMEM" ?) as a sentinel value instead of null when malloc fails might be one way? Also, there might be some benefit in making String immutable a la Java - overloaded operators in C++ have a tendency to generate anonymous temporaries, which is going to lead to heap fragmentation as well.
>>>>
>>>> --
>>>> Alan Burlison
>>>> --
>>>>
>>>> _______________________________________________
___________________________________________________

Posted on the Developers mailing list. Go to http://arduino.cc/mailman/listinfo/developers_arduino.cc to subscribe. Same exact one. I just included it just in case.

--Rick

On Tue, Jan 4, 2011 at 9:01 PM, Tom Igoe <> wrote:
> Is this test suite any different than the one in the github repo?
>
> t.
>
> On Jan 4, 2011, at 12:53 PM, Rick Anderson wrote:
>
>> I just created a test and unpacked and tested it. I also created a
>> test based on Tom's code. Not sure I caught the maximum value error
>> for 0xFF.
>>
>> I also ran the tests for bug 411. All the tests compile, but there is
>> still memory loss.
>>
>> I'm attaching the Arduino Test suite, and the test code so you can run
>> them as you debug. Let me know if this was helpful.
>>
>> --Rick
>>
>> Test run results:
>> Example:  ATS_StringAssignmentTest.pde
>> info.MANUFACTURER    = Arduino
>> info.CPU-NAME        = ATmega328P
>> info.GCC-Version     = 4.3.2
>> info.AVR-LibC-Ver    = 1.6.4
>> info.Compiled-date   = Jan  4 2011
>> info.Test-Suite-Name = ATS_StringAssignmentTest
>> info.Free-memory     = 1110 bytes
>> Memory Usage (lost 59 bytes)                                ... FAIL
>> --------------------------
>> Ran 1 tests in 1.378s
>>
>> FAILED (failures=1)
>>
>>
>> Example: ATS_StringMemoryTestPassByReference.pde
>>
>> info.MANUFACTURER    = Arduino
>> info.CPU-NAME        = ATmega328P
>> info.GCC-Version     = 4.3.2
>> info.AVR-LibC-Ver    = 1.6.4
>> info.Compiled-date   = Jan  4 2011
>> info.Test-Suite-Name = ATS_StringMemoryTestPassByReference
>> info.Free-memory     = 1120 bytes
>> Memory Usage (lost 59 bytes)                                ... FAIL
>> --------------------------
>> Ran 1 tests in 1.389s
>>
>> FAILED (failures=1)
>>
>>
>> Example: Tom Igoe Memory Test
>> info.MANUFACTURER    = Arduino
>> info.CPU-NAME        = ATmega328P
>> info.GCC-Version     = 4.3.2
>> info.AVR-LibC-Ver    = 1.6.4
>> info.Compiled-date   = Jan  4 2011
>> info.Test-Suite-Name = Tom Igoe Memory Test
>> info.Free-memory     = 1328 bytes
>> Memory Usage (lost 9 bytes)                                 ... FAIL
>> --------------------------
>> Ran 1 tests in 1.374s
>>
>> FAILED (failures=1)
>>
>>
>>
>> --Rick
>>
>> Tom, rewrote your example as a test.
>>
>> //************************************************************************
>> //*   Arduino Tom Igoe Memory Test
>> //*           (C) 2010 by Rick Anderson
>> //*           Open source as per standard Arduino code
>> //*
>> //************************************************************************
>> //*   Jan 4,  2011     Started on Tom Igoe Memory Test
>> //************************************************************************
>>
>> #include      "WProgram.h"
>> #include      "HardwareSerial.h"
>> #include      
>>
>> //************************************************************************
>> void setup()
>> {
>>  int          startMemoryUsage;
>>  /*
>>    * Create variable for the tests.
>>   */
>>
>>  String webColor = "#000000";
>>
>>  int red = 1023/4;
>>  int blue = 512/4;
>>  int green = 128/4;
>>
>>  /*
>>  * initiate the test run
>>   */
>>  //Record starting memory amount
>>  startMemoryUsage     =       ATS_GetFreeMemory();
>>  //Begin test run
>>  ATS_begin("Arduino", "Tom Igoe Memory Test");
>>
>>  webColor = "#";
>>  webColor += String(red, HEX);
>>  webColor += String(green, HEX);
>>  webColor += String(blue, HEX);
>>
>>  ATS_ReportMemoryUsage(startMemoryUsage);
>>
>>  /*
>>   * Test complete
>>   */
>>
>>  ATS_end();
>> }
>>
>>
>> //************************************************************************
>> void loop()
>> {
>>
>>
>> }
>>
>>
>>
>>
>> On Mon, Jan 3, 2011 at 9:35 PM, Tom Igoe <> wrote:
>>> It broke in the non-SDM version too, but it took longer to break. In the SDM version it breaks immediately. So it looks like whatever you did highlights the faults sooner, which is good. It also points to a need for an error response of some sort, in answer to your question last mail.
>>>
>>> t.
>>>
>>> On Jan 3, 2011, at 4:44 PM, Alexander Brevig wrote:
>>>
>>>> That breaking of String, does it only occur with the SDM version?
>>>>
>>>> If not, did you find any way to break it? Maybe any of the old faults related to memory?
>>>>
>>>>
>>>> I actually have no time to check this myself right now, so I opted to just ask you.
>>>>
>>>> On Mon, Jan 3, 2011 at 10:35 PM, Tom Igoe <> wrote:
>>>> Thanks, Alexander, and sorry for the delay.
>>>>
>>>> A few tests:
>>>>
>>>> For code that doesn't change the strings much, there's not a big difference, a couple dozen bytes' difference in code size.  However, when you start to do dynamic things, it does add up.  For example, the StringAppendOperator example is  4910 bytes in 0022, and 5148 bytes with the StaticDynamicMemory version. So it does start to take its toll, memory-wise.
>>>>
>>>> On some sketches it actually takes less memory.  For example, the one below is 3738 bytes using the StaticDynamicMemory version, and 3986 bytes in 0022.  However, it fails entirely on upload.  When the value of (analog 0)/4 is high (0xFF), it never gets out of the setup(). So there's still a pretty easy way to break String, even with these improvements.
>>>>
>>>>
>>>> void setup() {
>>>>  Serial.begin(9600);
>>>>  Serial.println("Beginning");
>>>> }
>>>>
>>>> void loop() {
>>>>
>>>>  String webColor = "#";
>>>>
>>>>  int red = analogRead(A0)/4;
>>>>  webColor += String(red, HEX);
>>>>  int green = analogRead(A1)/4;
>>>>  webColor += String(green, HEX);
>>>>  int blue = analogRead(A2)/4;
>>>>
>>>>  webColor += String(blue, HEX);
>>>>  Serial.println(webColor);
>>>> }
>>>>
>>>>
>>>>
>>>>
>>>>
>>>> On Dec 16, 2010, at 1:27 AM, Alexander Brevig wrote:
>>>>
>>>>> Attached is a zip containing WString.h and .cpp plus StaticDynamicMemory.h.
>>>>> Take a backup of the original WString files, and extract this zip into the hardware/arduino/cores/arduino folder.
>>>>>
>>>>> Now you're ready to test the modified String library, that does not fragment the heap.
>>>>>
>>>>>
>>>>> In the WString header there is a #define called STRING_BUFFER which is set to 100 for now, change this to suit your test needs.
>>>>>
>>>>>
>>>>> No error handling is implemented, what do you think we need?
>>>>>
>>>>> I plan to add an availableMemory():int method to the SDM library, and maybe some error flags and checks like hasError():int error
>>>>>
>>>>> I also suspect that this library is a bit slower performance wise, but I think that's just a cost we'll have to pay to being able to play with dynamic strings.
>>>>>
>>>>>
>>>>> Hope to  get feedback from someone!
>>>>>
>>>>> On Thu, Dec 16, 2010 at 1:11 AM, Alan Burlison <> wrote:
>>>>> On 15/12/2010 16:19, David A. Mellis wrote:
>>>>>
>>>>> I think you're right, but I also don't think that telling people to
>>>>> use the standard C library functions is a solution either.  Trying out
>>>>> this String class seems like one way of pushing forwards towards a
>>>>> compromise that provides both an easy-to-use API and a robust
>>>>> implementation.  For example, perhaps the buffer sizes need to be
>>>>> specified or provided when the String is instantiated.  Or we need an
>>>>> alternative implementation that does more reliable memory allocation
>>>>> (since we're not assuming that the internal buffer is continuous).
>>>>> Other ideas welcome.
>>>>>
>>>>> I think the problem is that the failure modes are not benign.  I haven't been through all the use cases so this might not work, but perhaps using a statically-allocated string ("NOMEM" ?) as a sentinel value instead of null when malloc fails might be one way?  Also, there might be some benefit in making String immutable a la Java - overloaded operators in C++ have a tendency to generate anonymous temporaries, which is going to lead to heap fragmentation as well.
>>>>>
>>>>> --
>>>>> Alan Burlison
>>>>> --
>>>>>
>>>>> _______________________________________________
___________________________________________________

Posted on the Developers mailing list. Go to http://arduino.cc/mailman/listinfo/developers_arduino.cc to subscribe. On 04/01/2011 17:53, Rick Anderson wrote:

> I also ran the tests for bug 411. All the tests compile, but there is
> still memory loss.

Most of the assumptions made by the test harness and test case code are
wrong, any reports of 'lost' memory are therefore likely to be wrong as
well. If you want to do leak detection you can't do it in the naive way
it is being done at present.

--
Alan Burlison
--

_______________________________________________
___________________________________________________

Posted on the Developers mailing list. Go to http://arduino.cc/mailman/listinfo/developers_arduino.cc to subscribe. Alan,

The tests themselves are quick and dirty, and not strategic or
comprehensive. I'd like your input to create a good procedure for
memory testing. I also have feedback from Paul Stoffregen for the test
suite:
----
Another problem involves gcc's optimizer ignoring the inline request
for ATS_ReportMemoryUsage. As the comment in the code explains, it
must be inline to avoid measuring its own stack frame. I believe
adding this line in ArduinoTestSuite.h fixes the problem by forcing
gcc to inline.

inline void ATS_ReportMemoryUsage(int _memoryUsageAtStart)
__attribute__((always_inline, unused));

The last problem is a tiny bit of dynamic memory permanently held for
the free list. To allow for this, the test really should call
malloc() and free() once, so the allocator is fully initialized before
testing.
----

I'd like to combine both sets of feedback, and set up some issues in
the system, then fix them. Is the above the problem you saw? Are their
other assumptions that would impact measuring memory? And updating the
memory test in the the test suite.

In terms of creating tests for memory leaks. It looks best to move all
the memory usage inside a function. What else could be done to
constrain the problem, and measuring more affectively.

I'm traveling back to NJ today, so I can't respond right away.

--Rick

On Wed, Jan 5, 2011 at 8:52 AM, Alan Burlison <> wrote:
> On 04/01/2011 17:53, Rick Anderson wrote:
>
>> I also ran the tests for bug 411. All the tests compile, but there is
>> still memory loss.
>
> Most of the assumptions made by the test harness and test case code are
> wrong, any reports of 'lost' memory are therefore likely to be wrong as
> well.  If you want to do leak detection you can't do it in the naive way it
> is being done at present.
>
> --
> Alan Burlison
> --
>



--
President
Fair Use Building and Research (****) Labs
http://fubarlabs.org

_______________________________________________
___________________________________________________

Posted on the Developers mailing list. Go to http://arduino.cc/mailman/listinfo/developers_arduino.cc to subscribe. On 05/01/2011 15:19, Rick Anderson wrote:

> ----
> Another problem involves gcc's optimizer ignoring the inline request
> for ATS_ReportMemoryUsage. As the comment in the code explains, it
> must be inline to avoid measuring its own stack frame. I believe
> adding this line in ArduinoTestSuite.h fixes the problem by forcing
> gcc to inline.
>
> inline void ATS_ReportMemoryUsage(int _memoryUsageAtStart)
> __attribute__((always_inline, unused));

Yes, that's one of the problems. And even the __attribute__
'workaround' is a fragile hack.

> The last problem is a tiny bit of dynamic memory permanently held for
> the free list. To allow for this, the test really should call
> malloc() and free() once, so the allocator is fully initialized before

That's part of a problem, but an initial call malloc/free call isn't
guaranteed to make all the issues go away either. From looking at the
avr-libc malloc implementation it does try to coalesce the heap, but
relying on multiple malloc implementation artefacts is a really bad idea
- there's no guarantee that future malloc implementations will always
coalesce on every free, and there's no guarantee that __bss_end or
__brkval will always be adjusted on each malloc/free call.

The other issue is that of object lifetimes. The test code has
instances of String objects which are allocated on the stack and that
are still in scope when the 'leak' memory check is performed. That
means the String destructors won't have been called and the dynamically
allocated part of the String will still be allocated.

A true memory leak is a block of allocated memory that has no references
to it. However that's not what the test code is checking for. If a
library routine used malloc to perform a one-time library-private buffer
allocation where the buffer is retained for the lifetime of the program,
the current leak checking would incorrectly report that as a leak. It
isn't a leak because there's still a reference to the block inside the
library.

The only semi-reliable way to do what you want is to use an instrumented
malloc implementation, and that's going to be very difficult to
implement on a constrained platform such as the AVR. If you want to
test the String implementation for leaks, my advice is to do it on a
more capable platform (e.g. *nix) and use one of the many instrumented
mallocs that are available.

--
Alan Burlison
--

_______________________________________________
___________________________________________________

Posted on the Developers mailing list. Go to http://arduino.cc/mailman/listinfo/developers_arduino.cc to subscribe. Slightly unrelated to what you guys are discussing now but:
I'm not sure if I've made this clear, but the new version of String that I'm
working on now does not use malloc or any other c function for dynamic
memory. What happens is that I allocate memory statically on the stack and
serve that memory dynamically to the instances of String.

I have some time on my hands now and have a look at getting the += not to
break the code

On Wed, Jan 5, 2011 at 7:10 PM, Alan Burlison <>wrote:

> On 05/01/2011 15:19, Rick Anderson wrote:
>
> ----
>> Another problem involves gcc's optimizer ignoring the inline request
>> for ATS_ReportMemoryUsage. As the comment in the code explains, it
>> must be inline to avoid measuring its own stack frame. I believe
>> adding this line in ArduinoTestSuite.h fixes the problem by forcing
>> gcc to inline.
>>
>> inline void ATS_ReportMemoryUsage(int _memoryUsageAtStart)
>> __attribute__((always_inline, unused));
>>
>
> Yes, that's one of the problems. And even the __attribute__ 'workaround'
> is a fragile hack.
>
>
> The last problem is a tiny bit of dynamic memory permanently held for
>> the free list. To allow for this, the test really should call
>> malloc() and free() once, so the allocator is fully initialized before
>>
>
> That's part of a problem, but an initial call malloc/free call isn't
> guaranteed to make all the issues go away either. From looking at the
> avr-libc malloc implementation it does try to coalesce the heap, but relying
> on multiple malloc implementation artefacts is a really bad idea - there's
> no guarantee that future malloc implementations will always coalesce on
> every free, and there's no guarantee that __bss_end or __brkval will always
> be adjusted on each malloc/free call.
>
> The other issue is that of object lifetimes. The test code has instances
> of String objects which are allocated on the stack and that are still in
> scope when the 'leak' memory check is performed. That means the String
> destructors won't have been called and the dynamically allocated part of the
> String will still be allocated.
>
> A true memory leak is a block of allocated memory that has no references to
> it. However that's not what the test code is checking for. If a library
> routine used malloc to perform a one-time library-private buffer allocation
> where the buffer is retained for the lifetime of the program, the current
> leak checking would incorrectly report that as a leak. It isn't a leak
> because there's still a reference to the block inside the library.
>
> The only semi-reliable way to do what you want is to use an instrumented
> malloc implementation, and that's going to be very difficult to implement on
> a constrained platform such as the AVR. If you want to test the String
> implementation for leaks, my advice is to do it on a more capable platform
> (e.g. *nix) and use one of the many instrumented mallocs that are available.
>
> --
> Alan Burlison
> --
>
>
> _______________________________________________
___________________________________________________

Posted on the Developers mailing list. Go to http://arduino.cc/mailman/listinfo/developers_arduino.cc to subscribe. On 05/01/2011 18:25, Alexander Brevig wrote:

> Slightly unrelated to what you guys are discussing now but:
> I'm not sure if I've made this clear, but the new version of String that I'm
> working on now does not use malloc or any other c function for dynamic
> memory. What happens is that I allocate memory statically on the stack and
> serve that memory dynamically to the instances of String.

Does that mean that the total space occupied by all Strings has to be
decided up front? If so, what is the behaviour when an allocation fails?

To be honest I don't really see the point of doing this - all you are
doing is re-implementing malloc.

--
Alan Burlison
--

_______________________________________________
___________________________________________________

Posted on the Developers mailing list. Go to http://arduino.cc/mailman/listinfo/developers_arduino.cc to subscribe. No, actually I am not reimplementing malloc, because my algorithm guarantees
no fragmentation and always 100% effective use of the allocated memory.

"Does that mean that the total space occupied by all Strings has to be
decided up front? "
Yes, just like the buffer for the serial ++

I know I would opt to have the restriction for a predetermined allocated
space WITH error reporting (how we do is up to you guys, feed me with ideas
I'll implement whatever we agree is best) than having
seemingly infinite memory that crashes and burns.

On Wed, Jan 5, 2011 at 7:33 PM, Alan Burlison <>wrote:

> On 05/01/2011 18:25, Alexander Brevig wrote:
>
> Slightly unrelated to what you guys are discussing now but:
>> I'm not sure if I've made this clear, but the new version of String that
>> I'm
>> working on now does not use malloc or any other c function for dynamic
>> memory. What happens is that I allocate memory statically on the stack and
>> serve that memory dynamically to the instances of String.
>>
>
> Does that mean that the total space occupied by all Strings has to be
> decided up front? If so, what is the behaviour when an allocation fails?
>
> To be honest I don't really see the point of doing this - all you are doing
> is re-implementing malloc.
>
> --
> Alan Burlison
> --
> Well, that was easy (seemingly, probably just jinxed myself...) but here the
test does no longer break, and the usage of memory never exceeds 11 bytes.

It would be awesome if someone would test it.


Also, please tell me now if this effort will lead to nowhere. Is the cost of
being constrained to a buffer size a deal-breaker?

On Wed, Jan 5, 2011 at 7:42 PM, Alexander Brevig
<>wrote:

> No, actually I am not reimplementing malloc, because my algorithm
> guarantees no fragmentation and always 100% effective use of the allocated
> memory.
>
> "Does that mean that the total space occupied by all Strings has to be
> decided up front? "
> Yes, just like the buffer for the serial ++
>
> I know I would opt to have the restriction for a predetermined allocated
> space WITH error reporting (how we do is up to you guys, feed me with ideas
> I'll implement whatever we agree is best) than having
> seemingly infinite memory that crashes and burns.
>
> On Wed, Jan 5, 2011 at 7:33 PM, Alan Burlison <>wrote:
>
>> On 05/01/2011 18:25, Alexander Brevig wrote:
>>
>> Slightly unrelated to what you guys are discussing now but:
>>> I'm not sure if I've made this clear, but the new version of String that
>>> I'm
>>> working on now does not use malloc or any other c function for dynamic
>>> memory. What happens is that I allocate memory statically on the stack
>>> and
>>> serve that memory dynamically to the instances of String.
>>>
>>
>> Does that mean that the total space occupied by all Strings has to be
>> decided up front? If so, what is the behaviour when an allocation fails?
>>
>> To be honest I don't really see the point of doing this - all you are
>> doing is re-implementing malloc.
>>
>> --
>> Alan Burlison
>> --
>>
>
> So sorry you all! I shipped my test code (for msvc++ compiler) in five
minutes I'll post an arduino compatible version. So sorry for this spam!

On Wed, Jan 5, 2011 at 8:01 PM, Alexander Brevig
<>wrote:

> Well, that was easy (seemingly, probably just jinxed myself...) but here
> the test does no longer break, and the usage of memory never exceeds 11
> bytes.
>
> It would be awesome if someone would test it.
>
>
> Also, please tell me now if this effort will lead to nowhere. Is the cost
> of being constrained to a buffer size a deal-breaker?
>
>
> On Wed, Jan 5, 2011 at 7:42 PM, Alexander Brevig <
> > wrote:
>
>> No, actually I am not reimplementing malloc, because my algorithm
>> guarantees no fragmentation and always 100% effective use of the allocated
>> memory.
>>
>> "Does that mean that the total space occupied by all Strings has to be
>> decided up front? "
>> Yes, just like the buffer for the serial ++
>>
>> I know I would opt to have the restriction for a predetermined allocated
>> space WITH error reporting (how we do is up to you guys, feed me with ideas
>> I'll implement whatever we agree is best) than having
>> seemingly infinite memory that crashes and burns.
>>
>> On Wed, Jan 5, 2011 at 7:33 PM, Alan Burlison <>wrote:
>>
>>> On 05/01/2011 18:25, Alexander Brevig wrote:
>>>
>>> Slightly unrelated to what you guys are discussing now but:
>>>> I'm not sure if I've made this clear, but the new version of String that
>>>> I'm
>>>> working on now does not use malloc or any other c function for dynamic
>>>> memory. What happens is that I allocate memory statically on the stack
>>>> and
>>>> serve that memory dynamically to the instances of String.
>>>>
>>>
>>> Does that mean that the total space occupied by all Strings has to be
>>> decided up front? If so, what is the behaviour when an allocation fails?
>>>
>>> To be honest I don't really see the point of doing this - all you are
>>> doing is re-implementing malloc.
>>>
>>> --
>>> Alan Burlison
>>> --
>>>
>>
>>
> > The other issue is that of object lifetimes. The test code has
> instances of String objects which are allocated on the stack and that
> are still in scope when the 'leak' memory check is performed.

That was also in my (off list) email a few days ago, though that bit
didn't make it here.

I believe the plan is to move the tests and object(s) they use to a
function, so the objects will be out of scope when the memory check is made.

There might also another copy of the test which pre-allocates a string
large enough to hold all the data. I'm not sure exactly how I feel
about that approach, but it seems like at least worth trying. Currently
the string library does not have a reserve() function. I've proposed it
before, and today I put it in issue #449.

> If a library routine used malloc to perform a one-time library-private
> buffer allocation where the buffer is retained for the lifetime of the
> program, the current leak checking would incorrectly report that as a
> leak. It isn't a leak because there's still a reference to the block
> inside the library.

Yes, you are correct, the test makes some assumptions about the internal
implementation, and yes, an ideal test wouldn't make any such
assumptions, and yes, it's probably impractical to completely avoid
assumptions on such limited hardware.

But there's a lot of value in actually testing on the real hardware,
with all its limitations and slight differences from running on a PC.
Personally, I think making some assumptions is a pretty good trade-off
for testing in the actual environment. Of course, there's plenty of
room for smart ideas to minimize such assumptions, or perhaps test in
multiple ways.

As someone who's spent a lot of time coding on the string class (and has
more planned), the real value isn't a perfect score if my code is bug
free, but rather a FAIL coming up when I make some mistake that
unexpectedly breaks something. Sure it's annoying if a FAIL comes up
erroneously because the internal implementation changed,

There are so many functions, with so many cases, that subtle errors can
happen (eg, does lastIndexOf work when the search string is the entire
original string... I broke that recently, but everything else worked.....)

If you have ideas about how to catch more types of errors, even if
imperfect, I'd really love to hear.




>
>
> The only semi-reliable way to do what you want is to use an
> instrumented malloc implementation, and that's going to be very
> difficult to implement on a constrained platform such as the AVR. If
> you want to test the String implementation for leaks, my advice is to
> do it on a more capable platform (e.g. *nix) and use one of the many
> instrumented mallocs that are available.
>


_______________________________________________
___________________________________________________

Posted on the Developers mailing list. Go to http://arduino.cc/mailman/listinfo/developers_arduino.cc to subscribe.

  #15  
05-01-2011 07:51 PM
Developers member admin is online now
User
 

That breaking of String, does it only occur with the SDM version?

If not, did you find any way to break it? Maybe any of the old faults
related to memory?


I actually have no time to check this myself right now, so I opted to just
ask you.

On Mon, Jan 3, 2011 at 10:35 PM, Tom Igoe <> wrote:

> Thanks, Alexander, and sorry for the delay.
>
> A few tests:
>
> For code that doesn't change the strings much, there's not a big
> difference, a couple dozen bytes' difference in code size. However, when
> you start to do dynamic things, it does add up. For example, the
> StringAppendOperator example is 4910 bytes in 0022, and 5148 bytes with the
> StaticDynamicMemory version. So it does start to take its toll, memory-wise.
>
> On some sketches it actually takes less memory. For example, the one below
> is 3738 bytes using the StaticDynamicMemory version, and 3986 bytes in 0022.
> However, it fails entirely on upload. When the value of (analog 0)/4 is
> high (0xFF), it never gets out of the setup(). So there's still a pretty
> easy way to break String, even with these improvements.
>
>
> void setup() {
> Serial.begin(9600);
> Serial.println("Beginning");
> }
>
> void loop() {
>
> String webColor = "#";
>
> int red = analogRead(A0)/4;
> webColor += String(red, HEX);
> int green = analogRead(A1)/4;
> webColor += String(green, HEX);
> int blue = analogRead(A2)/4;
>
> webColor += String(blue, HEX);
> Serial.println(webColor);
> }
>
>
>
>
>
> On Dec 16, 2010, at 1:27 AM, Alexander Brevig wrote:
>
> > Attached is a zip containing WString.h and .cpp plus
> StaticDynamicMemory.h.
> > Take a backup of the original WString files, and extract this zip into
> the hardware/arduino/cores/arduino folder.
> >
> > Now you're ready to test the modified String library, that does not
> fragment the heap.
> >
> >
> > In the WString header there is a #define called STRING_BUFFER which is
> set to 100 for now, change this to suit your test needs.
> >
> >
> > No error handling is implemented, what do you think we need?
> >
> > I plan to add an availableMemory():int method to the SDM library, and
> maybe some error flags and checks like hasError():int error
> >
> > I also suspect that this library is a bit slower performance wise, but I
> think that's just a cost we'll have to pay to being able to play with
> dynamic strings.
> >
> >
> > Hope to get feedback from someone!
> >
> > On Thu, Dec 16, 2010 at 1:11 AM, Alan Burlison <>
> wrote:
> > On 15/12/2010 16:19, David A. Mellis wrote:
> >
> > I think you're right, but I also don't think that telling people to
> > use the standard C library functions is a solution either. Trying out
> > this String class seems like one way of pushing forwards towards a
> > compromise that provides both an easy-to-use API and a robust
> > implementation. For example, perhaps the buffer sizes need to be
> > specified or provided when the String is instantiated. Or we need an
> > alternative implementation that does more reliable memory allocation
> > (since we're not assuming that the internal buffer is continuous).
> > Other ideas welcome.
> >
> > I think the problem is that the failure modes are not benign. I haven't
> been through all the use cases so this might not work, but perhaps using a
> statically-allocated string ("NOMEM" ?) as a sentinel value instead of null
> when malloc fails might be one way? Also, there might be some benefit in
> making String immutable a la Java - overloaded operators in C++ have a
> tendency to generate anonymous temporaries, which is going to lead to heap
> fragmentation as well.
> >
> > --
> > Alan Burlison
> > --
> >
> > _______________________________________________
___________________________________________________

Posted on the Developers mailing list. Go to http://arduino.cc/mailman/listinfo/developers_arduino.cc to subscribe. It broke in the non-SDM version too, but it took longer to break. In the SDM version it breaks immediately. So it looks like whatever you did highlights the faults sooner, which is good. It also points to a need for an error response of some sort, in answer to your question last mail.

t.

On Jan 3, 2011, at 4:44 PM, Alexander Brevig wrote:

> That breaking of String, does it only occur with the SDM version?
>
> If not, did you find any way to break it? Maybe any of the old faults related to memory?
>
>
> I actually have no time to check this myself right now, so I opted to just ask you.
>
> On Mon, Jan 3, 2011 at 10:35 PM, Tom Igoe <> wrote:
> Thanks, Alexander, and sorry for the delay.
>
> A few tests:
>
> For code that doesn't change the strings much, there's not a big difference, a couple dozen bytes' difference in code size. However, when you start to do dynamic things, it does add up. For example, the StringAppendOperator example is 4910 bytes in 0022, and 5148 bytes with the StaticDynamicMemory version. So it does start to take its toll, memory-wise.
>
> On some sketches it actually takes less memory. For example, the one below is 3738 bytes using the StaticDynamicMemory version, and 3986 bytes in 0022. However, it fails entirely on upload. When the value of (analog 0)/4 is high (0xFF), it never gets out of the setup(). So there's still a pretty easy way to break String, even with these improvements.
>
>
> void setup() {
> Serial.begin(9600);
> Serial.println("Beginning");
> }
>
> void loop() {
>
> String webColor = "#";
>
> int red = analogRead(A0)/4;
> webColor += String(red, HEX);
> int green = analogRead(A1)/4;
> webColor += String(green, HEX);
> int blue = analogRead(A2)/4;
>
> webColor += String(blue, HEX);
> Serial.println(webColor);
> }
>
>
>
>
>
> On Dec 16, 2010, at 1:27 AM, Alexander Brevig wrote:
>
> > Attached is a zip containing WString.h and .cpp plus StaticDynamicMemory.h.
> > Take a backup of the original WString files, and extract this zip into the hardware/arduino/cores/arduino folder.
> >
> > Now you're ready to test the modified String library, that does not fragment the heap.
> >
> >
> > In the WString header there is a #define called STRING_BUFFER which is set to 100 for now, change this to suit your test needs.
> >
> >
> > No error handling is implemented, what do you think we need?
> >
> > I plan to add an availableMemory():int method to the SDM library, and maybe some error flags and checks like hasError():int error
> >
> > I also suspect that this library is a bit slower performance wise, but I think that's just a cost we'll have to pay to being able to play with dynamic strings.
> >
> >
> > Hope to get feedback from someone!
> >
> > On Thu, Dec 16, 2010 at 1:11 AM, Alan Burlison <> wrote:
> > On 15/12/2010 16:19, David A. Mellis wrote:
> >
> > I think you're right, but I also don't think that telling people to
> > use the standard C library functions is a solution either. Trying out
> > this String class seems like one way of pushing forwards towards a
> > compromise that provides both an easy-to-use API and a robust
> > implementation. For example, perhaps the buffer sizes need to be
> > specified or provided when the String is instantiated. Or we need an
> > alternative implementation that does more reliable memory allocation
> > (since we're not assuming that the internal buffer is continuous).
> > Other ideas welcome.
> >
> > I think the problem is that the failure modes are not benign. I haven't been through all the use cases so this might not work, but perhaps using a statically-allocated string ("NOMEM" ?) as a sentinel value instead of null when malloc fails might be one way? Also, there might be some benefit in making String immutable a la Java - overloaded operators in C++ have a tendency to generate anonymous temporaries, which is going to lead to heap fragmentation as well.
> >
> > --
> > Alan Burlison
> > --
> >
> > _______________________________________________
___________________________________________________

Posted on the Developers mailing list. Go to http://arduino.cc/mailman/listinfo/developers_arduino.cc to subscribe. There seems to be a bug with the assignment operator, I'm on it and I'll get
back to you as soon as I get something done.

Thank you for your tests and feedback.


I'll do some tests on my own before I repost it here.

On Tue, Jan 4, 2011 at 6:53 PM, Rick Anderson
<>wrote:

> I just created a test and unpacked and tested it. I also created a
> test based on Tom's code. Not sure I caught the maximum value error
> for 0xFF.
>
> I also ran the tests for bug 411. All the tests compile, but there is
> still memory loss.
>
> I'm attaching the Arduino Test suite, and the test code so you can run
> them as you debug. Let me know if this was helpful.
>
> --Rick
>
> Test run results:
> Example: ATS_StringAssignmentTest.pde
> info.MANUFACTURER = Arduino
> info.CPU-NAME = ATmega328P
> info.GCC-Version = 4.3.2
> info.AVR-LibC-Ver = 1.6.4
> info.Compiled-date = Jan 4 2011
> info.Test-Suite-Name = ATS_StringAssignmentTest
> info.Free-memory = 1110 bytes
> Memory Usage (lost 59 bytes) ... FAIL
> --------------------------
> Ran 1 tests in 1.378s
>
> FAILED (failures=1)
>
>
> Example: ATS_StringMemoryTestPassByReference.pde
>
> info.MANUFACTURER = Arduino
> info.CPU-NAME = ATmega328P
> info.GCC-Version = 4.3.2
> info.AVR-LibC-Ver = 1.6.4
> info.Compiled-date = Jan 4 2011
> info.Test-Suite-Name = ATS_StringMemoryTestPassByReference
> info.Free-memory = 1120 bytes
> Memory Usage (lost 59 bytes) ... FAIL
> --------------------------
> Ran 1 tests in 1.389s
>
> FAILED (failures=1)
>
>
> Example: Tom Igoe Memory Test
> info.MANUFACTURER = Arduino
> info.CPU-NAME = ATmega328P
> info.GCC-Version = 4.3.2
> info.AVR-LibC-Ver = 1.6.4
> info.Compiled-date = Jan 4 2011
> info.Test-Suite-Name = Tom Igoe Memory Test
> info.Free-memory = 1328 bytes
> Memory Usage (lost 9 bytes) ... FAIL
> --------------------------
> Ran 1 tests in 1.374s
>
> FAILED (failures=1)
>
>
>
> --Rick
>
> Tom, rewrote your example as a test.
>
> //************************************************************************
> //* Arduino Tom Igoe Memory Test
> //* (C) 2010 by Rick Anderson
> //* Open source as per standard Arduino code
> //*
> //************************************************************************
> //* Jan 4, 2011 Started on Tom Igoe Memory Test
> //************************************************************************
>
> #include "WProgram.h"
> #include "HardwareSerial.h"
> #include
>
> //************************************************************************
> void setup()
> {
> int startMemoryUsage;
> /*
> * Create variable for the tests.
> */
>
> String webColor = "#000000";
>
> int red = 1023/4;
> int blue = 512/4;
> int green = 128/4;
>
> /*
> * initiate the test run
> */
> //Record starting memory amount
> startMemoryUsage = ATS_GetFreeMemory();
> //Begin test run
> ATS_begin("Arduino", "Tom Igoe Memory Test");
>
> webColor = "#";
> webColor += String(red, HEX);
> webColor += String(green, HEX);
> webColor += String(blue, HEX);
>
> ATS_ReportMemoryUsage(startMemoryUsage);
>
> /*
> * Test complete
> */
>
> ATS_end();
> }
>
>
> //************************************************************************
> void loop()
> {
>
>
> }
>
>
>
>
> On Mon, Jan 3, 2011 at 9:35 PM, Tom Igoe <> wrote:
> > It broke in the non-SDM version too, but it took longer to break. In the
> SDM version it breaks immediately. So it looks like whatever you did
> highlights the faults sooner, which is good. It also points to a need for an
> error response of some sort, in answer to your question last mail.
> >
> > t.
> >
> > On Jan 3, 2011, at 4:44 PM, Alexander Brevig wrote:
> >
> >> That breaking of String, does it only occur with the SDM version?
> >>
> >> If not, did you find any way to break it? Maybe any of the old faults
> related to memory?
> >>
> >>
> >> I actually have no time to check this myself right now, so I opted to
> just ask you.
> >>
> >> On Mon, Jan 3, 2011 at 10:35 PM, Tom Igoe <> wrote:
> >> Thanks, Alexander, and sorry for the delay.
> >>
> >> A few tests:
> >>
> >> For code that doesn't change the strings much, there's not a big
> difference, a couple dozen bytes' difference in code size. However, when
> you start to do dynamic things, it does add up. For example, the
> StringAppendOperator example is 4910 bytes in 0022, and 5148 bytes with the
> StaticDynamicMemory version. So it does start to take its toll, memory-wise.
> >>
> >> On some sketches it actually takes less memory. For example, the one
> below is 3738 bytes using the StaticDynamicMemory version, and 3986 bytes in
> 0022. However, it fails entirely on upload. When the value of (analog 0)/4
> is high (0xFF), it never gets out of the setup(). So there's still a pretty
> easy way to break String, even with these improvements.
> >>
> >>
> >> void setup() {
> >> Serial.begin(9600);
> >> Serial.println("Beginning");
> >> }
> >>
> >> void loop() {
> >>
> >> String webColor = "#";
> >>
> >> int red = analogRead(A0)/4;
> >> webColor += String(red, HEX);
> >> int green = analogRead(A1)/4;
> >> webColor += String(green, HEX);
> >> int blue = analogRead(A2)/4;
> >>
> >> webColor += String(blue, HEX);
> >> Serial.println(webColor);
> >> }
> >>
> >>
> >>
> >>
> >>
> >> On Dec 16, 2010, at 1:27 AM, Alexander Brevig wrote:
> >>
> >> > Attached is a zip containing WString.h and .cpp plus
> StaticDynamicMemory.h.
> >> > Take a backup of the original WString files, and extract this zip into
> the hardware/arduino/cores/arduino folder.
> >> >
> >> > Now you're ready to test the modified String library, that does not
> fragment the heap.
> >> >
> >> >
> >> > In the WString header there is a #define called STRING_BUFFER which is
> set to 100 for now, change this to suit your test needs.
> >> >
> >> >
> >> > No error handling is implemented, what do you think we need?
> >> >
> >> > I plan to add an availableMemory():int method to the SDM library, and
> maybe some error flags and checks like hasError():int error
> >> >
> >> > I also suspect that this library is a bit slower performance wise, but
> I think that's just a cost we'll have to pay to being able to play with
> dynamic strings.
> >> >
> >> >
> >> > Hope to get feedback from someone!
> >> >
> >> > On Thu, Dec 16, 2010 at 1:11 AM, Alan Burlison <
> > wrote:
> >> > On 15/12/2010 16:19, David A. Mellis wrote:
> >> >
> >> > I think you're right, but I also don't think that telling people to
> >> > use the standard C library functions is a solution either. Trying out
> >> > this String class seems like one way of pushing forwards towards a
> >> > compromise that provides both an easy-to-use API and a robust
> >> > implementation. For example, perhaps the buffer sizes need to be
> >> > specified or provided when the String is instantiated. Or we need an
> >> > alternative implementation that does more reliable memory allocation
> >> > (since we're not assuming that the internal buffer is continuous).
> >> > Other ideas welcome.
> >> >
> >> > I think the problem is that the failure modes are not benign. I
> haven't been through all the use cases so this might not work, but perhaps
> using a statically-allocated string ("NOMEM" ?) as a sentinel value instead
> of null when malloc fails might be one way? Also, there might be some
> benefit in making String immutable a la Java - overloaded operators in C++
> have a tendency to generate anonymous temporaries, which is going to lead to
> heap fragmentation as well.
> >> >
> >> > --
> >> > Alan Burlison
> >> > --
> >> >
> >> > _______________________________________________
___________________________________________________

Posted on the Developers mailing list. Go to http://arduino.cc/mailman/listinfo/developers_arduino.cc to subscribe. Is this test suite any different than the one in the github repo?

t.

On Jan 4, 2011, at 12:53 PM, Rick Anderson wrote:

> I just created a test and unpacked and tested it. I also created a
> test based on Tom's code. Not sure I caught the maximum value error
> for 0xFF.
>
> I also ran the tests for bug 411. All the tests compile, but there is
> still memory loss.
>
> I'm attaching the Arduino Test suite, and the test code so you can run
> them as you debug. Let me know if this was helpful.
>
> --Rick
>
> Test run results:
> Example: ATS_StringAssignmentTest.pde
> info.MANUFACTURER = Arduino
> info.CPU-NAME = ATmega328P
> info.GCC-Version = 4.3.2
> info.AVR-LibC-Ver = 1.6.4
> info.Compiled-date = Jan 4 2011
> info.Test-Suite-Name = ATS_StringAssignmentTest
> info.Free-memory = 1110 bytes
> Memory Usage (lost 59 bytes) ... FAIL
> --------------------------
> Ran 1 tests in 1.378s
>
> FAILED (failures=1)
>
>
> Example: ATS_StringMemoryTestPassByReference.pde
>
> info.MANUFACTURER = Arduino
> info.CPU-NAME = ATmega328P
> info.GCC-Version = 4.3.2
> info.AVR-LibC-Ver = 1.6.4
> info.Compiled-date = Jan 4 2011
> info.Test-Suite-Name = ATS_StringMemoryTestPassByReference
> info.Free-memory = 1120 bytes
> Memory Usage (lost 59 bytes) ... FAIL
> --------------------------
> Ran 1 tests in 1.389s
>
> FAILED (failures=1)
>
>
> Example: Tom Igoe Memory Test
> info.MANUFACTURER = Arduino
> info.CPU-NAME = ATmega328P
> info.GCC-Version = 4.3.2
> info.AVR-LibC-Ver = 1.6.4
> info.Compiled-date = Jan 4 2011
> info.Test-Suite-Name = Tom Igoe Memory Test
> info.Free-memory = 1328 bytes
> Memory Usage (lost 9 bytes) ... FAIL
> --------------------------
> Ran 1 tests in 1.374s
>
> FAILED (failures=1)
>
>
>
> --Rick
>
> Tom, rewrote your example as a test.
>
> //************************************************************************
> //* Arduino Tom Igoe Memory Test
> //* (C) 2010 by Rick Anderson
> //* Open source as per standard Arduino code
> //*
> //************************************************************************
> //* Jan 4, 2011 Started on Tom Igoe Memory Test
> //************************************************************************
>
> #include "WProgram.h"
> #include "HardwareSerial.h"
> #include
>
> //************************************************************************
> void setup()
> {
> int startMemoryUsage;
> /*
> * Create variable for the tests.
> */
>
> String webColor = "#000000";
>
> int red = 1023/4;
> int blue = 512/4;
> int green = 128/4;
>
> /*
> * initiate the test run
> */
> //Record starting memory amount
> startMemoryUsage = ATS_GetFreeMemory();
> //Begin test run
> ATS_begin("Arduino", "Tom Igoe Memory Test");
>
> webColor = "#";
> webColor += String(red, HEX);
> webColor += String(green, HEX);
> webColor += String(blue, HEX);
>
> ATS_ReportMemoryUsage(startMemoryUsage);
>
> /*
> * Test complete
> */
>
> ATS_end();
> }
>
>
> //************************************************************************
> void loop()
> {
>
>
> }
>
>
>
>
> On Mon, Jan 3, 2011 at 9:35 PM, Tom Igoe <> wrote:
>> It broke in the non-SDM version too, but it took longer to break. In the SDM version it breaks immediately. So it looks like whatever you did highlights the faults sooner, which is good. It also points to a need for an error response of some sort, in answer to your question last mail.
>>
>> t.
>>
>> On Jan 3, 2011, at 4:44 PM, Alexander Brevig wrote:
>>
>>> That breaking of String, does it only occur with the SDM version?
>>>
>>> If not, did you find any way to break it? Maybe any of the old faults related to memory?
>>>
>>>
>>> I actually have no time to check this myself right now, so I opted to just ask you.
>>>
>>> On Mon, Jan 3, 2011 at 10:35 PM, Tom Igoe <> wrote:
>>> Thanks, Alexander, and sorry for the delay.
>>>
>>> A few tests:
>>>
>>> For code that doesn't change the strings much, there's not a big difference, a couple dozen bytes' difference in code size. However, when you start to do dynamic things, it does add up. For example, the StringAppendOperator example is 4910 bytes in 0022, and 5148 bytes with the StaticDynamicMemory version. So it does start to take its toll, memory-wise.
>>>
>>> On some sketches it actually takes less memory. For example, the one below is 3738 bytes using the StaticDynamicMemory version, and 3986 bytes in 0022. However, it fails entirely on upload. When the value of (analog 0)/4 is high (0xFF), it never gets out of the setup(). So there's still a pretty easy way to break String, even with these improvements.
>>>
>>>
>>> void setup() {
>>> Serial.begin(9600);
>>> Serial.println("Beginning");
>>> }
>>>
>>> void loop() {
>>>
>>> String webColor = "#";
>>>
>>> int red = analogRead(A0)/4;
>>> webColor += String(red, HEX);
>>> int green = analogRead(A1)/4;
>>> webColor += String(green, HEX);
>>> int blue = analogRead(A2)/4;
>>>
>>> webColor += String(blue, HEX);
>>> Serial.println(webColor);
>>> }
>>>
>>>
>>>
>>>
>>>
>>> On Dec 16, 2010, at 1:27 AM, Alexander Brevig wrote:
>>>
>>>> Attached is a zip containing WString.h and .cpp plus StaticDynamicMemory.h.
>>>> Take a backup of the original WString files, and extract this zip into the hardware/arduino/cores/arduino folder.
>>>>
>>>> Now you're ready to test the modified String library, that does not fragment the heap.
>>>>
>>>>
>>>> In the WString header there is a #define called STRING_BUFFER which is set to 100 for now, change this to suit your test needs.
>>>>
>>>>
>>>> No error handling is implemented, what do you think we need?
>>>>
>>>> I plan to add an availableMemory():int method to the SDM library, and maybe some error flags and checks like hasError():int error
>>>>
>>>> I also suspect that this library is a bit slower performance wise, but I think that's just a cost we'll have to pay to being able to play with dynamic strings.
>>>>
>>>>
>>>> Hope to get feedback from someone!
>>>>
>>>> On Thu, Dec 16, 2010 at 1:11 AM, Alan Burlison <> wrote:
>>>> On 15/12/2010 16:19, David A. Mellis wrote:
>>>>
>>>> I think you're right, but I also don't think that telling people to
>>>> use the standard C library functions is a solution either. Trying out
>>>> this String class seems like one way of pushing forwards towards a
>>>> compromise that provides both an easy-to-use API and a robust
>>>> implementation. For example, perhaps the buffer sizes need to be
>>>> specified or provided when the String is instantiated. Or we need an
>>>> alternative implementation that does more reliable memory allocation
>>>> (since we're not assuming that the internal buffer is continuous).
>>>> Other ideas welcome.
>>>>
>>>> I think the problem is that the failure modes are not benign. I haven't been through all the use cases so this might not work, but perhaps using a statically-allocated string ("NOMEM" ?) as a sentinel value instead of null when malloc fails might be one way? Also, there might be some benefit in making String immutable a la Java - overloaded operators in C++ have a tendency to generate anonymous temporaries, which is going to lead to heap fragmentation as well.
>>>>
>>>> --
>>>> Alan Burlison
>>>> --
>>>>
>>>> _______________________________________________
___________________________________________________

Posted on the Developers mailing list. Go to http://arduino.cc/mailman/listinfo/developers_arduino.cc to subscribe. Same exact one. I just included it just in case.

--Rick

On Tue, Jan 4, 2011 at 9:01 PM, Tom Igoe <> wrote:
> Is this test suite any different than the one in the github repo?
>
> t.
>
> On Jan 4, 2011, at 12:53 PM, Rick Anderson wrote:
>
>> I just created a test and unpacked and tested it. I also created a
>> test based on Tom's code. Not sure I caught the maximum value error
>> for 0xFF.
>>
>> I also ran the tests for bug 411. All the tests compile, but there is
>> still memory loss.
>>
>> I'm attaching the Arduino Test suite, and the test code so you can run
>> them as you debug. Let me know if this was helpful.
>>
>> --Rick
>>
>> Test run results:
>> Example:  ATS_StringAssignmentTest.pde
>> info.MANUFACTURER    = Arduino
>> info.CPU-NAME        = ATmega328P
>> info.GCC-Version     = 4.3.2
>> info.AVR-LibC-Ver    = 1.6.4
>> info.Compiled-date   = Jan  4 2011
>> info.Test-Suite-Name = ATS_StringAssignmentTest
>> info.Free-memory     = 1110 bytes
>> Memory Usage (lost 59 bytes)                                ... FAIL
>> --------------------------
>> Ran 1 tests in 1.378s
>>
>> FAILED (failures=1)
>>
>>
>> Example: ATS_StringMemoryTestPassByReference.pde
>>
>> info.MANUFACTURER    = Arduino
>> info.CPU-NAME        = ATmega328P
>> info.GCC-Version     = 4.3.2
>> info.AVR-LibC-Ver    = 1.6.4
>> info.Compiled-date   = Jan  4 2011
>> info.Test-Suite-Name = ATS_StringMemoryTestPassByReference
>> info.Free-memory     = 1120 bytes
>> Memory Usage (lost 59 bytes)                                ... FAIL
>> --------------------------
>> Ran 1 tests in 1.389s
>>
>> FAILED (failures=1)
>>
>>
>> Example: Tom Igoe Memory Test
>> info.MANUFACTURER    = Arduino
>> info.CPU-NAME        = ATmega328P
>> info.GCC-Version     = 4.3.2
>> info.AVR-LibC-Ver    = 1.6.4
>> info.Compiled-date   = Jan  4 2011
>> info.Test-Suite-Name = Tom Igoe Memory Test
>> info.Free-memory     = 1328 bytes
>> Memory Usage (lost 9 bytes)                                 ... FAIL
>> --------------------------
>> Ran 1 tests in 1.374s
>>
>> FAILED (failures=1)
>>
>>
>>
>> --Rick
>>
>> Tom, rewrote your example as a test.
>>
>> //************************************************************************
>> //*   Arduino Tom Igoe Memory Test
>> //*           (C) 2010 by Rick Anderson
>> //*           Open source as per standard Arduino code
>> //*
>> //************************************************************************
>> //*   Jan 4,  2011     Started on Tom Igoe Memory Test
>> //************************************************************************
>>
>> #include      "WProgram.h"
>> #include      "HardwareSerial.h"
>> #include      
>>
>> //************************************************************************
>> void setup()
>> {
>>  int          startMemoryUsage;
>>  /*
>>    * Create variable for the tests.
>>   */
>>
>>  String webColor = "#000000";
>>
>>  int red = 1023/4;
>>  int blue = 512/4;
>>  int green = 128/4;
>>
>>  /*
>>  * initiate the test run
>>   */
>>  //Record starting memory amount
>>  startMemoryUsage     =       ATS_GetFreeMemory();
>>  //Begin test run
>>  ATS_begin("Arduino", "Tom Igoe Memory Test");
>>
>>  webColor = "#";
>>  webColor += String(red, HEX);
>>  webColor += String(green, HEX);
>>  webColor += String(blue, HEX);
>>
>>  ATS_ReportMemoryUsage(startMemoryUsage);
>>
>>  /*
>>   * Test complete
>>   */
>>
>>  ATS_end();
>> }
>>
>>
>> //************************************************************************
>> void loop()
>> {
>>
>>
>> }
>>
>>
>>
>>
>> On Mon, Jan 3, 2011 at 9:35 PM, Tom Igoe <> wrote:
>>> It broke in the non-SDM version too, but it took longer to break. In the SDM version it breaks immediately. So it looks like whatever you did highlights the faults sooner, which is good. It also points to a need for an error response of some sort, in answer to your question last mail.
>>>
>>> t.
>>>
>>> On Jan 3, 2011, at 4:44 PM, Alexander Brevig wrote:
>>>
>>>> That breaking of String, does it only occur with the SDM version?
>>>>
>>>> If not, did you find any way to break it? Maybe any of the old faults related to memory?
>>>>
>>>>
>>>> I actually have no time to check this myself right now, so I opted to just ask you.
>>>>
>>>> On Mon, Jan 3, 2011 at 10:35 PM, Tom Igoe <> wrote:
>>>> Thanks, Alexander, and sorry for the delay.
>>>>
>>>> A few tests:
>>>>
>>>> For code that doesn't change the strings much, there's not a big difference, a couple dozen bytes' difference in code size.  However, when you start to do dynamic things, it does add up.  For example, the StringAppendOperator example is  4910 bytes in 0022, and 5148 bytes with the StaticDynamicMemory version. So it does start to take its toll, memory-wise.
>>>>
>>>> On some sketches it actually takes less memory.  For example, the one below is 3738 bytes using the StaticDynamicMemory version, and 3986 bytes in 0022.  However, it fails entirely on upload.  When the value of (analog 0)/4 is high (0xFF), it never gets out of the setup(). So there's still a pretty easy way to break String, even with these improvements.
>>>>
>>>>
>>>> void setup() {
>>>>  Serial.begin(9600);
>>>>  Serial.println("Beginning");
>>>> }
>>>>
>>>> void loop() {
>>>>
>>>>  String webColor = "#";
>>>>
>>>>  int red = analogRead(A0)/4;
>>>>  webColor += String(red, HEX);
>>>>  int green = analogRead(A1)/4;
>>>>  webColor += String(green, HEX);
>>>>  int blue = analogRead(A2)/4;
>>>>
>>>>  webColor += String(blue, HEX);
>>>>  Serial.println(webColor);
>>>> }
>>>>
>>>>
>>>>
>>>>
>>>>
>>>> On Dec 16, 2010, at 1:27 AM, Alexander Brevig wrote:
>>>>
>>>>> Attached is a zip containing WString.h and .cpp plus StaticDynamicMemory.h.
>>>>> Take a backup of the original WString files, and extract this zip into the hardware/arduino/cores/arduino folder.
>>>>>
>>>>> Now you're ready to test the modified String library, that does not fragment the heap.
>>>>>
>>>>>
>>>>> In the WString header there is a #define called STRING_BUFFER which is set to 100 for now, change this to suit your test needs.
>>>>>
>>>>>
>>>>> No error handling is implemented, what do you think we need?
>>>>>
>>>>> I plan to add an availableMemory():int method to the SDM library, and maybe some error flags and checks like hasError():int error
>>>>>
>>>>> I also suspect that this library is a bit slower performance wise, but I think that's just a cost we'll have to pay to being able to play with dynamic strings.
>>>>>
>>>>>
>>>>> Hope to  get feedback from someone!
>>>>>
>>>>> On Thu, Dec 16, 2010 at 1:11 AM, Alan Burlison <> wrote:
>>>>> On 15/12/2010 16:19, David A. Mellis wrote:
>>>>>
>>>>> I think you're right, but I also don't think that telling people to
>>>>> use the standard C library functions is a solution either.  Trying out
>>>>> this String class seems like one way of pushing forwards towards a
>>>>> compromise that provides both an easy-to-use API and a robust
>>>>> implementation.  For example, perhaps the buffer sizes need to be
>>>>> specified or provided when the String is instantiated.  Or we need an
>>>>> alternative implementation that does more reliable memory allocation
>>>>> (since we're not assuming that the internal buffer is continuous).
>>>>> Other ideas welcome.
>>>>>
>>>>> I think the problem is that the failure modes are not benign.  I haven't been through all the use cases so this might not work, but perhaps using a statically-allocated string ("NOMEM" ?) as a sentinel value instead of null when malloc fails might be one way?  Also, there might be some benefit in making String immutable a la Java - overloaded operators in C++ have a tendency to generate anonymous temporaries, which is going to lead to heap fragmentation as well.
>>>>>
>>>>> --
>>>>> Alan Burlison
>>>>> --
>>>>>
>>>>> _______________________________________________
___________________________________________________

Posted on the Developers mailing list. Go to http://arduino.cc/mailman/listinfo/developers_arduino.cc to subscribe. On 04/01/2011 17:53, Rick Anderson wrote:

> I also ran the tests for bug 411. All the tests compile, but there is
> still memory loss.

Most of the assumptions made by the test harness and test case code are
wrong, any reports of 'lost' memory are therefore likely to be wrong as
well. If you want to do leak detection you can't do it in the naive way
it is being done at present.

--
Alan Burlison
--

_______________________________________________
___________________________________________________

Posted on the Developers mailing list. Go to http://arduino.cc/mailman/listinfo/developers_arduino.cc to subscribe. Alan,

The tests themselves are quick and dirty, and not strategic or
comprehensive. I'd like your input to create a good procedure for
memory testing. I also have feedback from Paul Stoffregen for the test
suite:
----
Another problem involves gcc's optimizer ignoring the inline request
for ATS_ReportMemoryUsage. As the comment in the code explains, it
must be inline to avoid measuring its own stack frame. I believe
adding this line in ArduinoTestSuite.h fixes the problem by forcing
gcc to inline.

inline void ATS_ReportMemoryUsage(int _memoryUsageAtStart)
__attribute__((always_inline, unused));

The last problem is a tiny bit of dynamic memory permanently held for
the free list. To allow for this, the test really should call
malloc() and free() once, so the allocator is fully initialized before
testing.
----

I'd like to combine both sets of feedback, and set up some issues in
the system, then fix them. Is the above the problem you saw? Are their
other assumptions that would impact measuring memory? And updating the
memory test in the the test suite.

In terms of creating tests for memory leaks. It looks best to move all
the memory usage inside a function. What else could be done to
constrain the problem, and measuring more affectively.

I'm traveling back to NJ today, so I can't respond right away.

--Rick

On Wed, Jan 5, 2011 at 8:52 AM, Alan Burlison <> wrote:
> On 04/01/2011 17:53, Rick Anderson wrote:
>
>> I also ran the tests for bug 411. All the tests compile, but there is
>> still memory loss.
>
> Most of the assumptions made by the test harness and test case code are
> wrong, any reports of 'lost' memory are therefore likely to be wrong as
> well.  If you want to do leak detection you can't do it in the naive way it
> is being done at present.
>
> --
> Alan Burlison
> --
>



--
President
Fair Use Building and Research (****) Labs
http://fubarlabs.org

_______________________________________________
___________________________________________________

Posted on the Developers mailing list. Go to http://arduino.cc/mailman/listinfo/developers_arduino.cc to subscribe. On 05/01/2011 15:19, Rick Anderson wrote:

> ----
> Another problem involves gcc's optimizer ignoring the inline request
> for ATS_ReportMemoryUsage. As the comment in the code explains, it
> must be inline to avoid measuring its own stack frame. I believe
> adding this line in ArduinoTestSuite.h fixes the problem by forcing
> gcc to inline.
>
> inline void ATS_ReportMemoryUsage(int _memoryUsageAtStart)
> __attribute__((always_inline, unused));

Yes, that's one of the problems. And even the __attribute__
'workaround' is a fragile hack.

> The last problem is a tiny bit of dynamic memory permanently held for
> the free list. To allow for this, the test really should call
> malloc() and free() once, so the allocator is fully initialized before

That's part of a problem, but an initial call malloc/free call isn't
guaranteed to make all the issues go away either. From looking at the
avr-libc malloc implementation it does try to coalesce the heap, but
relying on multiple malloc implementation artefacts is a really bad idea
- there's no guarantee that future malloc implementations will always
coalesce on every free, and there's no guarantee that __bss_end or
__brkval will always be adjusted on each malloc/free call.

The other issue is that of object lifetimes. The test code has
instances of String objects which are allocated on the stack and that
are still in scope when the 'leak' memory check is performed. That
means the String destructors won't have been called and the dynamically
allocated part of the String will still be allocated.

A true memory leak is a block of allocated memory that has no references
to it. However that's not what the test code is checking for. If a
library routine used malloc to perform a one-time library-private buffer
allocation where the buffer is retained for the lifetime of the program,
the current leak checking would incorrectly report that as a leak. It
isn't a leak because there's still a reference to the block inside the
library.

The only semi-reliable way to do what you want is to use an instrumented
malloc implementation, and that's going to be very difficult to
implement on a constrained platform such as the AVR. If you want to
test the String implementation for leaks, my advice is to do it on a
more capable platform (e.g. *nix) and use one of the many instrumented
mallocs that are available.

--
Alan Burlison
--

_______________________________________________
___________________________________________________

Posted on the Developers mailing list. Go to http://arduino.cc/mailman/listinfo/developers_arduino.cc to subscribe. Slightly unrelated to what you guys are discussing now but:
I'm not sure if I've made this clear, but the new version of String that I'm
working on now does not use malloc or any other c function for dynamic
memory. What happens is that I allocate memory statically on the stack and
serve that memory dynamically to the instances of String.

I have some time on my hands now and have a look at getting the += not to
break the code

On Wed, Jan 5, 2011 at 7:10 PM, Alan Burlison <>wrote:

> On 05/01/2011 15:19, Rick Anderson wrote:
>
> ----
>> Another problem involves gcc's optimizer ignoring the inline request
>> for ATS_ReportMemoryUsage. As the comment in the code explains, it
>> must be inline to avoid measuring its own stack frame. I believe
>> adding this line in ArduinoTestSuite.h fixes the problem by forcing
>> gcc to inline.
>>
>> inline void ATS_ReportMemoryUsage(int _memoryUsageAtStart)
>> __attribute__((always_inline, unused));
>>
>
> Yes, that's one of the problems. And even the __attribute__ 'workaround'
> is a fragile hack.
>
>
> The last problem is a tiny bit of dynamic memory permanently held for
>> the free list. To allow for this, the test really should call
>> malloc() and free() once, so the allocator is fully initialized before
>>
>
> That's part of a problem, but an initial call malloc/free call isn't
> guaranteed to make all the issues go away either. From looking at the
> avr-libc malloc implementation it does try to coalesce the heap, but relying
> on multiple malloc implementation artefacts is a really bad idea - there's
> no guarantee that future malloc implementations will always coalesce on
> every free, and there's no guarantee that __bss_end or __brkval will always
> be adjusted on each malloc/free call.
>
> The other issue is that of object lifetimes. The test code has instances
> of String objects which are allocated on the stack and that are still in
> scope when the 'leak' memory check is performed. That means the String
> destructors won't have been called and the dynamically allocated part of the
> String will still be allocated.
>
> A true memory leak is a block of allocated memory that has no references to
> it. However that's not what the test code is checking for. If a library
> routine used malloc to perform a one-time library-private buffer allocation
> where the buffer is retained for the lifetime of the program, the current
> leak checking would incorrectly report that as a leak. It isn't a leak
> because there's still a reference to the block inside the library.
>
> The only semi-reliable way to do what you want is to use an instrumented
> malloc implementation, and that's going to be very difficult to implement on
> a constrained platform such as the AVR. If you want to test the String
> implementation for leaks, my advice is to do it on a more capable platform
> (e.g. *nix) and use one of the many instrumented mallocs that are available.
>
> --
> Alan Burlison
> --
>
>
> _______________________________________________
___________________________________________________

Posted on the Developers mailing list. Go to http://arduino.cc/mailman/listinfo/developers_arduino.cc to subscribe. On 05/01/2011 18:25, Alexander Brevig wrote:

> Slightly unrelated to what you guys are discussing now but:
> I'm not sure if I've made this clear, but the new version of String that I'm
> working on now does not use malloc or any other c function for dynamic
> memory. What happens is that I allocate memory statically on the stack and
> serve that memory dynamically to the instances of String.

Does that mean that the total space occupied by all Strings has to be
decided up front? If so, what is the behaviour when an allocation fails?

To be honest I don't really see the point of doing this - all you are
doing is re-implementing malloc.

--
Alan Burlison
--

_______________________________________________
___________________________________________________

Posted on the Developers mailing list. Go to http://arduino.cc/mailman/listinfo/developers_arduino.cc to subscribe. No, actually I am not reimplementing malloc, because my algorithm guarantees
no fragmentation and always 100% effective use of the allocated memory.

"Does that mean that the total space occupied by all Strings has to be
decided up front? "
Yes, just like the buffer for the serial ++

I know I would opt to have the restriction for a predetermined allocated
space WITH error reporting (how we do is up to you guys, feed me with ideas
I'll implement whatever we agree is best) than having
seemingly infinite memory that crashes and burns.

On Wed, Jan 5, 2011 at 7:33 PM, Alan Burlison <>wrote:

> On 05/01/2011 18:25, Alexander Brevig wrote:
>
> Slightly unrelated to what you guys are discussing now but:
>> I'm not sure if I've made this clear, but the new version of String that
>> I'm
>> working on now does not use malloc or any other c function for dynamic
>> memory. What happens is that I allocate memory statically on the stack and
>> serve that memory dynamically to the instances of String.
>>
>
> Does that mean that the total space occupied by all Strings has to be
> decided up front? If so, what is the behaviour when an allocation fails?
>
> To be honest I don't really see the point of doing this - all you are doing
> is re-implementing malloc.
>
> --
> Alan Burlison
> --
> Well, that was easy (seemingly, probably just jinxed myself...) but here the
test does no longer break, and the usage of memory never exceeds 11 bytes.

It would be awesome if someone would test it.


Also, please tell me now if this effort will lead to nowhere. Is the cost of
being constrained to a buffer size a deal-breaker?

On Wed, Jan 5, 2011 at 7:42 PM, Alexander Brevig
<>wrote:

> No, actually I am not reimplementing malloc, because my algorithm
> guarantees no fragmentation and always 100% effective use of the allocated
> memory.
>
> "Does that mean that the total space occupied by all Strings has to be
> decided up front? "
> Yes, just like the buffer for the serial ++
>
> I know I would opt to have the restriction for a predetermined allocated
> space WITH error reporting (how we do is up to you guys, feed me with ideas
> I'll implement whatever we agree is best) than having
> seemingly infinite memory that crashes and burns.
>
> On Wed, Jan 5, 2011 at 7:33 PM, Alan Burlison <>wrote:
>
>> On 05/01/2011 18:25, Alexander Brevig wrote:
>>
>> Slightly unrelated to what you guys are discussing now but:
>>> I'm not sure if I've made this clear, but the new version of String that
>>> I'm
>>> working on now does not use malloc or any other c function for dynamic
>>> memory. What happens is that I allocate memory statically on the stack
>>> and
>>> serve that memory dynamically to the instances of String.
>>>
>>
>> Does that mean that the total space occupied by all Strings has to be
>> decided up front? If so, what is the behaviour when an allocation fails?
>>
>> To be honest I don't really see the point of doing this - all you are
>> doing is re-implementing malloc.
>>
>> --
>> Alan Burlison
>> --
>>
>
> So sorry you all! I shipped my test code (for msvc++ compiler) in five
minutes I'll post an arduino compatible version. So sorry for this spam!

On Wed, Jan 5, 2011 at 8:01 PM, Alexander Brevig
<>wrote:

> Well, that was easy (seemingly, probably just jinxed myself...) but here
> the test does no longer break, and the usage of memory never exceeds 11
> bytes.
>
> It would be awesome if someone would test it.
>
>
> Also, please tell me now if this effort will lead to nowhere. Is the cost
> of being constrained to a buffer size a deal-breaker?
>
>
> On Wed, Jan 5, 2011 at 7:42 PM, Alexander Brevig <
> > wrote:
>
>> No, actually I am not reimplementing malloc, because my algorithm
>> guarantees no fragmentation and always 100% effective use of the allocated
>> memory.
>>
>> "Does that mean that the total space occupied by all Strings has to be
>> decided up front? "
>> Yes, just like the buffer for the serial ++
>>
>> I know I would opt to have the restriction for a predetermined allocated
>> space WITH error reporting (how we do is up to you guys, feed me with ideas
>> I'll implement whatever we agree is best) than having
>> seemingly infinite memory that crashes and burns.
>>
>> On Wed, Jan 5, 2011 at 7:33 PM, Alan Burlison <>wrote:
>>
>>> On 05/01/2011 18:25, Alexander Brevig wrote:
>>>
>>> Slightly unrelated to what you guys are discussing now but:
>>>> I'm not sure if I've made this clear, but the new version of String that
>>>> I'm
>>>> working on now does not use malloc or any other c function for dynamic
>>>> memory. What happens is that I allocate memory statically on the stack
>>>> and
>>>> serve that memory dynamically to the instances of String.
>>>>
>>>
>>> Does that mean that the total space occupied by all Strings has to be
>>> decided up front? If so, what is the behaviour when an allocation fails?
>>>
>>> To be honest I don't really see the point of doing this - all you are
>>> doing is re-implementing malloc.
>>>
>>> --
>>> Alan Burlison
>>> --
>>>
>>
>>
> > The other issue is that of object lifetimes. The test code has
> instances of String objects which are allocated on the stack and that
> are still in scope when the 'leak' memory check is performed.

That was also in my (off list) email a few days ago, though that bit
didn't make it here.

I believe the plan is to move the tests and object(s) they use to a
function, so the objects will be out of scope when the memory check is made.

There might also another copy of the test which pre-allocates a string
large enough to hold all the data. I'm not sure exactly how I feel
about that approach, but it seems like at least worth trying. Currently
the string library does not have a reserve() function. I've proposed it
before, and today I put it in issue #449.

> If a library routine used malloc to perform a one-time library-private
> buffer allocation where the buffer is retained for the lifetime of the
> program, the current leak checking would incorrectly report that as a
> leak. It isn't a leak because there's still a reference to the block
> inside the library.

Yes, you are correct, the test makes some assumptions about the internal
implementation, and yes, an ideal test wouldn't make any such
assumptions, and yes, it's probably impractical to completely avoid
assumptions on such limited hardware.

But there's a lot of value in actually testing on the real hardware,
with all its limitations and slight differences from running on a PC.
Personally, I think making some assumptions is a pretty good trade-off
for testing in the actual environment. Of course, there's plenty of
room for smart ideas to minimize such assumptions, or perhaps test in
multiple ways.

As someone who's spent a lot of time coding on the string class (and has
more planned), the real value isn't a perfect score if my code is bug
free, but rather a FAIL coming up when I make some mistake that
unexpectedly breaks something. Sure it's annoying if a FAIL comes up
erroneously because the internal implementation changed,

There are so many functions, with so many cases, that subtle errors can
happen (eg, does lastIndexOf work when the search string is the entire
original string... I broke that recently, but everything else worked.....)

If you have ideas about how to catch more types of errors, even if
imperfect, I'd really love to hear.




>
>
> The only semi-reliable way to do what you want is to use an
> instrumented malloc implementation, and that's going to be very
> difficult to implement on a constrained platform such as the AVR. If
> you want to test the String implementation for leaks, my advice is to
> do it on a more capable platform (e.g. *nix) and use one of the many
> instrumented mallocs that are available.
>


_______________________________________________
___________________________________________________

Posted on the Developers mailing list. Go to http://arduino.cc/mailman/listinfo/developers_arduino.cc to subscribe. I'm not sure I follow, string.read(); what would that do?
How do you imagine String to use Stream ? :)

Attached: new version arduino compitable

On Wed, Jan 5, 2011 at 8:20 PM, Tom Igoe <> wrote:

> Could you then just use Stream as a basis for String? Sorry, I didn't look
> into the details of your DMA class, but as long as we're setting a limit to
> begin with, and if we know Stream's pretty solid, why not restructure String
> a bit to use it?
>
> t.
>
>
> On Jan 5, 2011, at 1:42 PM, Alexander Brevig wrote:
>
> > No, actually I am not reimplementing malloc, because my algorithm
> guarantees no fragmentation and always 100% effective use of the allocated
> memory.
> >
> > "Does that mean that the total space occupied by all Strings has to be
> decided up front? "
> > Yes, just like the buffer for the serial ++
> >
> > I know I would opt to have the restriction for a predetermined allocated
> space WITH error reporting (how we do is up to you guys, feed me with ideas
> I'll implement whatever we agree is best) than having seemingly infinite
> memory that crashes and burns.
> >
> > On Wed, Jan 5, 2011 at 7:33 PM, Alan Burlison <>
> wrote:
> > On 05/01/2011 18:25, Alexander Brevig wrote:
> >
> > Slightly unrelated to what you guys are discussing now but:
> > I'm not sure if I've made this clear, but the new version of String that
> I'm
> > working on now does not use malloc or any other c function for dynamic
> > memory. What happens is that I allocate memory statically on the stack
> and
> > serve that memory dynamically to the instances of String.
> >
> > Does that mean that the total space occupied by all Strings has to be
> decided up front? If so, what is the behaviour when an allocation fails?
> >
> > To be honest I don't really see the point of doing this - all you are
> doing is re-implementing malloc.
> >
> > --
> > Alan Burlison
> > --
> >
> > _______________________________________________
___________________________________________________

Posted on the Developers mailing list. Go to http://arduino.cc/mailman/listinfo/developers_arduino.cc to subscribe.

  #16  
05-01-2011 08:17 PM
Developers member admin is online now
User
 

That breaking of String, does it only occur with the SDM version?

If not, did you find any way to break it? Maybe any of the old faults
related to memory?


I actually have no time to check this myself right now, so I opted to just
ask you.

On Mon, Jan 3, 2011 at 10:35 PM, Tom Igoe <> wrote:

> Thanks, Alexander, and sorry for the delay.
>
> A few tests:
>
> For code that doesn't change the strings much, there's not a big
> difference, a couple dozen bytes' difference in code size. However, when
> you start to do dynamic things, it does add up. For example, the
> StringAppendOperator example is 4910 bytes in 0022, and 5148 bytes with the
> StaticDynamicMemory version. So it does start to take its toll, memory-wise.
>
> On some sketches it actually takes less memory. For example, the one below
> is 3738 bytes using the StaticDynamicMemory version, and 3986 bytes in 0022.
> However, it fails entirely on upload. When the value of (analog 0)/4 is
> high (0xFF), it never gets out of the setup(). So there's still a pretty
> easy way to break String, even with these improvements.
>
>
> void setup() {
> Serial.begin(9600);
> Serial.println("Beginning");
> }
>
> void loop() {
>
> String webColor = "#";
>
> int red = analogRead(A0)/4;
> webColor += String(red, HEX);
> int green = analogRead(A1)/4;
> webColor += String(green, HEX);
> int blue = analogRead(A2)/4;
>
> webColor += String(blue, HEX);
> Serial.println(webColor);
> }
>
>
>
>
>
> On Dec 16, 2010, at 1:27 AM, Alexander Brevig wrote:
>
> > Attached is a zip containing WString.h and .cpp plus
> StaticDynamicMemory.h.
> > Take a backup of the original WString files, and extract this zip into
> the hardware/arduino/cores/arduino folder.
> >
> > Now you're ready to test the modified String library, that does not
> fragment the heap.
> >
> >
> > In the WString header there is a #define called STRING_BUFFER which is
> set to 100 for now, change this to suit your test needs.
> >
> >
> > No error handling is implemented, what do you think we need?
> >
> > I plan to add an availableMemory():int method to the SDM library, and
> maybe some error flags and checks like hasError():int error
> >
> > I also suspect that this library is a bit slower performance wise, but I
> think that's just a cost we'll have to pay to being able to play with
> dynamic strings.
> >
> >
> > Hope to get feedback from someone!
> >
> > On Thu, Dec 16, 2010 at 1:11 AM, Alan Burlison <>
> wrote:
> > On 15/12/2010 16:19, David A. Mellis wrote:
> >
> > I think you're right, but I also don't think that telling people to
> > use the standard C library functions is a solution either. Trying out
> > this String class seems like one way of pushing forwards towards a
> > compromise that provides both an easy-to-use API and a robust
> > implementation. For example, perhaps the buffer sizes need to be
> > specified or provided when the String is instantiated. Or we need an
> > alternative implementation that does more reliable memory allocation
> > (since we're not assuming that the internal buffer is continuous).
> > Other ideas welcome.
> >
> > I think the problem is that the failure modes are not benign. I haven't
> been through all the use cases so this might not work, but perhaps using a
> statically-allocated string ("NOMEM" ?) as a sentinel value instead of null
> when malloc fails might be one way? Also, there might be some benefit in
> making String immutable a la Java - overloaded operators in C++ have a
> tendency to generate anonymous temporaries, which is going to lead to heap
> fragmentation as well.
> >
> > --
> > Alan Burlison
> > --
> >
> > _______________________________________________
___________________________________________________

Posted on the Developers mailing list. Go to http://arduino.cc/mailman/listinfo/developers_arduino.cc to subscribe. It broke in the non-SDM version too, but it took longer to break. In the SDM version it breaks immediately. So it looks like whatever you did highlights the faults sooner, which is good. It also points to a need for an error response of some sort, in answer to your question last mail.

t.

On Jan 3, 2011, at 4:44 PM, Alexander Brevig wrote:

> That breaking of String, does it only occur with the SDM version?
>
> If not, did you find any way to break it? Maybe any of the old faults related to memory?
>
>
> I actually have no time to check this myself right now, so I opted to just ask you.
>
> On Mon, Jan 3, 2011 at 10:35 PM, Tom Igoe <> wrote:
> Thanks, Alexander, and sorry for the delay.
>
> A few tests:
>
> For code that doesn't change the strings much, there's not a big difference, a couple dozen bytes' difference in code size. However, when you start to do dynamic things, it does add up. For example, the StringAppendOperator example is 4910 bytes in 0022, and 5148 bytes with the StaticDynamicMemory version. So it does start to take its toll, memory-wise.
>
> On some sketches it actually takes less memory. For example, the one below is 3738 bytes using the StaticDynamicMemory version, and 3986 bytes in 0022. However, it fails entirely on upload. When the value of (analog 0)/4 is high (0xFF), it never gets out of the setup(). So there's still a pretty easy way to break String, even with these improvements.
>
>
> void setup() {
> Serial.begin(9600);
> Serial.println("Beginning");
> }
>
> void loop() {
>
> String webColor = "#";
>
> int red = analogRead(A0)/4;
> webColor += String(red, HEX);
> int green = analogRead(A1)/4;
> webColor += String(green, HEX);
> int blue = analogRead(A2)/4;
>
> webColor += String(blue, HEX);
> Serial.println(webColor);
> }
>
>
>
>
>
> On Dec 16, 2010, at 1:27 AM, Alexander Brevig wrote:
>
> > Attached is a zip containing WString.h and .cpp plus StaticDynamicMemory.h.
> > Take a backup of the original WString files, and extract this zip into the hardware/arduino/cores/arduino folder.
> >
> > Now you're ready to test the modified String library, that does not fragment the heap.
> >
> >
> > In the WString header there is a #define called STRING_BUFFER which is set to 100 for now, change this to suit your test needs.
> >
> >
> > No error handling is implemented, what do you think we need?
> >
> > I plan to add an availableMemory():int method to the SDM library, and maybe some error flags and checks like hasError():int error
> >
> > I also suspect that this library is a bit slower performance wise, but I think that's just a cost we'll have to pay to being able to play with dynamic strings.
> >
> >
> > Hope to get feedback from someone!
> >
> > On Thu, Dec 16, 2010 at 1:11 AM, Alan Burlison <> wrote:
> > On 15/12/2010 16:19, David A. Mellis wrote:
> >
> > I think you're right, but I also don't think that telling people to
> > use the standard C library functions is a solution either. Trying out
> > this String class seems like one way of pushing forwards towards a
> > compromise that provides both an easy-to-use API and a robust
> > implementation. For example, perhaps the buffer sizes need to be
> > specified or provided when the String is instantiated. Or we need an
> > alternative implementation that does more reliable memory allocation
> > (since we're not assuming that the internal buffer is continuous).
> > Other ideas welcome.
> >
> > I think the problem is that the failure modes are not benign. I haven't been through all the use cases so this might not work, but perhaps using a statically-allocated string ("NOMEM" ?) as a sentinel value instead of null when malloc fails might be one way? Also, there might be some benefit in making String immutable a la Java - overloaded operators in C++ have a tendency to generate anonymous temporaries, which is going to lead to heap fragmentation as well.
> >
> > --
> > Alan Burlison
> > --
> >
> > _______________________________________________
___________________________________________________

Posted on the Developers mailing list. Go to http://arduino.cc/mailman/listinfo/developers_arduino.cc to subscribe. There seems to be a bug with the assignment operator, I'm on it and I'll get
back to you as soon as I get something done.

Thank you for your tests and feedback.


I'll do some tests on my own before I repost it here.

On Tue, Jan 4, 2011 at 6:53 PM, Rick Anderson
<>wrote:

> I just created a test and unpacked and tested it. I also created a
> test based on Tom's code. Not sure I caught the maximum value error
> for 0xFF.
>
> I also ran the tests for bug 411. All the tests compile, but there is
> still memory loss.
>
> I'm attaching the Arduino Test suite, and the test code so you can run
> them as you debug. Let me know if this was helpful.
>
> --Rick
>
> Test run results:
> Example: ATS_StringAssignmentTest.pde
> info.MANUFACTURER = Arduino
> info.CPU-NAME = ATmega328P
> info.GCC-Version = 4.3.2
> info.AVR-LibC-Ver = 1.6.4
> info.Compiled-date = Jan 4 2011
> info.Test-Suite-Name = ATS_StringAssignmentTest
> info.Free-memory = 1110 bytes
> Memory Usage (lost 59 bytes) ... FAIL
> --------------------------
> Ran 1 tests in 1.378s
>
> FAILED (failures=1)
>
>
> Example: ATS_StringMemoryTestPassByReference.pde
>
> info.MANUFACTURER = Arduino
> info.CPU-NAME = ATmega328P
> info.GCC-Version = 4.3.2
> info.AVR-LibC-Ver = 1.6.4
> info.Compiled-date = Jan 4 2011
> info.Test-Suite-Name = ATS_StringMemoryTestPassByReference
> info.Free-memory = 1120 bytes
> Memory Usage (lost 59 bytes) ... FAIL
> --------------------------
> Ran 1 tests in 1.389s
>
> FAILED (failures=1)
>
>
> Example: Tom Igoe Memory Test
> info.MANUFACTURER = Arduino
> info.CPU-NAME = ATmega328P
> info.GCC-Version = 4.3.2
> info.AVR-LibC-Ver = 1.6.4
> info.Compiled-date = Jan 4 2011
> info.Test-Suite-Name = Tom Igoe Memory Test
> info.Free-memory = 1328 bytes
> Memory Usage (lost 9 bytes) ... FAIL
> --------------------------
> Ran 1 tests in 1.374s
>
> FAILED (failures=1)
>
>
>
> --Rick
>
> Tom, rewrote your example as a test.
>
> //************************************************************************
> //* Arduino Tom Igoe Memory Test
> //* (C) 2010 by Rick Anderson
> //* Open source as per standard Arduino code
> //*
> //************************************************************************
> //* Jan 4, 2011 Started on Tom Igoe Memory Test
> //************************************************************************
>
> #include "WProgram.h"
> #include "HardwareSerial.h"
> #include
>
> //************************************************************************
> void setup()
> {
> int startMemoryUsage;
> /*
> * Create variable for the tests.
> */
>
> String webColor = "#000000";
>
> int red = 1023/4;
> int blue = 512/4;
> int green = 128/4;
>
> /*
> * initiate the test run
> */
> //Record starting memory amount
> startMemoryUsage = ATS_GetFreeMemory();
> //Begin test run
> ATS_begin("Arduino", "Tom Igoe Memory Test");
>
> webColor = "#";
> webColor += String(red, HEX);
> webColor += String(green, HEX);
> webColor += String(blue, HEX);
>
> ATS_ReportMemoryUsage(startMemoryUsage);
>
> /*
> * Test complete
> */
>
> ATS_end();
> }
>
>
> //************************************************************************
> void loop()
> {
>
>
> }
>
>
>
>
> On Mon, Jan 3, 2011 at 9:35 PM, Tom Igoe <> wrote:
> > It broke in the non-SDM version too, but it took longer to break. In the
> SDM version it breaks immediately. So it looks like whatever you did
> highlights the faults sooner, which is good. It also points to a need for an
> error response of some sort, in answer to your question last mail.
> >
> > t.
> >
> > On Jan 3, 2011, at 4:44 PM, Alexander Brevig wrote:
> >
> >> That breaking of String, does it only occur with the SDM version?
> >>
> >> If not, did you find any way to break it? Maybe any of the old faults
> related to memory?
> >>
> >>
> >> I actually have no time to check this myself right now, so I opted to
> just ask you.
> >>
> >> On Mon, Jan 3, 2011 at 10:35 PM, Tom Igoe <> wrote:
> >> Thanks, Alexander, and sorry for the delay.
> >>
> >> A few tests:
> >>
> >> For code that doesn't change the strings much, there's not a big
> difference, a couple dozen bytes' difference in code size. However, when
> you start to do dynamic things, it does add up. For example, the
> StringAppendOperator example is 4910 bytes in 0022, and 5148 bytes with the
> StaticDynamicMemory version. So it does start to take its toll, memory-wise.
> >>
> >> On some sketches it actually takes less memory. For example, the one
> below is 3738 bytes using the StaticDynamicMemory version, and 3986 bytes in
> 0022. However, it fails entirely on upload. When the value of (analog 0)/4
> is high (0xFF), it never gets out of the setup(). So there's still a pretty
> easy way to break String, even with these improvements.
> >>
> >>
> >> void setup() {
> >> Serial.begin(9600);
> >> Serial.println("Beginning");
> >> }
> >>
> >> void loop() {
> >>
> >> String webColor = "#";
> >>
> >> int red = analogRead(A0)/4;
> >> webColor += String(red, HEX);
> >> int green = analogRead(A1)/4;
> >> webColor += String(green, HEX);
> >> int blue = analogRead(A2)/4;
> >>
> >> webColor += String(blue, HEX);
> >> Serial.println(webColor);
> >> }
> >>
> >>
> >>
> >>
> >>
> >> On Dec 16, 2010, at 1:27 AM, Alexander Brevig wrote:
> >>
> >> > Attached is a zip containing WString.h and .cpp plus
> StaticDynamicMemory.h.
> >> > Take a backup of the original WString files, and extract this zip into
> the hardware/arduino/cores/arduino folder.
> >> >
> >> > Now you're ready to test the modified String library, that does not
> fragment the heap.
> >> >
> >> >
> >> > In the WString header there is a #define called STRING_BUFFER which is
> set to 100 for now, change this to suit your test needs.
> >> >
> >> >
> >> > No error handling is implemented, what do you think we need?
> >> >
> >> > I plan to add an availableMemory():int method to the SDM library, and
> maybe some error flags and checks like hasError():int error
> >> >
> >> > I also suspect that this library is a bit slower performance wise, but
> I think that's just a cost we'll have to pay to being able to play with
> dynamic strings.
> >> >
> >> >
> >> > Hope to get feedback from someone!
> >> >
> >> > On Thu, Dec 16, 2010 at 1:11 AM, Alan Burlison <
> > wrote:
> >> > On 15/12/2010 16:19, David A. Mellis wrote:
> >> >
> >> > I think you're right, but I also don't think that telling people to
> >> > use the standard C library functions is a solution either. Trying out
> >> > this String class seems like one way of pushing forwards towards a
> >> > compromise that provides both an easy-to-use API and a robust
> >> > implementation. For example, perhaps the buffer sizes need to be
> >> > specified or provided when the String is instantiated. Or we need an
> >> > alternative implementation that does more reliable memory allocation
> >> > (since we're not assuming that the internal buffer is continuous).
> >> > Other ideas welcome.
> >> >
> >> > I think the problem is that the failure modes are not benign. I
> haven't been through all the use cases so this might not work, but perhaps
> using a statically-allocated string ("NOMEM" ?) as a sentinel value instead
> of null when malloc fails might be one way? Also, there might be some
> benefit in making String immutable a la Java - overloaded operators in C++
> have a tendency to generate anonymous temporaries, which is going to lead to
> heap fragmentation as well.
> >> >
> >> > --
> >> > Alan Burlison
> >> > --
> >> >
> >> > _______________________________________________
___________________________________________________

Posted on the Developers mailing list. Go to http://arduino.cc/mailman/listinfo/developers_arduino.cc to subscribe. Is this test suite any different than the one in the github repo?

t.

On Jan 4, 2011, at 12:53 PM, Rick Anderson wrote:

> I just created a test and unpacked and tested it. I also created a
> test based on Tom's code. Not sure I caught the maximum value error
> for 0xFF.
>
> I also ran the tests for bug 411. All the tests compile, but there is
> still memory loss.
>
> I'm attaching the Arduino Test suite, and the test code so you can run
> them as you debug. Let me know if this was helpful.
>
> --Rick
>
> Test run results:
> Example: ATS_StringAssignmentTest.pde
> info.MANUFACTURER = Arduino
> info.CPU-NAME = ATmega328P
> info.GCC-Version = 4.3.2
> info.AVR-LibC-Ver = 1.6.4
> info.Compiled-date = Jan 4 2011
> info.Test-Suite-Name = ATS_StringAssignmentTest
> info.Free-memory = 1110 bytes
> Memory Usage (lost 59 bytes) ... FAIL
> --------------------------
> Ran 1 tests in 1.378s
>
> FAILED (failures=1)
>
>
> Example: ATS_StringMemoryTestPassByReference.pde
>
> info.MANUFACTURER = Arduino
> info.CPU-NAME = ATmega328P
> info.GCC-Version = 4.3.2
> info.AVR-LibC-Ver = 1.6.4
> info.Compiled-date = Jan 4 2011
> info.Test-Suite-Name = ATS_StringMemoryTestPassByReference
> info.Free-memory = 1120 bytes
> Memory Usage (lost 59 bytes) ... FAIL
> --------------------------
> Ran 1 tests in 1.389s
>
> FAILED (failures=1)
>
>
> Example: Tom Igoe Memory Test
> info.MANUFACTURER = Arduino
> info.CPU-NAME = ATmega328P
> info.GCC-Version = 4.3.2
> info.AVR-LibC-Ver = 1.6.4
> info.Compiled-date = Jan 4 2011
> info.Test-Suite-Name = Tom Igoe Memory Test
> info.Free-memory = 1328 bytes
> Memory Usage (lost 9 bytes) ... FAIL
> --------------------------
> Ran 1 tests in 1.374s
>
> FAILED (failures=1)
>
>
>
> --Rick
>
> Tom, rewrote your example as a test.
>
> //************************************************************************
> //* Arduino Tom Igoe Memory Test
> //* (C) 2010 by Rick Anderson
> //* Open source as per standard Arduino code
> //*
> //************************************************************************
> //* Jan 4, 2011 Started on Tom Igoe Memory Test
> //************************************************************************
>
> #include "WProgram.h"
> #include "HardwareSerial.h"
> #include
>
> //************************************************************************
> void setup()
> {
> int startMemoryUsage;
> /*
> * Create variable for the tests.
> */
>
> String webColor = "#000000";
>
> int red = 1023/4;
> int blue = 512/4;
> int green = 128/4;
>
> /*
> * initiate the test run
> */
> //Record starting memory amount
> startMemoryUsage = ATS_GetFreeMemory();
> //Begin test run
> ATS_begin("Arduino", "Tom Igoe Memory Test");
>
> webColor = "#";
> webColor += String(red, HEX);
> webColor += String(green, HEX);
> webColor += String(blue, HEX);
>
> ATS_ReportMemoryUsage(startMemoryUsage);
>
> /*
> * Test complete
> */
>
> ATS_end();
> }
>
>
> //************************************************************************
> void loop()
> {
>
>
> }
>
>
>
>
> On Mon, Jan 3, 2011 at 9:35 PM, Tom Igoe <> wrote:
>> It broke in the non-SDM version too, but it took longer to break. In the SDM version it breaks immediately. So it looks like whatever you did highlights the faults sooner, which is good. It also points to a need for an error response of some sort, in answer to your question last mail.
>>
>> t.
>>
>> On Jan 3, 2011, at 4:44 PM, Alexander Brevig wrote:
>>
>>> That breaking of String, does it only occur with the SDM version?
>>>
>>> If not, did you find any way to break it? Maybe any of the old faults related to memory?
>>>
>>>
>>> I actually have no time to check this myself right now, so I opted to just ask you.
>>>
>>> On Mon, Jan 3, 2011 at 10:35 PM, Tom Igoe <> wrote:
>>> Thanks, Alexander, and sorry for the delay.
>>>
>>> A few tests:
>>>
>>> For code that doesn't change the strings much, there's not a big difference, a couple dozen bytes' difference in code size. However, when you start to do dynamic things, it does add up. For example, the StringAppendOperator example is 4910 bytes in 0022, and 5148 bytes with the StaticDynamicMemory version. So it does start to take its toll, memory-wise.
>>>
>>> On some sketches it actually takes less memory. For example, the one below is 3738 bytes using the StaticDynamicMemory version, and 3986 bytes in 0022. However, it fails entirely on upload. When the value of (analog 0)/4 is high (0xFF), it never gets out of the setup(). So there's still a pretty easy way to break String, even with these improvements.
>>>
>>>
>>> void setup() {
>>> Serial.begin(9600);
>>> Serial.println("Beginning");
>>> }
>>>
>>> void loop() {
>>>
>>> String webColor = "#";
>>>
>>> int red = analogRead(A0)/4;
>>> webColor += String(red, HEX);
>>> int green = analogRead(A1)/4;
>>> webColor += String(green, HEX);
>>> int blue = analogRead(A2)/4;
>>>
>>> webColor += String(blue, HEX);
>>> Serial.println(webColor);
>>> }
>>>
>>>
>>>
>>>
>>>
>>> On Dec 16, 2010, at 1:27 AM, Alexander Brevig wrote:
>>>
>>>> Attached is a zip containing WString.h and .cpp plus StaticDynamicMemory.h.
>>>> Take a backup of the original WString files, and extract this zip into the hardware/arduino/cores/arduino folder.
>>>>
>>>> Now you're ready to test the modified String library, that does not fragment the heap.
>>>>
>>>>
>>>> In the WString header there is a #define called STRING_BUFFER which is set to 100 for now, change this to suit your test needs.
>>>>
>>>>
>>>> No error handling is implemented, what do you think we need?
>>>>
>>>> I plan to add an availableMemory():int method to the SDM library, and maybe some error flags and checks like hasError():int error
>>>>
>>>> I also suspect that this library is a bit slower performance wise, but I think that's just a cost we'll have to pay to being able to play with dynamic strings.
>>>>
>>>>
>>>> Hope to get feedback from someone!
>>>>
>>>> On Thu, Dec 16, 2010 at 1:11 AM, Alan Burlison <> wrote:
>>>> On 15/12/2010 16:19, David A. Mellis wrote:
>>>>
>>>> I think you're right, but I also don't think that telling people to
>>>> use the standard C library functions is a solution either. Trying out
>>>> this String class seems like one way of pushing forwards towards a
>>>> compromise that provides both an easy-to-use API and a robust
>>>> implementation. For example, perhaps the buffer sizes need to be
>>>> specified or provided when the String is instantiated. Or we need an
>>>> alternative implementation that does more reliable memory allocation
>>>> (since we're not assuming that the internal buffer is continuous).
>>>> Other ideas welcome.
>>>>
>>>> I think the problem is that the failure modes are not benign. I haven't been through all the use cases so this might not work, but perhaps using a statically-allocated string ("NOMEM" ?) as a sentinel value instead of null when malloc fails might be one way? Also, there might be some benefit in making String immutable a la Java - overloaded operators in C++ have a tendency to generate anonymous temporaries, which is going to lead to heap fragmentation as well.
>>>>
>>>> --
>>>> Alan Burlison
>>>> --
>>>>
>>>> _______________________________________________
___________________________________________________

Posted on the Developers mailing list. Go to http://arduino.cc/mailman/listinfo/developers_arduino.cc to subscribe. Same exact one. I just included it just in case.

--Rick

On Tue, Jan 4, 2011 at 9:01 PM, Tom Igoe <> wrote:
> Is this test suite any different than the one in the github repo?
>
> t.
>
> On Jan 4, 2011, at 12:53 PM, Rick Anderson wrote:
>
>> I just created a test and unpacked and tested it. I also created a
>> test based on Tom's code. Not sure I caught the maximum value error
>> for 0xFF.
>>
>> I also ran the tests for bug 411. All the tests compile, but there is
>> still memory loss.
>>
>> I'm attaching the Arduino Test suite, and the test code so you can run
>> them as you debug. Let me know if this was helpful.
>>
>> --Rick
>>
>> Test run results:
>> Example:  ATS_StringAssignmentTest.pde
>> info.MANUFACTURER    = Arduino
>> info.CPU-NAME        = ATmega328P
>> info.GCC-Version     = 4.3.2
>> info.AVR-LibC-Ver    = 1.6.4
>> info.Compiled-date   = Jan  4 2011
>> info.Test-Suite-Name = ATS_StringAssignmentTest
>> info.Free-memory     = 1110 bytes
>> Memory Usage (lost 59 bytes)                                ... FAIL
>> --------------------------
>> Ran 1 tests in 1.378s
>>
>> FAILED (failures=1)
>>
>>
>> Example: ATS_StringMemoryTestPassByReference.pde
>>
>> info.MANUFACTURER    = Arduino
>> info.CPU-NAME        = ATmega328P
>> info.GCC-Version     = 4.3.2
>> info.AVR-LibC-Ver    = 1.6.4
>> info.Compiled-date   = Jan  4 2011
>> info.Test-Suite-Name = ATS_StringMemoryTestPassByReference
>> info.Free-memory     = 1120 bytes
>> Memory Usage (lost 59 bytes)                                ... FAIL
>> --------------------------
>> Ran 1 tests in 1.389s
>>
>> FAILED (failures=1)
>>
>>
>> Example: Tom Igoe Memory Test
>> info.MANUFACTURER    = Arduino
>> info.CPU-NAME        = ATmega328P
>> info.GCC-Version     = 4.3.2
>> info.AVR-LibC-Ver    = 1.6.4
>> info.Compiled-date   = Jan  4 2011
>> info.Test-Suite-Name = Tom Igoe Memory Test
>> info.Free-memory     = 1328 bytes
>> Memory Usage (lost 9 bytes)                                 ... FAIL
>> --------------------------
>> Ran 1 tests in 1.374s
>>
>> FAILED (failures=1)
>>
>>
>>
>> --Rick
>>
>> Tom, rewrote your example as a test.
>>
>> //************************************************************************
>> //*   Arduino Tom Igoe Memory Test
>> //*           (C) 2010 by Rick Anderson
>> //*           Open source as per standard Arduino code
>> //*
>> //************************************************************************
>> //*   Jan 4,  2011     Started on Tom Igoe Memory Test
>> //************************************************************************
>>
>> #include      "WProgram.h"
>> #include      "HardwareSerial.h"
>> #include      
>>
>> //************************************************************************
>> void setup()
>> {
>>  int          startMemoryUsage;
>>  /*
>>    * Create variable for the tests.
>>   */
>>
>>  String webColor = "#000000";
>>
>>  int red = 1023/4;
>>  int blue = 512/4;
>>  int green = 128/4;
>>
>>  /*
>>  * initiate the test run
>>   */
>>  //Record starting memory amount
>>  startMemoryUsage     =       ATS_GetFreeMemory();
>>  //Begin test run
>>  ATS_begin("Arduino", "Tom Igoe Memory Test");
>>
>>  webColor = "#";
>>  webColor += String(red, HEX);
>>  webColor += String(green, HEX);
>>  webColor += String(blue, HEX);
>>
>>  ATS_ReportMemoryUsage(startMemoryUsage);
>>
>>  /*
>>   * Test complete
>>   */
>>
>>  ATS_end();
>> }
>>
>>
>> //************************************************************************
>> void loop()
>> {
>>
>>
>> }
>>
>>
>>
>>
>> On Mon, Jan 3, 2011 at 9:35 PM, Tom Igoe <> wrote:
>>> It broke in the non-SDM version too, but it took longer to break. In the SDM version it breaks immediately. So it looks like whatever you did highlights the faults sooner, which is good. It also points to a need for an error response of some sort, in answer to your question last mail.
>>>
>>> t.
>>>
>>> On Jan 3, 2011, at 4:44 PM, Alexander Brevig wrote:
>>>
>>>> That breaking of String, does it only occur with the SDM version?
>>>>
>>>> If not, did you find any way to break it? Maybe any of the old faults related to memory?
>>>>
>>>>
>>>> I actually have no time to check this myself right now, so I opted to just ask you.
>>>>
>>>> On Mon, Jan 3, 2011 at 10:35 PM, Tom Igoe <> wrote:
>>>> Thanks, Alexander, and sorry for the delay.
>>>>
>>>> A few tests:
>>>>
>>>> For code that doesn't change the strings much, there's not a big difference, a couple dozen bytes' difference in code size.  However, when you start to do dynamic things, it does add up.  For example, the StringAppendOperator example is  4910 bytes in 0022, and 5148 bytes with the StaticDynamicMemory version. So it does start to take its toll, memory-wise.
>>>>
>>>> On some sketches it actually takes less memory.  For example, the one below is 3738 bytes using the StaticDynamicMemory version, and 3986 bytes in 0022.  However, it fails entirely on upload.  When the value of (analog 0)/4 is high (0xFF), it never gets out of the setup(). So there's still a pretty easy way to break String, even with these improvements.
>>>>
>>>>
>>>> void setup() {
>>>>  Serial.begin(9600);
>>>>  Serial.println("Beginning");
>>>> }
>>>>
>>>> void loop() {
>>>>
>>>>  String webColor = "#";
>>>>
>>>>  int red = analogRead(A0)/4;
>>>>  webColor += String(red, HEX);
>>>>  int green = analogRead(A1)/4;
>>>>  webColor += String(green, HEX);
>>>>  int blue = analogRead(A2)/4;
>>>>
>>>>  webColor += String(blue, HEX);
>>>>  Serial.println(webColor);
>>>> }
>>>>
>>>>
>>>>
>>>>
>>>>
>>>> On Dec 16, 2010, at 1:27 AM, Alexander Brevig wrote:
>>>>
>>>>> Attached is a zip containing WString.h and .cpp plus StaticDynamicMemory.h.
>>>>> Take a backup of the original WString files, and extract this zip into the hardware/arduino/cores/arduino folder.
>>>>>
>>>>> Now you're ready to test the modified String library, that does not fragment the heap.
>>>>>
>>>>>
>>>>> In the WString header there is a #define called STRING_BUFFER which is set to 100 for now, change this to suit your test needs.
>>>>>
>>>>>
>>>>> No error handling is implemented, what do you think we need?
>>>>>
>>>>> I plan to add an availableMemory():int method to the SDM library, and maybe some error flags and checks like hasError():int error
>>>>>
>>>>> I also suspect that this library is a bit slower performance wise, but I think that's just a cost we'll have to pay to being able to play with dynamic strings.
>>>>>
>>>>>
>>>>> Hope to  get feedback from someone!
>>>>>
>>>>> On Thu, Dec 16, 2010 at 1:11 AM, Alan Burlison <> wrote:
>>>>> On 15/12/2010 16:19, David A. Mellis wrote:
>>>>>
>>>>> I think you're right, but I also don't think that telling people to
>>>>> use the standard C library functions is a solution either.  Trying out
>>>>> this String class seems like one way of pushing forwards towards a
>>>>> compromise that provides both an easy-to-use API and a robust
>>>>> implementation.  For example, perhaps the buffer sizes need to be
>>>>> specified or provided when the String is instantiated.  Or we need an
>>>>> alternative implementation that does more reliable memory allocation
>>>>> (since we're not assuming that the internal buffer is continuous).
>>>>> Other ideas welcome.
>>>>>
>>>>> I think the problem is that the failure modes are not benign.  I haven't been through all the use cases so this might not work, but perhaps using a statically-allocated string ("NOMEM" ?) as a sentinel value instead of null when malloc fails might be one way?  Also, there might be some benefit in making String immutable a la Java - overloaded operators in C++ have a tendency to generate anonymous temporaries, which is going to lead to heap fragmentation as well.
>>>>>
>>>>> --
>>>>> Alan Burlison
>>>>> --
>>>>>
>>>>> _______________________________________________
___________________________________________________

Posted on the Developers mailing list. Go to http://arduino.cc/mailman/listinfo/developers_arduino.cc to subscribe. On 04/01/2011 17:53, Rick Anderson wrote:

> I also ran the tests for bug 411. All the tests compile, but there is
> still memory loss.

Most of the assumptions made by the test harness and test case code are
wrong, any reports of 'lost' memory are therefore likely to be wrong as
well. If you want to do leak detection you can't do it in the naive way
it is being done at present.

--
Alan Burlison
--

_______________________________________________
___________________________________________________

Posted on the Developers mailing list. Go to http://arduino.cc/mailman/listinfo/developers_arduino.cc to subscribe. Alan,

The tests themselves are quick and dirty, and not strategic or
comprehensive. I'd like your input to create a good procedure for
memory testing. I also have feedback from Paul Stoffregen for the test
suite:
----
Another problem involves gcc's optimizer ignoring the inline request
for ATS_ReportMemoryUsage. As the comment in the code explains, it
must be inline to avoid measuring its own stack frame. I believe
adding this line in ArduinoTestSuite.h fixes the problem by forcing
gcc to inline.

inline void ATS_ReportMemoryUsage(int _memoryUsageAtStart)
__attribute__((always_inline, unused));

The last problem is a tiny bit of dynamic memory permanently held for
the free list. To allow for this, the test really should call
malloc() and free() once, so the allocator is fully initialized before
testing.
----

I'd like to combine both sets of feedback, and set up some issues in
the system, then fix them. Is the above the problem you saw? Are their
other assumptions that would impact measuring memory? And updating the
memory test in the the test suite.

In terms of creating tests for memory leaks. It looks best to move all
the memory usage inside a function. What else could be done to
constrain the problem, and measuring more affectively.

I'm traveling back to NJ today, so I can't respond right away.

--Rick

On Wed, Jan 5, 2011 at 8:52 AM, Alan Burlison <> wrote:
> On 04/01/2011 17:53, Rick Anderson wrote:
>
>> I also ran the tests for bug 411. All the tests compile, but there is
>> still memory loss.
>
> Most of the assumptions made by the test harness and test case code are
> wrong, any reports of 'lost' memory are therefore likely to be wrong as
> well.  If you want to do leak detection you can't do it in the naive way it
> is being done at present.
>
> --
> Alan Burlison
> --
>



--
President
Fair Use Building and Research (****) Labs
http://fubarlabs.org

_______________________________________________
___________________________________________________

Posted on the Developers mailing list. Go to http://arduino.cc/mailman/listinfo/developers_arduino.cc to subscribe. On 05/01/2011 15:19, Rick Anderson wrote:

> ----
> Another problem involves gcc's optimizer ignoring the inline request
> for ATS_ReportMemoryUsage. As the comment in the code explains, it
> must be inline to avoid measuring its own stack frame. I believe
> adding this line in ArduinoTestSuite.h fixes the problem by forcing
> gcc to inline.
>
> inline void ATS_ReportMemoryUsage(int _memoryUsageAtStart)
> __attribute__((always_inline, unused));

Yes, that's one of the problems. And even the __attribute__
'workaround' is a fragile hack.

> The last problem is a tiny bit of dynamic memory permanently held for
> the free list. To allow for this, the test really should call
> malloc() and free() once, so the allocator is fully initialized before

That's part of a problem, but an initial call malloc/free call isn't
guaranteed to make all the issues go away either. From looking at the
avr-libc malloc implementation it does try to coalesce the heap, but
relying on multiple malloc implementation artefacts is a really bad idea
- there's no guarantee that future malloc implementations will always
coalesce on every free, and there's no guarantee that __bss_end or
__brkval will always be adjusted on each malloc/free call.

The other issue is that of object lifetimes. The test code has
instances of String objects which are allocated on the stack and that
are still in scope when the 'leak' memory check is performed. That
means the String destructors won't have been called and the dynamically
allocated part of the String will still be allocated.

A true memory leak is a block of allocated memory that has no references
to it. However that's not what the test code is checking for. If a
library routine used malloc to perform a one-time library-private buffer
allocation where the buffer is retained for the lifetime of the program,
the current leak checking would incorrectly report that as a leak. It
isn't a leak because there's still a reference to the block inside the
library.

The only semi-reliable way to do what you want is to use an instrumented
malloc implementation, and that's going to be very difficult to
implement on a constrained platform such as the AVR. If you want to
test the String implementation for leaks, my advice is to do it on a
more capable platform (e.g. *nix) and use one of the many instrumented
mallocs that are available.

--
Alan Burlison
--

_______________________________________________
___________________________________________________

Posted on the Developers mailing list. Go to http://arduino.cc/mailman/listinfo/developers_arduino.cc to subscribe. Slightly unrelated to what you guys are discussing now but:
I'm not sure if I've made this clear, but the new version of String that I'm
working on now does not use malloc or any other c function for dynamic
memory. What happens is that I allocate memory statically on the stack and
serve that memory dynamically to the instances of String.

I have some time on my hands now and have a look at getting the += not to
break the code

On Wed, Jan 5, 2011 at 7:10 PM, Alan Burlison <>wrote:

> On 05/01/2011 15:19, Rick Anderson wrote:
>
> ----
>> Another problem involves gcc's optimizer ignoring the inline request
>> for ATS_ReportMemoryUsage. As the comment in the code explains, it
>> must be inline to avoid measuring its own stack frame. I believe
>> adding this line in ArduinoTestSuite.h fixes the problem by forcing
>> gcc to inline.
>>
>> inline void ATS_ReportMemoryUsage(int _memoryUsageAtStart)
>> __attribute__((always_inline, unused));
>>
>
> Yes, that's one of the problems. And even the __attribute__ 'workaround'
> is a fragile hack.
>
>
> The last problem is a tiny bit of dynamic memory permanently held for
>> the free list. To allow for this, the test really should call
>> malloc() and free() once, so the allocator is fully initialized before
>>
>
> That's part of a problem, but an initial call malloc/free call isn't
> guaranteed to make all the issues go away either. From looking at the
> avr-libc malloc implementation it does try to coalesce the heap, but relying
> on multiple malloc implementation artefacts is a really bad idea - there's
> no guarantee that future malloc implementations will always coalesce on
> every free, and there's no guarantee that __bss_end or __brkval will always
> be adjusted on each malloc/free call.
>
> The other issue is that of object lifetimes. The test code has instances
> of String objects which are allocated on the stack and that are still in
> scope when the 'leak' memory check is performed. That means the String
> destructors won't have been called and the dynamically allocated part of the
> String will still be allocated.
>
> A true memory leak is a block of allocated memory that has no references to
> it. However that's not what the test code is checking for. If a library
> routine used malloc to perform a one-time library-private buffer allocation
> where the buffer is retained for the lifetime of the program, the current
> leak checking would incorrectly report that as a leak. It isn't a leak
> because there's still a reference to the block inside the library.
>
> The only semi-reliable way to do what you want is to use an instrumented
> malloc implementation, and that's going to be very difficult to implement on
> a constrained platform such as the AVR. If you want to test the String
> implementation for leaks, my advice is to do it on a more capable platform
> (e.g. *nix) and use one of the many instrumented mallocs that are available.
>
> --
> Alan Burlison
> --
>
>
> _______________________________________________
___________________________________________________

Posted on the Developers mailing list. Go to http://arduino.cc/mailman/listinfo/developers_arduino.cc to subscribe. On 05/01/2011 18:25, Alexander Brevig wrote:

> Slightly unrelated to what you guys are discussing now but:
> I'm not sure if I've made this clear, but the new version of String that I'm
> working on now does not use malloc or any other c function for dynamic
> memory. What happens is that I allocate memory statically on the stack and
> serve that memory dynamically to the instances of String.

Does that mean that the total space occupied by all Strings has to be
decided up front? If so, what is the behaviour when an allocation fails?

To be honest I don't really see the point of doing this - all you are
doing is re-implementing malloc.

--
Alan Burlison
--

_______________________________________________
___________________________________________________

Posted on the Developers mailing list. Go to http://arduino.cc/mailman/listinfo/developers_arduino.cc to subscribe. No, actually I am not reimplementing malloc, because my algorithm guarantees
no fragmentation and always 100% effective use of the allocated memory.

"Does that mean that the total space occupied by all Strings has to be
decided up front? "
Yes, just like the buffer for the serial ++

I know I would opt to have the restriction for a predetermined allocated
space WITH error reporting (how we do is up to you guys, feed me with ideas
I'll implement whatever we agree is best) than having
seemingly infinite memory that crashes and burns.

On Wed, Jan 5, 2011 at 7:33 PM, Alan Burlison <>wrote:

> On 05/01/2011 18:25, Alexander Brevig wrote:
>
> Slightly unrelated to what you guys are discussing now but:
>> I'm not sure if I've made this clear, but the new version of String that
>> I'm
>> working on now does not use malloc or any other c function for dynamic
>> memory. What happens is that I allocate memory statically on the stack and
>> serve that memory dynamically to the instances of String.
>>
>
> Does that mean that the total space occupied by all Strings has to be
> decided up front? If so, what is the behaviour when an allocation fails?
>
> To be honest I don't really see the point of doing this - all you are doing
> is re-implementing malloc.
>
> --
> Alan Burlison
> --
> Well, that was easy (seemingly, probably just jinxed myself...) but here the
test does no longer break, and the usage of memory never exceeds 11 bytes.

It would be awesome if someone would test it.


Also, please tell me now if this effort will lead to nowhere. Is the cost of
being constrained to a buffer size a deal-breaker?

On Wed, Jan 5, 2011 at 7:42 PM, Alexander Brevig
<>wrote:

> No, actually I am not reimplementing malloc, because my algorithm
> guarantees no fragmentation and always 100% effective use of the allocated
> memory.
>
> "Does that mean that the total space occupied by all Strings has to be
> decided up front? "
> Yes, just like the buffer for the serial ++
>
> I know I would opt to have the restriction for a predetermined allocated
> space WITH error reporting (how we do is up to you guys, feed me with ideas
> I'll implement whatever we agree is best) than having
> seemingly infinite memory that crashes and burns.
>
> On Wed, Jan 5, 2011 at 7:33 PM, Alan Burlison <>wrote:
>
>> On 05/01/2011 18:25, Alexander Brevig wrote:
>>
>> Slightly unrelated to what you guys are discussing now but:
>>> I'm not sure if I've made this clear, but the new version of String that
>>> I'm
>>> working on now does not use malloc or any other c function for dynamic
>>> memory. What happens is that I allocate memory statically on the stack
>>> and
>>> serve that memory dynamically to the instances of String.
>>>
>>
>> Does that mean that the total space occupied by all Strings has to be
>> decided up front? If so, what is the behaviour when an allocation fails?
>>
>> To be honest I don't really see the point of doing this - all you are
>> doing is re-implementing malloc.
>>
>> --
>> Alan Burlison
>> --
>>
>
> So sorry you all! I shipped my test code (for msvc++ compiler) in five
minutes I'll post an arduino compatible version. So sorry for this spam!

On Wed, Jan 5, 2011 at 8:01 PM, Alexander Brevig
<>wrote:

> Well, that was easy (seemingly, probably just jinxed myself...) but here
> the test does no longer break, and the usage of memory never exceeds 11
> bytes.
>
> It would be awesome if someone would test it.
>
>
> Also, please tell me now if this effort will lead to nowhere. Is the cost
> of being constrained to a buffer size a deal-breaker?
>
>
> On Wed, Jan 5, 2011 at 7:42 PM, Alexander Brevig <
> > wrote:
>
>> No, actually I am not reimplementing malloc, because my algorithm
>> guarantees no fragmentation and always 100% effective use of the allocated
>> memory.
>>
>> "Does that mean that the total space occupied by all Strings has to be
>> decided up front? "
>> Yes, just like the buffer for the serial ++
>>
>> I know I would opt to have the restriction for a predetermined allocated
>> space WITH error reporting (how we do is up to you guys, feed me with ideas
>> I'll implement whatever we agree is best) than having
>> seemingly infinite memory that crashes and burns.
>>
>> On Wed, Jan 5, 2011 at 7:33 PM, Alan Burlison <>wrote:
>>
>>> On 05/01/2011 18:25, Alexander Brevig wrote:
>>>
>>> Slightly unrelated to what you guys are discussing now but:
>>>> I'm not sure if I've made this clear, but the new version of String that
>>>> I'm
>>>> working on now does not use malloc or any other c function for dynamic
>>>> memory. What happens is that I allocate memory statically on the stack
>>>> and
>>>> serve that memory dynamically to the instances of String.
>>>>
>>>
>>> Does that mean that the total space occupied by all Strings has to be
>>> decided up front? If so, what is the behaviour when an allocation fails?
>>>
>>> To be honest I don't really see the point of doing this - all you are
>>> doing is re-implementing malloc.
>>>
>>> --
>>> Alan Burlison
>>> --
>>>
>>
>>
> > The other issue is that of object lifetimes. The test code has
> instances of String objects which are allocated on the stack and that
> are still in scope when the 'leak' memory check is performed.

That was also in my (off list) email a few days ago, though that bit
didn't make it here.

I believe the plan is to move the tests and object(s) they use to a
function, so the objects will be out of scope when the memory check is made.

There might also another copy of the test which pre-allocates a string
large enough to hold all the data. I'm not sure exactly how I feel
about that approach, but it seems like at least worth trying. Currently
the string library does not have a reserve() function. I've proposed it
before, and today I put it in issue #449.

> If a library routine used malloc to perform a one-time library-private
> buffer allocation where the buffer is retained for the lifetime of the
> program, the current leak checking would incorrectly report that as a
> leak. It isn't a leak because there's still a reference to the block
> inside the library.

Yes, you are correct, the test makes some assumptions about the internal
implementation, and yes, an ideal test wouldn't make any such
assumptions, and yes, it's probably impractical to completely avoid
assumptions on such limited hardware.

But there's a lot of value in actually testing on the real hardware,
with all its limitations and slight differences from running on a PC.
Personally, I think making some assumptions is a pretty good trade-off
for testing in the actual environment. Of course, there's plenty of
room for smart ideas to minimize such assumptions, or perhaps test in
multiple ways.

As someone who's spent a lot of time coding on the string class (and has
more planned), the real value isn't a perfect score if my code is bug
free, but rather a FAIL coming up when I make some mistake that
unexpectedly breaks something. Sure it's annoying if a FAIL comes up
erroneously because the internal implementation changed,

There are so many functions, with so many cases, that subtle errors can
happen (eg, does lastIndexOf work when the search string is the entire
original string... I broke that recently, but everything else worked.....)

If you have ideas about how to catch more types of errors, even if
imperfect, I'd really love to hear.




>
>
> The only semi-reliable way to do what you want is to use an
> instrumented malloc implementation, and that's going to be very
> difficult to implement on a constrained platform such as the AVR. If
> you want to test the String implementation for leaks, my advice is to
> do it on a more capable platform (e.g. *nix) and use one of the many
> instrumented mallocs that are available.
>


_______________________________________________
___________________________________________________

Posted on the Developers mailing list. Go to http://arduino.cc/mailman/listinfo/developers_arduino.cc to subscribe. I'm not sure I follow, string.read(); what would that do?
How do you imagine String to use Stream ? :)

Attached: new version arduino compitable

On Wed, Jan 5, 2011 at 8:20 PM, Tom Igoe <> wrote:

> Could you then just use Stream as a basis for String? Sorry, I didn't look
> into the details of your DMA class, but as long as we're setting a limit to
> begin with, and if we know Stream's pretty solid, why not restructure String
> a bit to use it?
>
> t.
>
>
> On Jan 5, 2011, at 1:42 PM, Alexander Brevig wrote:
>
> > No, actually I am not reimplementing malloc, because my algorithm
> guarantees no fragmentation and always 100% effective use of the allocated
> memory.
> >
> > "Does that mean that the total space occupied by all Strings has to be
> decided up front? "
> > Yes, just like the buffer for the serial ++
> >
> > I know I would opt to have the restriction for a predetermined allocated
> space WITH error reporting (how we do is up to you guys, feed me with ideas
> I'll implement whatever we agree is best) than having seemingly infinite
> memory that crashes and burns.
> >
> > On Wed, Jan 5, 2011 at 7:33 PM, Alan Burlison <>
> wrote:
> > On 05/01/2011 18:25, Alexander Brevig wrote:
> >
> > Slightly unrelated to what you guys are discussing now but:
> > I'm not sure if I've made this clear, but the new version of String that
> I'm
> > working on now does not use malloc or any other c function for dynamic
> > memory. What happens is that I allocate memory statically on the stack
> and
> > serve that memory dynamically to the instances of String.
> >
> > Does that mean that the total space occupied by all Strings has to be
> decided up front? If so, what is the behaviour when an allocation fails?
> >
> > To be honest I don't really see the point of doing this - all you are
> doing is re-implementing malloc.
> >
> > --
> > Alan Burlison
> > --
> >
> > _______________________________________________
___________________________________________________

Posted on the Developers mailing list. Go to http://arduino.cc/mailman/listinfo/developers_arduino.cc to subscribe. > I'm not sure I follow, string.read(); what would that do?
> How do you imagine String to use Stream ? :)

I also do not understand? In fact, I'm completely mystified. Please
explain...

But I would like to let you know I've been working on debugging the
string class, and in the last few days together with the test suite.
I'll likely post code sometimes next week.


>
> Attached: new version arduino compitable
>
> On Wed, Jan 5, 2011 at 8:20 PM, Tom Igoe <
> > wrote:
>
> Could you then just use Stream as a basis for String? Sorry, I
> didn't look into the details of your DMA class, but as long as
> we're setting a limit to begin with, and if we know Stream's
> pretty solid, why not restructure String a bit to use it?
>
> t.
>
>
> On Jan 5, 2011, at 1:42 PM, Alexander Brevig wrote:
>
> > No, actually I am not reimplementing malloc, because my
> algorithm guarantees no fragmentation and always 100% effective
> use of the allocated memory.
> >
> > "Does that mean that the total space occupied by all Strings has
> to be decided up front? "
> > Yes, just like the buffer for the serial ++
> >
> > I know I would opt to have the restriction for a predetermined
> allocated space WITH error reporting (how we do is up to you guys,
> feed me with ideas I'll implement whatever we agree is best) than
> having seemingly infinite memory that crashes and burns.
> >
> > On Wed, Jan 5, 2011 at 7:33 PM, Alan Burlison
> < > wrote:
> > On 05/01/2011 18:25, Alexander Brevig wrote:
> >
> > Slightly unrelated to what you guys are discussing now but:
> > I'm not sure if I've made this clear, but the new version of
> String that I'm
> > working on now does not use malloc or any other c function for
> dynamic
> > memory. What happens is that I allocate memory statically on the
> stack and
> > serve that memory dynamically to the instances of String.
> >
> > Does that mean that the total space occupied by all Strings has
> to be decided up front? If so, what is the behaviour when an
> allocation fails?
> >
> > To be honest I don't really see the point of doing this - all
> you are doing is re-implementing malloc.
> >
> > --
> > Alan Burlison
> > --
> >
> > _______________________________________________
___________________________________________________

Posted on the Developers mailing list. Go to http://arduino.cc/mailman/listinfo/developers_arduino.cc to subscribe.

  #17  
05-01-2011 11:27 PM
Developers member admin is online now
User
 

That breaking of String, does it only occur with the SDM version?

If not, did you find any way to break it? Maybe any of the old faults
related to memory?


I actually have no time to check this myself right now, so I opted to just
ask you.

On Mon, Jan 3, 2011 at 10:35 PM, Tom Igoe <> wrote:

> Thanks, Alexander, and sorry for the delay.
>
> A few tests:
>
> For code that doesn't change the strings much, there's not a big
> difference, a couple dozen bytes' difference in code size. However, when
> you start to do dynamic things, it does add up. For example, the
> StringAppendOperator example is 4910 bytes in 0022, and 5148 bytes with the
> StaticDynamicMemory version. So it does start to take its toll, memory-wise.
>
> On some sketches it actually takes less memory. For example, the one below
> is 3738 bytes using the StaticDynamicMemory version, and 3986 bytes in 0022.
> However, it fails entirely on upload. When the value of (analog 0)/4 is
> high (0xFF), it never gets out of the setup(). So there's still a pretty
> easy way to break String, even with these improvements.
>
>
> void setup() {
> Serial.begin(9600);
> Serial.println("Beginning");
> }
>
> void loop() {
>
> String webColor = "#";
>
> int red = analogRead(A0)/4;
> webColor += String(red, HEX);
> int green = analogRead(A1)/4;
> webColor += String(green, HEX);
> int blue = analogRead(A2)/4;
>
> webColor += String(blue, HEX);
> Serial.println(webColor);
> }
>
>
>
>
>
> On Dec 16, 2010, at 1:27 AM, Alexander Brevig wrote:
>
> > Attached is a zip containing WString.h and .cpp plus
> StaticDynamicMemory.h.
> > Take a backup of the original WString files, and extract this zip into
> the hardware/arduino/cores/arduino folder.
> >
> > Now you're ready to test the modified String library, that does not
> fragment the heap.
> >
> >
> > In the WString header there is a #define called STRING_BUFFER which is
> set to 100 for now, change this to suit your test needs.
> >
> >
> > No error handling is implemented, what do you think we need?
> >
> > I plan to add an availableMemory():int method to the SDM library, and
> maybe some error flags and checks like hasError():int error
> >
> > I also suspect that this library is a bit slower performance wise, but I
> think that's just a cost we'll have to pay to being able to play with
> dynamic strings.
> >
> >
> > Hope to get feedback from someone!
> >
> > On Thu, Dec 16, 2010 at 1:11 AM, Alan Burlison <>
> wrote:
> > On 15/12/2010 16:19, David A. Mellis wrote:
> >
> > I think you're right, but I also don't think that telling people to
> > use the standard C library functions is a solution either. Trying out
> > this String class seems like one way of pushing forwards towards a
> > compromise that provides both an easy-to-use API and a robust
> > implementation. For example, perhaps the buffer sizes need to be
> > specified or provided when the String is instantiated. Or we need an
> > alternative implementation that does more reliable memory allocation
> > (since we're not assuming that the internal buffer is continuous).
> > Other ideas welcome.
> >
> > I think the problem is that the failure modes are not benign. I haven't
> been through all the use cases so this might not work, but perhaps using a
> statically-allocated string ("NOMEM" ?) as a sentinel value instead of null
> when malloc fails might be one way? Also, there might be some benefit in
> making String immutable a la Java - overloaded operators in C++ have a
> tendency to generate anonymous temporaries, which is going to lead to heap
> fragmentation as well.
> >
> > --
> > Alan Burlison
> > --
> >
> > _______________________________________________
___________________________________________________

Posted on the Developers mailing list. Go to http://arduino.cc/mailman/listinfo/developers_arduino.cc to subscribe. It broke in the non-SDM version too, but it took longer to break. In the SDM version it breaks immediately. So it looks like whatever you did highlights the faults sooner, which is good. It also points to a need for an error response of some sort, in answer to your question last mail.

t.

On Jan 3, 2011, at 4:44 PM, Alexander Brevig wrote:

> That breaking of String, does it only occur with the SDM version?
>
> If not, did you find any way to break it? Maybe any of the old faults related to memory?
>
>
> I actually have no time to check this myself right now, so I opted to just ask you.
>
> On Mon, Jan 3, 2011 at 10:35 PM, Tom Igoe <> wrote:
> Thanks, Alexander, and sorry for the delay.
>
> A few tests:
>
> For code that doesn't change the strings much, there's not a big difference, a couple dozen bytes' difference in code size. However, when you start to do dynamic things, it does add up. For example, the StringAppendOperator example is 4910 bytes in 0022, and 5148 bytes with the StaticDynamicMemory version. So it does start to take its toll, memory-wise.
>
> On some sketches it actually takes less memory. For example, the one below is 3738 bytes using the StaticDynamicMemory version, and 3986 bytes in 0022. However, it fails entirely on upload. When the value of (analog 0)/4 is high (0xFF), it never gets out of the setup(). So there's still a pretty easy way to break String, even with these improvements.
>
>
> void setup() {
> Serial.begin(9600);
> Serial.println("Beginning");
> }
>
> void loop() {
>
> String webColor = "#";
>
> int red = analogRead(A0)/4;
> webColor += String(red, HEX);
> int green = analogRead(A1)/4;
> webColor += String(green, HEX);
> int blue = analogRead(A2)/4;
>
> webColor += String(blue, HEX);
> Serial.println(webColor);
> }
>
>
>
>
>
> On Dec 16, 2010, at 1:27 AM, Alexander Brevig wrote:
>
> > Attached is a zip containing WString.h and .cpp plus StaticDynamicMemory.h.
> > Take a backup of the original WString files, and extract this zip into the hardware/arduino/cores/arduino folder.
> >
> > Now you're ready to test the modified String library, that does not fragment the heap.
> >
> >
> > In the WString header there is a #define called STRING_BUFFER which is set to 100 for now, change this to suit your test needs.
> >
> >
> > No error handling is implemented, what do you think we need?
> >
> > I plan to add an availableMemory():int method to the SDM library, and maybe some error flags and checks like hasError():int error
> >
> > I also suspect that this library is a bit slower performance wise, but I think that's just a cost we'll have to pay to being able to play with dynamic strings.
> >
> >
> > Hope to get feedback from someone!
> >
> > On Thu, Dec 16, 2010 at 1:11 AM, Alan Burlison <> wrote:
> > On 15/12/2010 16:19, David A. Mellis wrote:
> >
> > I think you're right, but I also don't think that telling people to
> > use the standard C library functions is a solution either. Trying out
> > this String class seems like one way of pushing forwards towards a
> > compromise that provides both an easy-to-use API and a robust
> > implementation. For example, perhaps the buffer sizes need to be
> > specified or provided when the String is instantiated. Or we need an
> > alternative implementation that does more reliable memory allocation
> > (since we're not assuming that the internal buffer is continuous).
> > Other ideas welcome.
> >
> > I think the problem is that the failure modes are not benign. I haven't been through all the use cases so this might not work, but perhaps using a statically-allocated string ("NOMEM" ?) as a sentinel value instead of null when malloc fails might be one way? Also, there might be some benefit in making String immutable a la Java - overloaded operators in C++ have a tendency to generate anonymous temporaries, which is going to lead to heap fragmentation as well.
> >
> > --
> > Alan Burlison
> > --
> >
> > _______________________________________________
___________________________________________________

Posted on the Developers mailing list. Go to http://arduino.cc/mailman/listinfo/developers_arduino.cc to subscribe. There seems to be a bug with the assignment operator, I'm on it and I'll get
back to you as soon as I get something done.

Thank you for your tests and feedback.


I'll do some tests on my own before I repost it here.

On Tue, Jan 4, 2011 at 6:53 PM, Rick Anderson
<>wrote:

> I just created a test and unpacked and tested it. I also created a
> test based on Tom's code. Not sure I caught the maximum value error
> for 0xFF.
>
> I also ran the tests for bug 411. All the tests compile, but there is
> still memory loss.
>
> I'm attaching the Arduino Test suite, and the test code so you can run
> them as you debug. Let me know if this was helpful.
>
> --Rick
>
> Test run results:
> Example: ATS_StringAssignmentTest.pde
> info.MANUFACTURER = Arduino
> info.CPU-NAME = ATmega328P
> info.GCC-Version = 4.3.2
> info.AVR-LibC-Ver = 1.6.4
> info.Compiled-date = Jan 4 2011
> info.Test-Suite-Name = ATS_StringAssignmentTest
> info.Free-memory = 1110 bytes
> Memory Usage (lost 59 bytes) ... FAIL
> --------------------------
> Ran 1 tests in 1.378s
>
> FAILED (failures=1)
>
>
> Example: ATS_StringMemoryTestPassByReference.pde
>
> info.MANUFACTURER = Arduino
> info.CPU-NAME = ATmega328P
> info.GCC-Version = 4.3.2
> info.AVR-LibC-Ver = 1.6.4
> info.Compiled-date = Jan 4 2011
> info.Test-Suite-Name = ATS_StringMemoryTestPassByReference
> info.Free-memory = 1120 bytes
> Memory Usage (lost 59 bytes) ... FAIL
> --------------------------
> Ran 1 tests in 1.389s
>
> FAILED (failures=1)
>
>
> Example: Tom Igoe Memory Test
> info.MANUFACTURER = Arduino
> info.CPU-NAME = ATmega328P
> info.GCC-Version = 4.3.2
> info.AVR-LibC-Ver = 1.6.4
> info.Compiled-date = Jan 4 2011
> info.Test-Suite-Name = Tom Igoe Memory Test
> info.Free-memory = 1328 bytes
> Memory Usage (lost 9 bytes) ... FAIL
> --------------------------
> Ran 1 tests in 1.374s
>
> FAILED (failures=1)
>
>
>
> --Rick
>
> Tom, rewrote your example as a test.
>
> //************************************************************************
> //* Arduino Tom Igoe Memory Test
> //* (C) 2010 by Rick Anderson
> //* Open source as per standard Arduino code
> //*
> //************************************************************************
> //* Jan 4, 2011 Started on Tom Igoe Memory Test
> //************************************************************************
>
> #include "WProgram.h"
> #include "HardwareSerial.h"
> #include
>
> //************************************************************************
> void setup()
> {
> int startMemoryUsage;
> /*
> * Create variable for the tests.
> */
>
> String webColor = "#000000";
>
> int red = 1023/4;
> int blue = 512/4;
> int green = 128/4;
>
> /*
> * initiate the test run
> */
> //Record starting memory amount
> startMemoryUsage = ATS_GetFreeMemory();
> //Begin test run
> ATS_begin("Arduino", "Tom Igoe Memory Test");
>
> webColor = "#";
> webColor += String(red, HEX);
> webColor += String(green, HEX);
> webColor += String(blue, HEX);
>
> ATS_ReportMemoryUsage(startMemoryUsage);
>
> /*
> * Test complete
> */
>
> ATS_end();
> }
>
>
> //************************************************************************
> void loop()
> {
>
>
> }
>
>
>
>
> On Mon, Jan 3, 2011 at 9:35 PM, Tom Igoe <> wrote:
> > It broke in the non-SDM version too, but it took longer to break. In the
> SDM version it breaks immediately. So it looks like whatever you did
> highlights the faults sooner, which is good. It also points to a need for an
> error response of some sort, in answer to your question last mail.
> >
> > t.
> >
> > On Jan 3, 2011, at 4:44 PM, Alexander Brevig wrote:
> >
> >> That breaking of String, does it only occur with the SDM version?
> >>
> >> If not, did you find any way to break it? Maybe any of the old faults
> related to memory?
> >>
> >>
> >> I actually have no time to check this myself right now, so I opted to
> just ask you.
> >>
> >> On Mon, Jan 3, 2011 at 10:35 PM, Tom Igoe <> wrote:
> >> Thanks, Alexander, and sorry for the delay.
> >>
> >> A few tests:
> >>
> >> For code that doesn't change the strings much, there's not a big
> difference, a couple dozen bytes' difference in code size. However, when
> you start to do dynamic things, it does add up. For example, the
> StringAppendOperator example is 4910 bytes in 0022, and 5148 bytes with the
> StaticDynamicMemory version. So it does start to take its toll, memory-wise.
> >>
> >> On some sketches it actually takes less memory. For example, the one
> below is 3738 bytes using the StaticDynamicMemory version, and 3986 bytes in
> 0022. However, it fails entirely on upload. When the value of (analog 0)/4
> is high (0xFF), it never gets out of the setup(). So there's still a pretty
> easy way to break String, even with these improvements.
> >>
> >>
> >> void setup() {
> >> Serial.begin(9600);
> >> Serial.println("Beginning");
> >> }
> >>
> >> void loop() {
> >>
> >> String webColor = "#";
> >>
> >> int red = analogRead(A0)/4;
> >> webColor += String(red, HEX);
> >> int green = analogRead(A1)/4;
> >> webColor += String(green, HEX);
> >> int blue = analogRead(A2)/4;
> >>
> >> webColor += String(blue, HEX);
> >> Serial.println(webColor);
> >> }
> >>
> >>
> >>
> >>
> >>
> >> On Dec 16, 2010, at 1:27 AM, Alexander Brevig wrote:
> >>
> >> > Attached is a zip containing WString.h and .cpp plus
> StaticDynamicMemory.h.
> >> > Take a backup of the original WString files, and extract this zip into
> the hardware/arduino/cores/arduino folder.
> >> >
> >> > Now you're ready to test the modified String library, that does not
> fragment the heap.
> >> >
> >> >
> >> > In the WString header there is a #define called STRING_BUFFER which is
> set to 100 for now, change this to suit your test needs.
> >> >
> >> >
> >> > No error handling is implemented, what do you think we need?
> >> >
> >> > I plan to add an availableMemory():int method to the SDM library, and
> maybe some error flags and checks like hasError():int error
> >> >
> >> > I also suspect that this library is a bit slower performance wise, but
> I think that's just a cost we'll have to pay to being able to play with
> dynamic strings.
> >> >
> >> >
> >> > Hope to get feedback from someone!
> >> >
> >> > On Thu, Dec 16, 2010 at 1:11 AM, Alan Burlison <
> > wrote:
> >> > On 15/12/2010 16:19, David A. Mellis wrote:
> >> >
> >> > I think you're right, but I also don't think that telling people to
> >> > use the standard C library functions is a solution either. Trying out
> >> > this String class seems like one way of pushing forwards towards a
> >> > compromise that provides both an easy-to-use API and a robust
> >> > implementation. For example, perhaps the buffer sizes need to be
> >> > specified or provided when the String is instantiated. Or we need an
> >> > alternative implementation that does more reliable memory allocation
> >> > (since we're not assuming that the internal buffer is continuous).
> >> > Other ideas welcome.
> >> >
> >> > I think the problem is that the failure modes are not benign. I
> haven't been through all the use cases so this might not work, but perhaps
> using a statically-allocated string ("NOMEM" ?) as a sentinel value instead
> of null when malloc fails might be one way? Also, there might be some
> benefit in making String immutable a la Java - overloaded operators in C++
> have a tendency to generate anonymous temporaries, which is going to lead to
> heap fragmentation as well.
> >> >
> >> > --
> >> > Alan Burlison
> >> > --
> >> >
> >> > _______________________________________________
___________________________________________________

Posted on the Developers mailing list. Go to http://arduino.cc/mailman/listinfo/developers_arduino.cc to subscribe. Is this test suite any different than the one in the github repo?

t.

On Jan 4, 2011, at 12:53 PM, Rick Anderson wrote:

> I just created a test and unpacked and tested it. I also created a
> test based on Tom's code. Not sure I caught the maximum value error
> for 0xFF.
>
> I also ran the tests for bug 411. All the tests compile, but there is
> still memory loss.
>
> I'm attaching the Arduino Test suite, and the test code so you can run
> them as you debug. Let me know if this was helpful.
>
> --Rick
>
> Test run results:
> Example: ATS_StringAssignmentTest.pde
> info.MANUFACTURER = Arduino
> info.CPU-NAME = ATmega328P
> info.GCC-Version = 4.3.2
> info.AVR-LibC-Ver = 1.6.4
> info.Compiled-date = Jan 4 2011
> info.Test-Suite-Name = ATS_StringAssignmentTest
> info.Free-memory = 1110 bytes
> Memory Usage (lost 59 bytes) ... FAIL
> --------------------------
> Ran 1 tests in 1.378s
>
> FAILED (failures=1)
>
>
> Example: ATS_StringMemoryTestPassByReference.pde
>
> info.MANUFACTURER = Arduino
> info.CPU-NAME = ATmega328P
> info.GCC-Version = 4.3.2
> info.AVR-LibC-Ver = 1.6.4
> info.Compiled-date = Jan 4 2011
> info.Test-Suite-Name = ATS_StringMemoryTestPassByReference
> info.Free-memory = 1120 bytes
> Memory Usage (lost 59 bytes) ... FAIL
> --------------------------
> Ran 1 tests in 1.389s
>
> FAILED (failures=1)
>
>
> Example: Tom Igoe Memory Test
> info.MANUFACTURER = Arduino
> info.CPU-NAME = ATmega328P
> info.GCC-Version = 4.3.2
> info.AVR-LibC-Ver = 1.6.4
> info.Compiled-date = Jan 4 2011
> info.Test-Suite-Name = Tom Igoe Memory Test
> info.Free-memory = 1328 bytes
> Memory Usage (lost 9 bytes) ... FAIL
> --------------------------
> Ran 1 tests in 1.374s
>
> FAILED (failures=1)
>
>
>
> --Rick
>
> Tom, rewrote your example as a test.
>
> //************************************************************************
> //* Arduino Tom Igoe Memory Test
> //* (C) 2010 by Rick Anderson
> //* Open source as per standard Arduino code
> //*
> //************************************************************************
> //* Jan 4, 2011 Started on Tom Igoe Memory Test
> //************************************************************************
>
> #include "WProgram.h"
> #include "HardwareSerial.h"
> #include
>
> //************************************************************************
> void setup()
> {
> int startMemoryUsage;
> /*
> * Create variable for the tests.
> */
>
> String webColor = "#000000";
>
> int red = 1023/4;
> int blue = 512/4;
> int green = 128/4;
>
> /*
> * initiate the test run
> */
> //Record starting memory amount
> startMemoryUsage = ATS_GetFreeMemory();
> //Begin test run
> ATS_begin("Arduino", "Tom Igoe Memory Test");
>
> webColor = "#";
> webColor += String(red, HEX);
> webColor += String(green, HEX);
> webColor += String(blue, HEX);
>
> ATS_ReportMemoryUsage(startMemoryUsage);
>
> /*
> * Test complete
> */
>
> ATS_end();
> }
>
>
> //************************************************************************
> void loop()
> {
>
>
> }
>
>
>
>
> On Mon, Jan 3, 2011 at 9:35 PM, Tom Igoe <> wrote:
>> It broke in the non-SDM version too, but it took longer to break. In the SDM version it breaks immediately. So it looks like whatever you did highlights the faults sooner, which is good. It also points to a need for an error response of some sort, in answer to your question last mail.
>>
>> t.
>>
>> On Jan 3, 2011, at 4:44 PM, Alexander Brevig wrote:
>>
>>> That breaking of String, does it only occur with the SDM version?
>>>
>>> If not, did you find any way to break it? Maybe any of the old faults related to memory?
>>>
>>>
>>> I actually have no time to check this myself right now, so I opted to just ask you.
>>>
>>> On Mon, Jan 3, 2011 at 10:35 PM, Tom Igoe <> wrote:
>>> Thanks, Alexander, and sorry for the delay.
>>>
>>> A few tests:
>>>
>>> For code that doesn't change the strings much, there's not a big difference, a couple dozen bytes' difference in code size. However, when you start to do dynamic things, it does add up. For example, the StringAppendOperator example is 4910 bytes in 0022, and 5148 bytes with the StaticDynamicMemory version. So it does start to take its toll, memory-wise.
>>>
>>> On some sketches it actually takes less memory. For example, the one below is 3738 bytes using the StaticDynamicMemory version, and 3986 bytes in 0022. However, it fails entirely on upload. When the value of (analog 0)/4 is high (0xFF), it never gets out of the setup(). So there's still a pretty easy way to break String, even with these improvements.
>>>
>>>
>>> void setup() {
>>> Serial.begin(9600);
>>> Serial.println("Beginning");
>>> }
>>>
>>> void loop() {
>>>
>>> String webColor = "#";
>>>
>>> int red = analogRead(A0)/4;
>>> webColor += String(red, HEX);
>>> int green = analogRead(A1)/4;
>>> webColor += String(green, HEX);
>>> int blue = analogRead(A2)/4;
>>>
>>> webColor += String(blue, HEX);
>>> Serial.println(webColor);
>>> }
>>>
>>>
>>>
>>>
>>>
>>> On Dec 16, 2010, at 1:27 AM, Alexander Brevig wrote:
>>>
>>>> Attached is a zip containing WString.h and .cpp plus StaticDynamicMemory.h.
>>>> Take a backup of the original WString files, and extract this zip into the hardware/arduino/cores/arduino folder.
>>>>
>>>> Now you're ready to test the modified String library, that does not fragment the heap.
>>>>
>>>>
>>>> In the WString header there is a #define called STRING_BUFFER which is set to 100 for now, change this to suit your test needs.
>>>>
>>>>
>>>> No error handling is implemented, what do you think we need?
>>>>
>>>> I plan to add an availableMemory():int method to the SDM library, and maybe some error flags and checks like hasError():int error
>>>>
>>>> I also suspect that this library is a bit slower performance wise, but I think that's just a cost we'll have to pay to being able to play with dynamic strings.
>>>>
>>>>
>>>> Hope to get feedback from someone!
>>>>
>>>> On Thu, Dec 16, 2010 at 1:11 AM, Alan Burlison <> wrote:
>>>> On 15/12/2010 16:19, David A. Mellis wrote:
>>>>
>>>> I think you're right, but I also don't think that telling people to
>>>> use the standard C library functions is a solution either. Trying out
>>>> this String class seems like one way of pushing forwards towards a
>>>> compromise that provides both an easy-to-use API and a robust
>>>> implementation. For example, perhaps the buffer sizes need to be
>>>> specified or provided when the String is instantiated. Or we need an
>>>> alternative implementation that does more reliable memory allocation
>>>> (since we're not assuming that the internal buffer is continuous).
>>>> Other ideas welcome.
>>>>
>>>> I think the problem is that the failure modes are not benign. I haven't been through all the use cases so this might not work, but perhaps using a statically-allocated string ("NOMEM" ?) as a sentinel value instead of null when malloc fails might be one way? Also, there might be some benefit in making String immutable a la Java - overloaded operators in C++ have a tendency to generate anonymous temporaries, which is going to lead to heap fragmentation as well.
>>>>
>>>> --
>>>> Alan Burlison
>>>> --
>>>>
>>>> _______________________________________________
___________________________________________________

Posted on the Developers mailing list. Go to http://arduino.cc/mailman/listinfo/developers_arduino.cc to subscribe. Same exact one. I just included it just in case.

--Rick

On Tue, Jan 4, 2011 at 9:01 PM, Tom Igoe <> wrote:
> Is this test suite any different than the one in the github repo?
>
> t.
>
> On Jan 4, 2011, at 12:53 PM, Rick Anderson wrote:
>
>> I just created a test and unpacked and tested it. I also created a
>> test based on Tom's code. Not sure I caught the maximum value error
>> for 0xFF.
>>
>> I also ran the tests for bug 411. All the tests compile, but there is
>> still memory loss.
>>
>> I'm attaching the Arduino Test suite, and the test code so you can run
>> them as you debug. Let me know if this was helpful.
>>
>> --Rick
>>
>> Test run results:
>> Example:  ATS_StringAssignmentTest.pde
>> info.MANUFACTURER    = Arduino
>> info.CPU-NAME        = ATmega328P
>> info.GCC-Version     = 4.3.2
>> info.AVR-LibC-Ver    = 1.6.4
>> info.Compiled-date   = Jan  4 2011
>> info.Test-Suite-Name = ATS_StringAssignmentTest
>> info.Free-memory     = 1110 bytes
>> Memory Usage (lost 59 bytes)                                ... FAIL
>> --------------------------
>> Ran 1 tests in 1.378s
>>
>> FAILED (failures=1)
>>
>>
>> Example: ATS_StringMemoryTestPassByReference.pde
>>
>> info.MANUFACTURER    = Arduino
>> info.CPU-NAME        = ATmega328P
>> info.GCC-Version     = 4.3.2
>> info.AVR-LibC-Ver    = 1.6.4
>> info.Compiled-date   = Jan  4 2011
>> info.Test-Suite-Name = ATS_StringMemoryTestPassByReference
>> info.Free-memory     = 1120 bytes
>> Memory Usage (lost 59 bytes)                                ... FAIL
>> --------------------------
>> Ran 1 tests in 1.389s
>>
>> FAILED (failures=1)
>>
>>
>> Example: Tom Igoe Memory Test
>> info.MANUFACTURER    = Arduino
>> info.CPU-NAME        = ATmega328P
>> info.GCC-Version     = 4.3.2
>> info.AVR-LibC-Ver    = 1.6.4
>> info.Compiled-date   = Jan  4 2011
>> info.Test-Suite-Name = Tom Igoe Memory Test
>> info.Free-memory     = 1328 bytes
>> Memory Usage (lost 9 bytes)                                 ... FAIL
>> --------------------------
>> Ran 1 tests in 1.374s
>>
>> FAILED (failures=1)
>>
>>
>>
>> --Rick
>>
>> Tom, rewrote your example as a test.
>>
>> //************************************************************************
>> //*   Arduino Tom Igoe Memory Test
>> //*           (C) 2010 by Rick Anderson
>> //*           Open source as per standard Arduino code
>> //*
>> //************************************************************************
>> //*   Jan 4,  2011     Started on Tom Igoe Memory Test
>> //************************************************************************
>>
>> #include      "WProgram.h"
>> #include      "HardwareSerial.h"
>> #include      
>>
>> //************************************************************************
>> void setup()
>> {
>>  int          startMemoryUsage;
>>  /*
>>    * Create variable for the tests.
>>   */
>>
>>  String webColor = "#000000";
>>
>>  int red = 1023/4;
>>  int blue = 512/4;
>>  int green = 128/4;
>>
>>  /*
>>  * initiate the test run
>>   */
>>  //Record starting memory amount
>>  startMemoryUsage     =       ATS_GetFreeMemory();
>>  //Begin test run
>>  ATS_begin("Arduino", "Tom Igoe Memory Test");
>>
>>  webColor = "#";
>>  webColor += String(red, HEX);
>>  webColor += String(green, HEX);
>>  webColor += String(blue, HEX);
>>
>>  ATS_ReportMemoryUsage(startMemoryUsage);
>>
>>  /*
>>   * Test complete
>>   */
>>
>>  ATS_end();
>> }
>>
>>
>> //************************************************************************
>> void loop()
>> {
>>
>>
>> }
>>
>>
>>
>>
>> On Mon, Jan 3, 2011 at 9:35 PM, Tom Igoe <> wrote:
>>> It broke in the non-SDM version too, but it took longer to break. In the SDM version it breaks immediately. So it looks like whatever you did highlights the faults sooner, which is good. It also points to a need for an error response of some sort, in answer to your question last mail.
>>>
>>> t.
>>>
>>> On Jan 3, 2011, at 4:44 PM, Alexander Brevig wrote:
>>>
>>>> That breaking of String, does it only occur with the SDM version?
>>>>
>>>> If not, did you find any way to break it? Maybe any of the old faults related to memory?
>>>>
>>>>
>>>> I actually have no time to check this myself right now, so I opted to just ask you.
>>>>
>>>> On Mon, Jan 3, 2011 at 10:35 PM, Tom Igoe <> wrote:
>>>> Thanks, Alexander, and sorry for the delay.
>>>>
>>>> A few tests:
>>>>
>>>> For code that doesn't change the strings much, there's not a big difference, a couple dozen bytes' difference in code size.  However, when you start to do dynamic things, it does add up.  For example, the StringAppendOperator example is  4910 bytes in 0022, and 5148 bytes with the StaticDynamicMemory version. So it does start to take its toll, memory-wise.
>>>>
>>>> On some sketches it actually takes less memory.  For example, the one below is 3738 bytes using the StaticDynamicMemory version, and 3986 bytes in 0022.  However, it fails entirely on upload.  When the value of (analog 0)/4 is high (0xFF), it never gets out of the setup(). So there's still a pretty easy way to break String, even with these improvements.
>>>>
>>>>
>>>> void setup() {
>>>>  Serial.begin(9600);
>>>>  Serial.println("Beginning");
>>>> }
>>>>
>>>> void loop() {
>>>>
>>>>  String webColor = "#";
>>>>
>>>>  int red = analogRead(A0)/4;
>>>>  webColor += String(red, HEX);
>>>>  int green = analogRead(A1)/4;
>>>>  webColor += String(green, HEX);
>>>>  int blue = analogRead(A2)/4;
>>>>
>>>>  webColor += String(blue, HEX);
>>>>  Serial.println(webColor);
>>>> }
>>>>
>>>>
>>>>
>>>>
>>>>
>>>> On Dec 16, 2010, at 1:27 AM, Alexander Brevig wrote:
>>>>
>>>>> Attached is a zip containing WString.h and .cpp plus StaticDynamicMemory.h.
>>>>> Take a backup of the original WString files, and extract this zip into the hardware/arduino/cores/arduino folder.
>>>>>
>>>>> Now you're ready to test the modified String library, that does not fragment the heap.
>>>>>
>>>>>
>>>>> In the WString header there is a #define called STRING_BUFFER which is set to 100 for now, change this to suit your test needs.
>>>>>
>>>>>
>>>>> No error handling is implemented, what do you think we need?
>>>>>
>>>>> I plan to add an availableMemory():int method to the SDM library, and maybe some error flags and checks like hasError():int error
>>>>>
>>>>> I also suspect that this library is a bit slower performance wise, but I think that's just a cost we'll have to pay to being able to play with dynamic strings.
>>>>>
>>>>>
>>>>> Hope to  get feedback from someone!
>>>>>
>>>>> On Thu, Dec 16, 2010 at 1:11 AM, Alan Burlison <> wrote:
>>>>> On 15/12/2010 16:19, David A. Mellis wrote:
>>>>>
>>>>> I think you're right, but I also don't think that telling people to
>>>>> use the standard C library functions is a solution either.  Trying out
>>>>> this String class seems like one way of pushing forwards towards a
>>>>> compromise that provides both an easy-to-use API and a robust
>>>>> implementation.  For example, perhaps the buffer sizes need to be
>>>>> specified or provided when the String is instantiated.  Or we need an
>>>>> alternative implementation that does more reliable memory allocation
>>>>> (since we're not assuming that the internal buffer is continuous).
>>>>> Other ideas welcome.
>>>>>
>>>>> I think the problem is that the failure modes are not benign.  I haven't been through all the use cases so this might not work, but perhaps using a statically-allocated string ("NOMEM" ?) as a sentinel value instead of null when malloc fails might be one way?  Also, there might be some benefit in making String immutable a la Java - overloaded operators in C++ have a tendency to generate anonymous temporaries, which is going to lead to heap fragmentation as well.
>>>>>
>>>>> --
>>>>> Alan Burlison
>>>>> --
>>>>>
>>>>> _______________________________________________
___________________________________________________

Posted on the Developers mailing list. Go to http://arduino.cc/mailman/listinfo/developers_arduino.cc to subscribe. On 04/01/2011 17:53, Rick Anderson wrote:

> I also ran the tests for bug 411. All the tests compile, but there is
> still memory loss.

Most of the assumptions made by the test harness and test case code are
wrong, any reports of 'lost' memory are therefore likely to be wrong as
well. If you want to do leak detection you can't do it in the naive way
it is being done at present.

--
Alan Burlison
--

_______________________________________________
___________________________________________________

Posted on the Developers mailing list. Go to http://arduino.cc/mailman/listinfo/developers_arduino.cc to subscribe. Alan,

The tests themselves are quick and dirty, and not strategic or
comprehensive. I'd like your input to create a good procedure for
memory testing. I also have feedback from Paul Stoffregen for the test
suite:
----
Another problem involves gcc's optimizer ignoring the inline request
for ATS_ReportMemoryUsage. As the comment in the code explains, it
must be inline to avoid measuring its own stack frame. I believe
adding this line in ArduinoTestSuite.h fixes the problem by forcing
gcc to inline.

inline void ATS_ReportMemoryUsage(int _memoryUsageAtStart)
__attribute__((always_inline, unused));

The last problem is a tiny bit of dynamic memory permanently held for
the free list. To allow for this, the test really should call
malloc() and free() once, so the allocator is fully initialized before
testing.
----

I'd like to combine both sets of feedback, and set up some issues in
the system, then fix them. Is the above the problem you saw? Are their
other assumptions that would impact measuring memory? And updating the
memory test in the the test suite.

In terms of creating tests for memory leaks. It looks best to move all
the memory usage inside a function. What else could be done to
constrain the problem, and measuring more affectively.

I'm traveling back to NJ today, so I can't respond right away.

--Rick

On Wed, Jan 5, 2011 at 8:52 AM, Alan Burlison <> wrote:
> On 04/01/2011 17:53, Rick Anderson wrote:
>
>> I also ran the tests for bug 411. All the tests compile, but there is
>> still memory loss.
>
> Most of the assumptions made by the test harness and test case code are
> wrong, any reports of 'lost' memory are therefore likely to be wrong as
> well.  If you want to do leak detection you can't do it in the naive way it
> is being done at present.
>
> --
> Alan Burlison
> --
>



--
President
Fair Use Building and Research (****) Labs
http://fubarlabs.org

_______________________________________________
___________________________________________________

Posted on the Developers mailing list. Go to http://arduino.cc/mailman/listinfo/developers_arduino.cc to subscribe. On 05/01/2011 15:19, Rick Anderson wrote:

> ----
> Another problem involves gcc's optimizer ignoring the inline request
> for ATS_ReportMemoryUsage. As the comment in the code explains, it
> must be inline to avoid measuring its own stack frame. I believe
> adding this line in ArduinoTestSuite.h fixes the problem by forcing
> gcc to inline.
>
> inline void ATS_ReportMemoryUsage(int _memoryUsageAtStart)
> __attribute__((always_inline, unused));

Yes, that's one of the problems. And even the __attribute__
'workaround' is a fragile hack.

> The last problem is a tiny bit of dynamic memory permanently held for
> the free list. To allow for this, the test really should call
> malloc() and free() once, so the allocator is fully initialized before

That's part of a problem, but an initial call malloc/free call isn't
guaranteed to make all the issues go away either. From looking at the
avr-libc malloc implementation it does try to coalesce the heap, but
relying on multiple malloc implementation artefacts is a really bad idea
- there's no guarantee that future malloc implementations will always
coalesce on every free, and there's no guarantee that __bss_end or
__brkval will always be adjusted on each malloc/free call.

The other issue is that of object lifetimes. The test code has
instances of String objects which are allocated on the stack and that
are still in scope when the 'leak' memory check is performed. That
means the String destructors won't have been called and the dynamically
allocated part of the String will still be allocated.

A true memory leak is a block of allocated memory that has no references
to it. However that's not what the test code is checking for. If a
library routine used malloc to perform a one-time library-private buffer
allocation where the buffer is retained for the lifetime of the program,
the current leak checking would incorrectly report that as a leak. It
isn't a leak because there's still a reference to the block inside the
library.

The only semi-reliable way to do what you want is to use an instrumented
malloc implementation, and that's going to be very difficult to
implement on a constrained platform such as the AVR. If you want to
test the String implementation for leaks, my advice is to do it on a
more capable platform (e.g. *nix) and use one of the many instrumented
mallocs that are available.

--
Alan Burlison
--

_______________________________________________
___________________________________________________

Posted on the Developers mailing list. Go to http://arduino.cc/mailman/listinfo/developers_arduino.cc to subscribe. Slightly unrelated to what you guys are discussing now but:
I'm not sure if I've made this clear, but the new version of String that I'm
working on now does not use malloc or any other c function for dynamic
memory. What happens is that I allocate memory statically on the stack and
serve that memory dynamically to the instances of String.

I have some time on my hands now and have a look at getting the += not to
break the code

On Wed, Jan 5, 2011 at 7:10 PM, Alan Burlison <>wrote:

> On 05/01/2011 15:19, Rick Anderson wrote:
>
> ----
>> Another problem involves gcc's optimizer ignoring the inline request
>> for ATS_ReportMemoryUsage. As the comment in the code explains, it
>> must be inline to avoid measuring its own stack frame. I believe
>> adding this line in ArduinoTestSuite.h fixes the problem by forcing
>> gcc to inline.
>>
>> inline void ATS_ReportMemoryUsage(int _memoryUsageAtStart)
>> __attribute__((always_inline, unused));
>>
>
> Yes, that's one of the problems. And even the __attribute__ 'workaround'
> is a fragile hack.
>
>
> The last problem is a tiny bit of dynamic memory permanently held for
>> the free list. To allow for this, the test really should call
>> malloc() and free() once, so the allocator is fully initialized before
>>
>
> That's part of a problem, but an initial call malloc/free call isn't
> guaranteed to make all the issues go away either. From looking at the
> avr-libc malloc implementation it does try to coalesce the heap, but relying
> on multiple malloc implementation artefacts is a really bad idea - there's
> no guarantee that future malloc implementations will always coalesce on
> every free, and there's no guarantee that __bss_end or __brkval will always
> be adjusted on each malloc/free call.
>
> The other issue is that of object lifetimes. The test code has instances
> of String objects which are allocated on the stack and that are still in
> scope when the 'leak' memory check is performed. That means the String
> destructors won't have been called and the dynamically allocated part of the
> String will still be allocated.
>
> A true memory leak is a block of allocated memory that has no references to
> it. However that's not what the test code is checking for. If a library
> routine used malloc to perform a one-time library-private buffer allocation
> where the buffer is retained for the lifetime of the program, the current
> leak checking would incorrectly report that as a leak. It isn't a leak
> because there's still a reference to the block inside the library.
>
> The only semi-reliable way to do what you want is to use an instrumented
> malloc implementation, and that's going to be very difficult to implement on
> a constrained platform such as the AVR. If you want to test the String
> implementation for leaks, my advice is to do it on a more capable platform
> (e.g. *nix) and use one of the many instrumented mallocs that are available.
>
> --
> Alan Burlison
> --
>
>
> _______________________________________________
___________________________________________________

Posted on the Developers mailing list. Go to http://arduino.cc/mailman/listinfo/developers_arduino.cc to subscribe. On 05/01/2011 18:25, Alexander Brevig wrote:

> Slightly unrelated to what you guys are discussing now but:
> I'm not sure if I've made this clear, but the new version of String that I'm
> working on now does not use malloc or any other c function for dynamic
> memory. What happens is that I allocate memory statically on the stack and
> serve that memory dynamically to the instances of String.

Does that mean that the total space occupied by all Strings has to be
decided up front? If so, what is the behaviour when an allocation fails?

To be honest I don't really see the point of doing this - all you are
doing is re-implementing malloc.

--
Alan Burlison
--

_______________________________________________
___________________________________________________

Posted on the Developers mailing list. Go to http://arduino.cc/mailman/listinfo/developers_arduino.cc to subscribe. No, actually I am not reimplementing malloc, because my algorithm guarantees
no fragmentation and always 100% effective use of the allocated memory.

"Does that mean that the total space occupied by all Strings has to be
decided up front? "
Yes, just like the buffer for the serial ++

I know I would opt to have the restriction for a predetermined allocated
space WITH error reporting (how we do is up to you guys, feed me with ideas
I'll implement whatever we agree is best) than having
seemingly infinite memory that crashes and burns.

On Wed, Jan 5, 2011 at 7:33 PM, Alan Burlison <>wrote:

> On 05/01/2011 18:25, Alexander Brevig wrote:
>
> Slightly unrelated to what you guys are discussing now but:
>> I'm not sure if I've made this clear, but the new version of String that
>> I'm
>> working on now does not use malloc or any other c function for dynamic
>> memory. What happens is that I allocate memory statically on the stack and
>> serve that memory dynamically to the instances of String.
>>
>
> Does that mean that the total space occupied by all Strings has to be
> decided up front? If so, what is the behaviour when an allocation fails?
>
> To be honest I don't really see the point of doing this - all you are doing
> is re-implementing malloc.
>
> --
> Alan Burlison
> --
> Well, that was easy (seemingly, probably just jinxed myself...) but here the
test does no longer break, and the usage of memory never exceeds 11 bytes.

It would be awesome if someone would test it.


Also, please tell me now if this effort will lead to nowhere. Is the cost of
being constrained to a buffer size a deal-breaker?

On Wed, Jan 5, 2011 at 7:42 PM, Alexander Brevig
<>wrote:

> No, actually I am not reimplementing malloc, because my algorithm
> guarantees no fragmentation and always 100% effective use of the allocated
> memory.
>
> "Does that mean that the total space occupied by all Strings has to be
> decided up front? "
> Yes, just like the buffer for the serial ++
>
> I know I would opt to have the restriction for a predetermined allocated
> space WITH error reporting (how we do is up to you guys, feed me with ideas
> I'll implement whatever we agree is best) than having
> seemingly infinite memory that crashes and burns.
>
> On Wed, Jan 5, 2011 at 7:33 PM, Alan Burlison <>wrote:
>
>> On 05/01/2011 18:25, Alexander Brevig wrote:
>>
>> Slightly unrelated to what you guys are discussing now but:
>>> I'm not sure if I've made this clear, but the new version of String that
>>> I'm
>>> working on now does not use malloc or any other c function for dynamic
>>> memory. What happens is that I allocate memory statically on the stack
>>> and
>>> serve that memory dynamically to the instances of String.
>>>
>>
>> Does that mean that the total space occupied by all Strings has to be
>> decided up front? If so, what is the behaviour when an allocation fails?
>>
>> To be honest I don't really see the point of doing this - all you are
>> doing is re-implementing malloc.
>>
>> --
>> Alan Burlison
>> --
>>
>
> So sorry you all! I shipped my test code (for msvc++ compiler) in five
minutes I'll post an arduino compatible version. So sorry for this spam!

On Wed, Jan 5, 2011 at 8:01 PM, Alexander Brevig
<>wrote:

> Well, that was easy (seemingly, probably just jinxed myself...) but here
> the test does no longer break, and the usage of memory never exceeds 11
> bytes.
>
> It would be awesome if someone would test it.
>
>
> Also, please tell me now if this effort will lead to nowhere. Is the cost
> of being constrained to a buffer size a deal-breaker?
>
>
> On Wed, Jan 5, 2011 at 7:42 PM, Alexander Brevig <
> > wrote:
>
>> No, actually I am not reimplementing malloc, because my algorithm
>> guarantees no fragmentation and always 100% effective use of the allocated
>> memory.
>>
>> "Does that mean that the total space occupied by all Strings has to be
>> decided up front? "
>> Yes, just like the buffer for the serial ++
>>
>> I know I would opt to have the restriction for a predetermined allocated
>> space WITH error reporting (how we do is up to you guys, feed me with ideas
>> I'll implement whatever we agree is best) than having
>> seemingly infinite memory that crashes and burns.
>>
>> On Wed, Jan 5, 2011 at 7:33 PM, Alan Burlison <>wrote:
>>
>>> On 05/01/2011 18:25, Alexander Brevig wrote:
>>>
>>> Slightly unrelated to what you guys are discussing now but:
>>>> I'm not sure if I've made this clear, but the new version of String that
>>>> I'm
>>>> working on now does not use malloc or any other c function for dynamic
>>>> memory. What happens is that I allocate memory statically on the stack
>>>> and
>>>> serve that memory dynamically to the instances of String.
>>>>
>>>
>>> Does that mean that the total space occupied by all Strings has to be
>>> decided up front? If so, what is the behaviour when an allocation fails?
>>>
>>> To be honest I don't really see the point of doing this - all you are
>>> doing is re-implementing malloc.
>>>
>>> --
>>> Alan Burlison
>>> --
>>>
>>
>>
> > The other issue is that of object lifetimes. The test code has
> instances of String objects which are allocated on the stack and that
> are still in scope when the 'leak' memory check is performed.

That was also in my (off list) email a few days ago, though that bit
didn't make it here.

I believe the plan is to move the tests and object(s) they use to a
function, so the objects will be out of scope when the memory check is made.

There might also another copy of the test which pre-allocates a string
large enough to hold all the data. I'm not sure exactly how I feel
about that approach, but it seems like at least worth trying. Currently
the string library does not have a reserve() function. I've proposed it
before, and today I put it in issue #449.

> If a library routine used malloc to perform a one-time library-private
> buffer allocation where the buffer is retained for the lifetime of the
> program, the current leak checking would incorrectly report that as a
> leak. It isn't a leak because there's still a reference to the block
> inside the library.

Yes, you are correct, the test makes some assumptions about the internal
implementation, and yes, an ideal test wouldn't make any such
assumptions, and yes, it's probably impractical to completely avoid
assumptions on such limited hardware.

But there's a lot of value in actually testing on the real hardware,
with all its limitations and slight differences from running on a PC.
Personally, I think making some assumptions is a pretty good trade-off
for testing in the actual environment. Of course, there's plenty of
room for smart ideas to minimize such assumptions, or perhaps test in
multiple ways.

As someone who's spent a lot of time coding on the string class (and has
more planned), the real value isn't a perfect score if my code is bug
free, but rather a FAIL coming up when I make some mistake that
unexpectedly breaks something. Sure it's annoying if a FAIL comes up
erroneously because the internal implementation changed,

There are so many functions, with so many cases, that subtle errors can
happen (eg, does lastIndexOf work when the search string is the entire
original string... I broke that recently, but everything else worked.....)

If you have ideas about how to catch more types of errors, even if
imperfect, I'd really love to hear.




>
>
> The only semi-reliable way to do what you want is to use an
> instrumented malloc implementation, and that's going to be very
> difficult to implement on a constrained platform such as the AVR. If
> you want to test the String implementation for leaks, my advice is to
> do it on a more capable platform (e.g. *nix) and use one of the many
> instrumented mallocs that are available.
>


_______________________________________________
___________________________________________________

Posted on the Developers mailing list. Go to http://arduino.cc/mailman/listinfo/developers_arduino.cc to subscribe. I'm not sure I follow, string.read(); what would that do?
How do you imagine String to use Stream ? :)

Attached: new version arduino compitable

On Wed, Jan 5, 2011 at 8:20 PM, Tom Igoe <> wrote:

> Could you then just use Stream as a basis for String? Sorry, I didn't look
> into the details of your DMA class, but as long as we're setting a limit to
> begin with, and if we know Stream's pretty solid, why not restructure String
> a bit to use it?
>
> t.
>
>
> On Jan 5, 2011, at 1:42 PM, Alexander Brevig wrote:
>
> > No, actually I am not reimplementing malloc, because my algorithm
> guarantees no fragmentation and always 100% effective use of the allocated
> memory.
> >
> > "Does that mean that the total space occupied by all Strings has to be
> decided up front? "
> > Yes, just like the buffer for the serial ++
> >
> > I know I would opt to have the restriction for a predetermined allocated
> space WITH error reporting (how we do is up to you guys, feed me with ideas
> I'll implement whatever we agree is best) than having seemingly infinite
> memory that crashes and burns.
> >
> > On Wed, Jan 5, 2011 at 7:33 PM, Alan Burlison <>
> wrote:
> > On 05/01/2011 18:25, Alexander Brevig wrote:
> >
> > Slightly unrelated to what you guys are discussing now but:
> > I'm not sure if I've made this clear, but the new version of String that
> I'm
> > working on now does not use malloc or any other c function for dynamic
> > memory. What happens is that I allocate memory statically on the stack
> and
> > serve that memory dynamically to the instances of String.
> >
> > Does that mean that the total space occupied by all Strings has to be
> decided up front? If so, what is the behaviour when an allocation fails?
> >
> > To be honest I don't really see the point of doing this - all you are
> doing is re-implementing malloc.
> >
> > --
> > Alan Burlison
> > --
> >
> > _______________________________________________
___________________________________________________

Posted on the Developers mailing list. Go to http://arduino.cc/mailman/listinfo/developers_arduino.cc to subscribe. > I'm not sure I follow, string.read(); what would that do?
> How do you imagine String to use Stream ? :)

I also do not understand? In fact, I'm completely mystified. Please
explain...

But I would like to let you know I've been working on debugging the
string class, and in the last few days together with the test suite.
I'll likely post code sometimes next week.


>
> Attached: new version arduino compitable
>
> On Wed, Jan 5, 2011 at 8:20 PM, Tom Igoe <
> > wrote:
>
> Could you then just use Stream as a basis for String? Sorry, I
> didn't look into the details of your DMA class, but as long as
> we're setting a limit to begin with, and if we know Stream's
> pretty solid, why not restructure String a bit to use it?
>
> t.
>
>
> On Jan 5, 2011, at 1:42 PM, Alexander Brevig wrote:
>
> > No, actually I am not reimplementing malloc, because my
> algorithm guarantees no fragmentation and always 100% effective
> use of the allocated memory.
> >
> > "Does that mean that the total space occupied by all Strings has
> to be decided up front? "
> > Yes, just like the buffer for the serial ++
> >
> > I know I would opt to have the restriction for a predetermined
> allocated space WITH error reporting (how we do is up to you guys,
> feed me with ideas I'll implement whatever we agree is best) than
> having seemingly infinite memory that crashes and burns.
> >
> > On Wed, Jan 5, 2011 at 7:33 PM, Alan Burlison
> < > wrote:
> > On 05/01/2011 18:25, Alexander Brevig wrote:
> >
> > Slightly unrelated to what you guys are discussing now but:
> > I'm not sure if I've made this clear, but the new version of
> String that I'm
> > working on now does not use malloc or any other c function for
> dynamic
> > memory. What happens is that I allocate memory statically on the
> stack and
> > serve that memory dynamically to the instances of String.
> >
> > Does that mean that the total space occupied by all Strings has
> to be decided up front? If so, what is the behaviour when an
> allocation fails?
> >
> > To be honest I don't really see the point of doing this - all
> you are doing is re-implementing malloc.
> >
> > --
> > Alan Burlison
> > --
> >
> > _______________________________________________
___________________________________________________

Posted on the Developers mailing list. Go to http://arduino.cc/mailman/listinfo/developers_arduino.cc to subscribe. I'm very interested to see if one of your tests break the new version of the
String class Paul! the version with _3. If you manage to break it I'll shut
up about statically allocating a buffer forever, until then I'll probably
try to push for at least some more time :)

+1 internet to the one who first breaks the new lib, -1 for me (and I
promise, this is the first and last time I gamble in internets)

On Wed, Jan 5, 2011 at 8:09 PM, Paul Stoffregen <> wrote:

>
> The other issue is that of object lifetimes. The test code has instances
>> of String objects which are allocated on the stack and that are still in
>> scope when the 'leak' memory check is performed.
>>
>
> That was also in my (off list) email a few days ago, though that bit didn't
> make it here.
>
> I believe the plan is to move the tests and object(s) they use to a
> function, so the objects will be out of scope when the memory check is made.
>
> There might also another copy of the test which pre-allocates a string
> large enough to hold all the data. I'm not sure exactly how I feel about
> that approach, but it seems like at least worth trying. Currently the
> string library does not have a reserve() function. I've proposed it before,
> and today I put it in issue #449.
>
>
> If a library routine used malloc to perform a one-time library-private
>> buffer allocation where the buffer is retained for the lifetime of the
>> program, the current leak checking would incorrectly report that as a leak.
>> It isn't a leak because there's still a reference to the block inside the
>> library.
>>
>
> Yes, you are correct, the test makes some assumptions about the internal
> implementation, and yes, an ideal test wouldn't make any such assumptions,
> and yes, it's probably impractical to completely avoid assumptions on such
> limited hardware.
>
> But there's a lot of value in actually testing on the real hardware, with
> all its limitations and slight differences from running on a PC.
> Personally, I think making some assumptions is a pretty good trade-off for
> testing in the actual environment. Of course, there's plenty of room for
> smart ideas to minimize such assumptions, or perhaps test in multiple ways.
>
> As someone who's spent a lot of time coding on the string class (and has
> more planned), the real value isn't a perfect score if my code is bug free,
> but rather a FAIL coming up when I make some mistake that unexpectedly
> breaks something. Sure it's annoying if a FAIL comes up erroneously because
> the internal implementation changed,
>
> There are so many functions, with so many cases, that subtle errors can
> happen (eg, does lastIndexOf work when the search string is the entire
> original string... I broke that recently, but everything else worked.....)
>
> If you have ideas about how to catch more types of errors, even if
> imperfect, I'd really love to hear.
>
>
>
>
>
>
>>
>> The only semi-reliable way to do what you want is to use an instrumented
>> malloc implementation, and that's going to be very difficult to implement on
>> a constrained platform such as the AVR. If you want to test the String
>> implementation for leaks, my advice is to do it on a more capable platform
>> (e.g. *nix) and use one of the many instrumented mallocs that are available.
>>
>>
>
> _______________________________________________
___________________________________________________

Posted on the Developers mailing list. Go to http://arduino.cc/mailman/listinfo/developers_arduino.cc to subscribe.

  #18  
06-01-2011 01:08 AM
Developers member admin is online now
User
 

That breaking of String, does it only occur with the SDM version?

If not, did you find any way to break it? Maybe any of the old faults
related to memory?


I actually have no time to check this myself right now, so I opted to just
ask you.

On Mon, Jan 3, 2011 at 10:35 PM, Tom Igoe <> wrote:

> Thanks, Alexander, and sorry for the delay.
>
> A few tests:
>
> For code that doesn't change the strings much, there's not a big
> difference, a couple dozen bytes' difference in code size. However, when
> you start to do dynamic things, it does add up. For example, the
> StringAppendOperator example is 4910 bytes in 0022, and 5148 bytes with the
> StaticDynamicMemory version. So it does start to take its toll, memory-wise.
>
> On some sketches it actually takes less memory. For example, the one below
> is 3738 bytes using the StaticDynamicMemory version, and 3986 bytes in 0022.
> However, it fails entirely on upload. When the value of (analog 0)/4 is
> high (0xFF), it never gets out of the setup(). So there's still a pretty
> easy way to break String, even with these improvements.
>
>
> void setup() {
> Serial.begin(9600);
> Serial.println("Beginning");
> }
>
> void loop() {
>
> String webColor = "#";
>
> int red = analogRead(A0)/4;
> webColor += String(red, HEX);
> int green = analogRead(A1)/4;
> webColor += String(green, HEX);
> int blue = analogRead(A2)/4;
>
> webColor += String(blue, HEX);
> Serial.println(webColor);
> }
>
>
>
>
>
> On Dec 16, 2010, at 1:27 AM, Alexander Brevig wrote:
>
> > Attached is a zip containing WString.h and .cpp plus
> StaticDynamicMemory.h.
> > Take a backup of the original WString files, and extract this zip into
> the hardware/arduino/cores/arduino folder.
> >
> > Now you're ready to test the modified String library, that does not
> fragment the heap.
> >
> >
> > In the WString header there is a #define called STRING_BUFFER which is
> set to 100 for now, change this to suit your test needs.
> >
> >
> > No error handling is implemented, what do you think we need?
> >
> > I plan to add an availableMemory():int method to the SDM library, and
> maybe some error flags and checks like hasError():int error
> >
> > I also suspect that this library is a bit slower performance wise, but I
> think that's just a cost we'll have to pay to being able to play with
> dynamic strings.
> >
> >
> > Hope to get feedback from someone!
> >
> > On Thu, Dec 16, 2010 at 1:11 AM, Alan Burlison <>
> wrote:
> > On 15/12/2010 16:19, David A. Mellis wrote:
> >
> > I think you're right, but I also don't think that telling people to
> > use the standard C library functions is a solution either. Trying out
> > this String class seems like one way of pushing forwards towards a
> > compromise that provides both an easy-to-use API and a robust
> > implementation. For example, perhaps the buffer sizes need to be
> > specified or provided when the String is instantiated. Or we need an
> > alternative implementation that does more reliable memory allocation
> > (since we're not assuming that the internal buffer is continuous).
> > Other ideas welcome.
> >
> > I think the problem is that the failure modes are not benign. I haven't
> been through all the use cases so this might not work, but perhaps using a
> statically-allocated string ("NOMEM" ?) as a sentinel value instead of null
> when malloc fails might be one way? Also, there might be some benefit in
> making String immutable a la Java - overloaded operators in C++ have a
> tendency to generate anonymous temporaries, which is going to lead to heap
> fragmentation as well.
> >
> > --
> > Alan Burlison
> > --
> >
> > _______________________________________________
___________________________________________________

Posted on the Developers mailing list. Go to http://arduino.cc/mailman/listinfo/developers_arduino.cc to subscribe. It broke in the non-SDM version too, but it took longer to break. In the SDM version it breaks immediately. So it looks like whatever you did highlights the faults sooner, which is good. It also points to a need for an error response of some sort, in answer to your question last mail.

t.

On Jan 3, 2011, at 4:44 PM, Alexander Brevig wrote:

> That breaking of String, does it only occur with the SDM version?
>
> If not, did you find any way to break it? Maybe any of the old faults related to memory?
>
>
> I actually have no time to check this myself right now, so I opted to just ask you.
>
> On Mon, Jan 3, 2011 at 10:35 PM, Tom Igoe <> wrote:
> Thanks, Alexander, and sorry for the delay.
>
> A few tests:
>
> For code that doesn't change the strings much, there's not a big difference, a couple dozen bytes' difference in code size. However, when you start to do dynamic things, it does add up. For example, the StringAppendOperator example is 4910 bytes in 0022, and 5148 bytes with the StaticDynamicMemory version. So it does start to take its toll, memory-wise.
>
> On some sketches it actually takes less memory. For example, the one below is 3738 bytes using the StaticDynamicMemory version, and 3986 bytes in 0022. However, it fails entirely on upload. When the value of (analog 0)/4 is high (0xFF), it never gets out of the setup(). So there's still a pretty easy way to break String, even with these improvements.
>
>
> void setup() {
> Serial.begin(9600);
> Serial.println("Beginning");
> }
>
> void loop() {
>
> String webColor = "#";
>
> int red = analogRead(A0)/4;
> webColor += String(red, HEX);
> int green = analogRead(A1)/4;
> webColor += String(green, HEX);
> int blue = analogRead(A2)/4;
>
> webColor += String(blue, HEX);
> Serial.println(webColor);
> }
>
>
>
>
>
> On Dec 16, 2010, at 1:27 AM, Alexander Brevig wrote:
>
> > Attached is a zip containing WString.h and .cpp plus StaticDynamicMemory.h.
> > Take a backup of the original WString files, and extract this zip into the hardware/arduino/cores/arduino folder.
> >
> > Now you're ready to test the modified String library, that does not fragment the heap.
> >
> >
> > In the WString header there is a #define called STRING_BUFFER which is set to 100 for now, change this to suit your test needs.
> >
> >
> > No error handling is implemented, what do you think we need?
> >
> > I plan to add an availableMemory():int method to the SDM library, and maybe some error flags and checks like hasError():int error
> >
> > I also suspect that this library is a bit slower performance wise, but I think that's just a cost we'll have to pay to being able to play with dynamic strings.
> >
> >
> > Hope to get feedback from someone!
> >
> > On Thu, Dec 16, 2010 at 1:11 AM, Alan Burlison <> wrote:
> > On 15/12/2010 16:19, David A. Mellis wrote:
> >
> > I think you're right, but I also don't think that telling people to
> > use the standard C library functions is a solution either. Trying out
> > this String class seems like one way of pushing forwards towards a
> > compromise that provides both an easy-to-use API and a robust
> > implementation. For example, perhaps the buffer sizes need to be
> > specified or provided when the String is instantiated. Or we need an
> > alternative implementation that does more reliable memory allocation
> > (since we're not assuming that the internal buffer is continuous).
> > Other ideas welcome.
> >
> > I think the problem is that the failure modes are not benign. I haven't been through all the use cases so this might not work, but perhaps using a statically-allocated string ("NOMEM" ?) as a sentinel value instead of null when malloc fails might be one way? Also, there might be some benefit in making String immutable a la Java - overloaded operators in C++ have a tendency to generate anonymous temporaries, which is going to lead to heap fragmentation as well.
> >
> > --
> > Alan Burlison
> > --
> >
> > _______________________________________________
___________________________________________________

Posted on the Developers mailing list. Go to http://arduino.cc/mailman/listinfo/developers_arduino.cc to subscribe. There seems to be a bug with the assignment operator, I'm on it and I'll get
back to you as soon as I get something done.

Thank you for your tests and feedback.


I'll do some tests on my own before I repost it here.

On Tue, Jan 4, 2011 at 6:53 PM, Rick Anderson
<>wrote:

> I just created a test and unpacked and tested it. I also created a
> test based on Tom's code. Not sure I caught the maximum value error
> for 0xFF.
>
> I also ran the tests for bug 411. All the tests compile, but there is
> still memory loss.
>
> I'm attaching the Arduino Test suite, and the test code so you can run
> them as you debug. Let me know if this was helpful.
>
> --Rick
>
> Test run results:
> Example: ATS_StringAssignmentTest.pde
> info.MANUFACTURER = Arduino
> info.CPU-NAME = ATmega328P
> info.GCC-Version = 4.3.2
> info.AVR-LibC-Ver = 1.6.4
> info.Compiled-date = Jan 4 2011
> info.Test-Suite-Name = ATS_StringAssignmentTest
> info.Free-memory = 1110 bytes
> Memory Usage (lost 59 bytes) ... FAIL
> --------------------------
> Ran 1 tests in 1.378s
>
> FAILED (failures=1)
>
>
> Example: ATS_StringMemoryTestPassByReference.pde
>
> info.MANUFACTURER = Arduino
> info.CPU-NAME = ATmega328P
> info.GCC-Version = 4.3.2
> info.AVR-LibC-Ver = 1.6.4
> info.Compiled-date = Jan 4 2011
> info.Test-Suite-Name = ATS_StringMemoryTestPassByReference
> info.Free-memory = 1120 bytes
> Memory Usage (lost 59 bytes) ... FAIL
> --------------------------
> Ran 1 tests in 1.389s
>
> FAILED (failures=1)
>
>
> Example: Tom Igoe Memory Test
> info.MANUFACTURER = Arduino
> info.CPU-NAME = ATmega328P
> info.GCC-Version = 4.3.2
> info.AVR-LibC-Ver = 1.6.4
> info.Compiled-date = Jan 4 2011
> info.Test-Suite-Name = Tom Igoe Memory Test
> info.Free-memory = 1328 bytes
> Memory Usage (lost 9 bytes) ... FAIL
> --------------------------
> Ran 1 tests in 1.374s
>
> FAILED (failures=1)
>
>
>
> --Rick
>
> Tom, rewrote your example as a test.
>
> //************************************************************************
> //* Arduino Tom Igoe Memory Test
> //* (C) 2010 by Rick Anderson
> //* Open source as per standard Arduino code
> //*
> //************************************************************************
> //* Jan 4, 2011 Started on Tom Igoe Memory Test
> //************************************************************************
>
> #include "WProgram.h"
> #include "HardwareSerial.h"
> #include
>
> //************************************************************************
> void setup()
> {
> int startMemoryUsage;
> /*
> * Create variable for the tests.
> */
>
> String webColor = "#000000";
>
> int red = 1023/4;
> int blue = 512/4;
> int green = 128/4;
>
> /*
> * initiate the test run
> */
> //Record starting memory amount
> startMemoryUsage = ATS_GetFreeMemory();
> //Begin test run
> ATS_begin("Arduino", "Tom Igoe Memory Test");
>
> webColor = "#";
> webColor += String(red, HEX);
> webColor += String(green, HEX);
> webColor += String(blue, HEX);
>
> ATS_ReportMemoryUsage(startMemoryUsage);
>
> /*
> * Test complete
> */
>
> ATS_end();
> }
>
>
> //************************************************************************
> void loop()
> {
>
>
> }
>
>
>
>
> On Mon, Jan 3, 2011 at 9:35 PM, Tom Igoe <> wrote:
> > It broke in the non-SDM version too, but it took longer to break. In the
> SDM version it breaks immediately. So it looks like whatever you did
> highlights the faults sooner, which is good. It also points to a need for an
> error response of some sort, in answer to your question last mail.
> >
> > t.
> >
> > On Jan 3, 2011, at 4:44 PM, Alexander Brevig wrote:
> >
> >> That breaking of String, does it only occur with the SDM version?
> >>
> >> If not, did you find any way to break it? Maybe any of the old faults
> related to memory?
> >>
> >>
> >> I actually have no time to check this myself right now, so I opted to
> just ask you.
> >>
> >> On Mon, Jan 3, 2011 at 10:35 PM, Tom Igoe <> wrote:
> >> Thanks, Alexander, and sorry for the delay.
> >>
> >> A few tests:
> >>
> >> For code that doesn't change the strings much, there's not a big
> difference, a couple dozen bytes' difference in code size. However, when
> you start to do dynamic things, it does add up. For example, the
> StringAppendOperator example is 4910 bytes in 0022, and 5148 bytes with the
> StaticDynamicMemory version. So it does start to take its toll, memory-wise.
> >>
> >> On some sketches it actually takes less memory. For example, the one
> below is 3738 bytes using the StaticDynamicMemory version, and 3986 bytes in
> 0022. However, it fails entirely on upload. When the value of (analog 0)/4
> is high (0xFF), it never gets out of the setup(). So there's still a pretty
> easy way to break String, even with these improvements.
> >>
> >>
> >> void setup() {
> >> Serial.begin(9600);
> >> Serial.println("Beginning");
> >> }
> >>
> >> void loop() {
> >>
> >> String webColor = "#";
> >>
> >> int red = analogRead(A0)/4;
> >> webColor += String(red, HEX);
> >> int green = analogRead(A1)/4;
> >> webColor += String(green, HEX);
> >> int blue = analogRead(A2)/4;
> >>
> >> webColor += String(blue, HEX);
> >> Serial.println(webColor);
> >> }
> >>
> >>
> >>
> >>
> >>
> >> On Dec 16, 2010, at 1:27 AM, Alexander Brevig wrote:
> >>
> >> > Attached is a zip containing WString.h and .cpp plus
> StaticDynamicMemory.h.
> >> > Take a backup of the original WString files, and extract this zip into
> the hardware/arduino/cores/arduino folder.
> >> >
> >> > Now you're ready to test the modified String library, that does not
> fragment the heap.
> >> >
> >> >
> >> > In the WString header there is a #define called STRING_BUFFER which is
> set to 100 for now, change this to suit your test needs.
> >> >
> >> >
> >> > No error handling is implemented, what do you think we need?
> >> >
> >> > I plan to add an availableMemory():int method to the SDM library, and
> maybe some error flags and checks like hasError():int error
> >> >
> >> > I also suspect that this library is a bit slower performance wise, but
> I think that's just a cost we'll have to pay to being able to play with
> dynamic strings.
> >> >
> >> >
> >> > Hope to get feedback from someone!
> >> >
> >> > On Thu, Dec 16, 2010 at 1:11 AM, Alan Burlison <
> > wrote:
> >> > On 15/12/2010 16:19, David A. Mellis wrote:
> >> >
> >> > I think you're right, but I also don't think that telling people to
> >> > use the standard C library functions is a solution either. Trying out
> >> > this String class seems like one way of pushing forwards towards a
> >> > compromise that provides both an easy-to-use API and a robust
> >> > implementation. For example, perhaps the buffer sizes need to be
> >> > specified or provided when the String is instantiated. Or we need an
> >> > alternative implementation that does more reliable memory allocation
> >> > (since we're not assuming that the internal buffer is continuous).
> >> > Other ideas welcome.
> >> >
> >> > I think the problem is that the failure modes are not benign. I
> haven't been through all the use cases so this might not work, but perhaps
> using a statically-allocated string ("NOMEM" ?) as a sentinel value instead
> of null when malloc fails might be one way? Also, there might be some
> benefit in making String immutable a la Java - overloaded operators in C++
> have a tendency to generate anonymous temporaries, which is going to lead to
> heap fragmentation as well.
> >> >
> >> > --
> >> > Alan Burlison
> >> > --
> >> >
> >> > _______________________________________________
___________________________________________________

Posted on the Developers mailing list. Go to http://arduino.cc/mailman/listinfo/developers_arduino.cc to subscribe. Is this test suite any different than the one in the github repo?

t.

On Jan 4, 2011, at 12:53 PM, Rick Anderson wrote:

> I just created a test and unpacked and tested it. I also created a
> test based on Tom's code. Not sure I caught the maximum value error
> for 0xFF.
>
> I also ran the tests for bug 411. All the tests compile, but there is
> still memory loss.
>
> I'm attaching the Arduino Test suite, and the test code so you can run
> them as you debug. Let me know if this was helpful.
>
> --Rick
>
> Test run results:
> Example: ATS_StringAssignmentTest.pde
> info.MANUFACTURER = Arduino
> info.CPU-NAME = ATmega328P
> info.GCC-Version = 4.3.2
> info.AVR-LibC-Ver = 1.6.4
> info.Compiled-date = Jan 4 2011
> info.Test-Suite-Name = ATS_StringAssignmentTest
> info.Free-memory = 1110 bytes
> Memory Usage (lost 59 bytes) ... FAIL
> --------------------------
> Ran 1 tests in 1.378s
>
> FAILED (failures=1)
>
>
> Example: ATS_StringMemoryTestPassByReference.pde
>
> info.MANUFACTURER = Arduino
> info.CPU-NAME = ATmega328P
> info.GCC-Version = 4.3.2
> info.AVR-LibC-Ver = 1.6.4
> info.Compiled-date = Jan 4 2011
> info.Test-Suite-Name = ATS_StringMemoryTestPassByReference
> info.Free-memory = 1120 bytes
> Memory Usage (lost 59 bytes) ... FAIL
> --------------------------
> Ran 1 tests in 1.389s
>
> FAILED (failures=1)
>
>
> Example: Tom Igoe Memory Test
> info.MANUFACTURER = Arduino
> info.CPU-NAME = ATmega328P
> info.GCC-Version = 4.3.2
> info.AVR-LibC-Ver = 1.6.4
> info.Compiled-date = Jan 4 2011
> info.Test-Suite-Name = Tom Igoe Memory Test
> info.Free-memory = 1328 bytes
> Memory Usage (lost 9 bytes) ... FAIL
> --------------------------
> Ran 1 tests in 1.374s
>
> FAILED (failures=1)
>
>
>
> --Rick
>
> Tom, rewrote your example as a test.
>
> //************************************************************************
> //* Arduino Tom Igoe Memory Test
> //* (C) 2010 by Rick Anderson
> //* Open source as per standard Arduino code
> //*
> //************************************************************************
> //* Jan 4, 2011 Started on Tom Igoe Memory Test
> //************************************************************************
>
> #include "WProgram.h"
> #include "HardwareSerial.h"
> #include
>
> //************************************************************************
> void setup()
> {
> int startMemoryUsage;
> /*
> * Create variable for the tests.
> */
>
> String webColor = "#000000";
>
> int red = 1023/4;
> int blue = 512/4;
> int green = 128/4;
>
> /*
> * initiate the test run
> */
> //Record starting memory amount
> startMemoryUsage = ATS_GetFreeMemory();
> //Begin test run
> ATS_begin("Arduino", "Tom Igoe Memory Test");
>
> webColor = "#";
> webColor += String(red, HEX);
> webColor += String(green, HEX);
> webColor += String(blue, HEX);
>
> ATS_ReportMemoryUsage(startMemoryUsage);
>
> /*
> * Test complete
> */
>
> ATS_end();
> }
>
>
> //************************************************************************
> void loop()
> {
>
>
> }
>
>
>
>
> On Mon, Jan 3, 2011 at 9:35 PM, Tom Igoe <> wrote:
>> It broke in the non-SDM version too, but it took longer to break. In the SDM version it breaks immediately. So it looks like whatever you did highlights the faults sooner, which is good. It also points to a need for an error response of some sort, in answer to your question last mail.
>>
>> t.
>>
>> On Jan 3, 2011, at 4:44 PM, Alexander Brevig wrote:
>>
>>> That breaking of String, does it only occur with the SDM version?
>>>
>>> If not, did you find any way to break it? Maybe any of the old faults related to memory?
>>>
>>>
>>> I actually have no time to check this myself right now, so I opted to just ask you.
>>>
>>> On Mon, Jan 3, 2011 at 10:35 PM, Tom Igoe <> wrote:
>>> Thanks, Alexander, and sorry for the delay.
>>>
>>> A few tests:
>>>
>>> For code that doesn't change the strings much, there's not a big difference, a couple dozen bytes' difference in code size. However, when you start to do dynamic things, it does add up. For example, the StringAppendOperator example is 4910 bytes in 0022, and 5148 bytes with the StaticDynamicMemory version. So it does start to take its toll, memory-wise.
>>>
>>> On some sketches it actually takes less memory. For example, the one below is 3738 bytes using the StaticDynamicMemory version, and 3986 bytes in 0022. However, it fails entirely on upload. When the value of (analog 0)/4 is high (0xFF), it never gets out of the setup(). So there's still a pretty easy way to break String, even with these improvements.
>>>
>>>
>>> void setup() {
>>> Serial.begin(9600);
>>> Serial.println("Beginning");
>>> }
>>>
>>> void loop() {
>>>
>>> String webColor = "#";
>>>
>>> int red = analogRead(A0)/4;
>>> webColor += String(red, HEX);
>>> int green = analogRead(A1)/4;
>>> webColor += String(green, HEX);
>>> int blue = analogRead(A2)/4;
>>>
>>> webColor += String(blue, HEX);
>>> Serial.println(webColor);
>>> }
>>>
>>>
>>>
>>>
>>>
>>> On Dec 16, 2010, at 1:27 AM, Alexander Brevig wrote:
>>>
>>>> Attached is a zip containing WString.h and .cpp plus StaticDynamicMemory.h.
>>>> Take a backup of the original WString files, and extract this zip into the hardware/arduino/cores/arduino folder.
>>>>
>>>> Now you're ready to test the modified String library, that does not fragment the heap.
>>>>
>>>>
>>>> In the WString header there is a #define called STRING_BUFFER which is set to 100 for now, change this to suit your test needs.
>>>>
>>>>
>>>> No error handling is implemented, what do you think we need?
>>>>
>>>> I plan to add an availableMemory():int method to the SDM library, and maybe some error flags and checks like hasError():int error
>>>>
>>>> I also suspect that this library is a bit slower performance wise, but I think that's just a cost we'll have to pay to being able to play with dynamic strings.
>>>>
>>>>
>>>> Hope to get feedback from someone!
>>>>
>>>> On Thu, Dec 16, 2010 at 1:11 AM, Alan Burlison <> wrote:
>>>> On 15/12/2010 16:19, David A. Mellis wrote:
>>>>
>>>> I think you're right, but I also don't think that telling people to
>>>> use the standard C library functions is a solution either. Trying out
>>>> this String class seems like one way of pushing forwards towards a
>>>> compromise that provides both an easy-to-use API and a robust
>>>> implementation. For example, perhaps the buffer sizes need to be
>>>> specified or provided when the String is instantiated. Or we need an
>>>> alternative implementation that does more reliable memory allocation
>>>> (since we're not assuming that the internal buffer is continuous).
>>>> Other ideas welcome.
>>>>
>>>> I think the problem is that the failure modes are not benign. I haven't been through all the use cases so this might not work, but perhaps using a statically-allocated string ("NOMEM" ?) as a sentinel value instead of null when malloc fails might be one way? Also, there might be some benefit in making String immutable a la Java - overloaded operators in C++ have a tendency to generate anonymous temporaries, which is going to lead to heap fragmentation as well.
>>>>
>>>> --
>>>> Alan Burlison
>>>> --
>>>>
>>>> _______________________________________________
___________________________________________________

Posted on the Developers mailing list. Go to http://arduino.cc/mailman/listinfo/developers_arduino.cc to subscribe. Same exact one. I just included it just in case.

--Rick

On Tue, Jan 4, 2011 at 9:01 PM, Tom Igoe <> wrote:
> Is this test suite any different than the one in the github repo?
>
> t.
>
> On Jan 4, 2011, at 12:53 PM, Rick Anderson wrote:
>
>> I just created a test and unpacked and tested it. I also created a
>> test based on Tom's code. Not sure I caught the maximum value error
>> for 0xFF.
>>
>> I also ran the tests for bug 411. All the tests compile, but there is
>> still memory loss.
>>
>> I'm attaching the Arduino Test suite, and the test code so you can run
>> them as you debug. Let me know if this was helpful.
>>
>> --Rick
>>
>> Test run results:
>> Example:  ATS_StringAssignmentTest.pde
>> info.MANUFACTURER    = Arduino
>> info.CPU-NAME        = ATmega328P
>> info.GCC-Version     = 4.3.2
>> info.AVR-LibC-Ver    = 1.6.4
>> info.Compiled-date   = Jan  4 2011
>> info.Test-Suite-Name = ATS_StringAssignmentTest
>> info.Free-memory     = 1110 bytes
>> Memory Usage (lost 59 bytes)                                ... FAIL
>> --------------------------
>> Ran 1 tests in 1.378s
>>
>> FAILED (failures=1)
>>
>>
>> Example: ATS_StringMemoryTestPassByReference.pde
>>
>> info.MANUFACTURER    = Arduino
>> info.CPU-NAME        = ATmega328P
>> info.GCC-Version     = 4.3.2
>> info.AVR-LibC-Ver    = 1.6.4
>> info.Compiled-date   = Jan  4 2011
>> info.Test-Suite-Name = ATS_StringMemoryTestPassByReference
>> info.Free-memory     = 1120 bytes
>> Memory Usage (lost 59 bytes)                                ... FAIL
>> --------------------------
>> Ran 1 tests in 1.389s
>>
>> FAILED (failures=1)
>>
>>
>> Example: Tom Igoe Memory Test
>> info.MANUFACTURER    = Arduino
>> info.CPU-NAME        = ATmega328P
>> info.GCC-Version     = 4.3.2
>> info.AVR-LibC-Ver    = 1.6.4
>> info.Compiled-date   = Jan  4 2011
>> info.Test-Suite-Name = Tom Igoe Memory Test
>> info.Free-memory     = 1328 bytes
>> Memory Usage (lost 9 bytes)                                 ... FAIL
>> --------------------------
>> Ran 1 tests in 1.374s
>>
>> FAILED (failures=1)
>>
>>
>>
>> --Rick
>>
>> Tom, rewrote your example as a test.
>>
>> //************************************************************************
>> //*   Arduino Tom Igoe Memory Test
>> //*           (C) 2010 by Rick Anderson
>> //*           Open source as per standard Arduino code
>> //*
>> //************************************************************************
>> //*   Jan 4,  2011     Started on Tom Igoe Memory Test
>> //************************************************************************
>>
>> #include      "WProgram.h"
>> #include      "HardwareSerial.h"
>> #include      
>>
>> //************************************************************************
>> void setup()
>> {
>>  int          startMemoryUsage;
>>  /*
>>    * Create variable for the tests.
>>   */
>>
>>  String webColor = "#000000";
>>
>>  int red = 1023/4;
>>  int blue = 512/4;
>>  int green = 128/4;
>>
>>  /*
>>  * initiate the test run
>>   */
>>  //Record starting memory amount
>>  startMemoryUsage     =       ATS_GetFreeMemory();
>>  //Begin test run
>>  ATS_begin("Arduino", "Tom Igoe Memory Test");
>>
>>  webColor = "#";
>>  webColor += String(red, HEX);
>>  webColor += String(green, HEX);
>>  webColor += String(blue, HEX);
>>
>>  ATS_ReportMemoryUsage(startMemoryUsage);
>>
>>  /*
>>   * Test complete
>>   */
>>
>>  ATS_end();
>> }
>>
>>
>> //************************************************************************
>> void loop()
>> {
>>
>>
>> }
>>
>>
>>
>>
>> On Mon, Jan 3, 2011 at 9:35 PM, Tom Igoe <> wrote:
>>> It broke in the non-SDM version too, but it took longer to break. In the SDM version it breaks immediately. So it looks like whatever you did highlights the faults sooner, which is good. It also points to a need for an error response of some sort, in answer to your question last mail.
>>>
>>> t.
>>>
>>> On Jan 3, 2011, at 4:44 PM, Alexander Brevig wrote:
>>>
>>>> That breaking of String, does it only occur with the SDM version?
>>>>
>>>> If not, did you find any way to break it? Maybe any of the old faults related to memory?
>>>>
>>>>
>>>> I actually have no time to check this myself right now, so I opted to just ask you.
>>>>
>>>> On Mon, Jan 3, 2011 at 10:35 PM, Tom Igoe <> wrote:
>>>> Thanks, Alexander, and sorry for the delay.
>>>>
>>>> A few tests:
>>>>
>>>> For code that doesn't change the strings much, there's not a big difference, a couple dozen bytes' difference in code size.  However, when you start to do dynamic things, it does add up.  For example, the StringAppendOperator example is  4910 bytes in 0022, and 5148 bytes with the StaticDynamicMemory version. So it does start to take its toll, memory-wise.
>>>>
>>>> On some sketches it actually takes less memory.  For example, the one below is 3738 bytes using the StaticDynamicMemory version, and 3986 bytes in 0022.  However, it fails entirely on upload.  When the value of (analog 0)/4 is high (0xFF), it never gets out of the setup(). So there's still a pretty easy way to break String, even with these improvements.
>>>>
>>>>
>>>> void setup() {
>>>>  Serial.begin(9600);
>>>>  Serial.println("Beginning");
>>>> }
>>>>
>>>> void loop() {
>>>>
>>>>  String webColor = "#";
>>>>
>>>>  int red = analogRead(A0)/4;
>>>>  webColor += String(red, HEX);
>>>>  int green = analogRead(A1)/4;
>>>>  webColor += String(green, HEX);
>>>>  int blue = analogRead(A2)/4;
>>>>
>>>>  webColor += String(blue, HEX);
>>>>  Serial.println(webColor);
>>>> }
>>>>
>>>>
>>>>
>>>>
>>>>
>>>> On Dec 16, 2010, at 1:27 AM, Alexander Brevig wrote:
>>>>
>>>>> Attached is a zip containing WString.h and .cpp plus StaticDynamicMemory.h.
>>>>> Take a backup of the original WString files, and extract this zip into the hardware/arduino/cores/arduino folder.
>>>>>
>>>>> Now you're ready to test the modified String library, that does not fragment the heap.
>>>>>
>>>>>
>>>>> In the WString header there is a #define called STRING_BUFFER which is set to 100 for now, change this to suit your test needs.
>>>>>
>>>>>
>>>>> No error handling is implemented, what do you think we need?
>>>>>
>>>>> I plan to add an availableMemory():int method to the SDM library, and maybe some error flags and checks like hasError():int error
>>>>>
>>>>> I also suspect that this library is a bit slower performance wise, but I think that's just a cost we'll have to pay to being able to play with dynamic strings.
>>>>>
>>>>>
>>>>> Hope to  get feedback from someone!
>>>>>
>>>>> On Thu, Dec 16, 2010 at 1:11 AM, Alan Burlison <> wrote:
>>>>> On 15/12/2010 16:19, David A. Mellis wrote:
>>>>>
>>>>> I think you're right, but I also don't think that telling people to
>>>>> use the standard C library functions is a solution either.  Trying out
>>>>> this String class seems like one way of pushing forwards towards a
>>>>> compromise that provides both an easy-to-use API and a robust
>>>>> implementation.  For example, perhaps the buffer sizes need to be
>>>>> specified or provided when the String is instantiated.  Or we need an
>>>>> alternative implementation that does more reliable memory allocation
>>>>> (since we're not assuming that the internal buffer is continuous).
>>>>> Other ideas welcome.
>>>>>
>>>>> I think the problem is that the failure modes are not benign.  I haven't been through all the use cases so this might not work, but perhaps using a statically-allocated string ("NOMEM" ?) as a sentinel value instead of null when malloc fails might be one way?  Also, there might be some benefit in making String immutable a la Java - overloaded operators in C++ have a tendency to generate anonymous temporaries, which is going to lead to heap fragmentation as well.
>>>>>
>>>>> --
>>>>> Alan Burlison
>>>>> --
>>>>>
>>>>> _______________________________________________
___________________________________________________

Posted on the Developers mailing list. Go to http://arduino.cc/mailman/listinfo/developers_arduino.cc to subscribe. On 04/01/2011 17:53, Rick Anderson wrote:

> I also ran the tests for bug 411. All the tests compile, but there is
> still memory loss.

Most of the assumptions made by the test harness and test case code are
wrong, any reports of 'lost' memory are therefore likely to be wrong as
well. If you want to do leak detection you can't do it in the naive way
it is being done at present.

--
Alan Burlison
--

_______________________________________________
___________________________________________________

Posted on the Developers mailing list. Go to http://arduino.cc/mailman/listinfo/developers_arduino.cc to subscribe. Alan,

The tests themselves are quick and dirty, and not strategic or
comprehensive. I'd like your input to create a good procedure for
memory testing. I also have feedback from Paul Stoffregen for the test
suite:
----
Another problem involves gcc's optimizer ignoring the inline request
for ATS_ReportMemoryUsage. As the comment in the code explains, it
must be inline to avoid measuring its own stack frame. I believe
adding this line in ArduinoTestSuite.h fixes the problem by forcing
gcc to inline.

inline void ATS_ReportMemoryUsage(int _memoryUsageAtStart)
__attribute__((always_inline, unused));

The last problem is a tiny bit of dynamic memory permanently held for
the free list. To allow for this, the test really should call
malloc() and free() once, so the allocator is fully initialized before
testing.
----

I'd like to combine both sets of feedback, and set up some issues in
the system, then fix them. Is the above the problem you saw? Are their
other assumptions that would impact measuring memory? And updating the
memory test in the the test suite.

In terms of creating tests for memory leaks. It looks best to move all
the memory usage inside a function. What else could be done to
constrain the problem, and measuring more affectively.

I'm traveling back to NJ today, so I can't respond right away.

--Rick

On Wed, Jan 5, 2011 at 8:52 AM, Alan Burlison <> wrote:
> On 04/01/2011 17:53, Rick Anderson wrote:
>
>> I also ran the tests for bug 411. All the tests compile, but there is
>> still memory loss.
>
> Most of the assumptions made by the test harness and test case code are
> wrong, any reports of 'lost' memory are therefore likely to be wrong as
> well.  If you want to do leak detection you can't do it in the naive way it
> is being done at present.
>
> --
> Alan Burlison
> --
>



--
President
Fair Use Building and Research (****) Labs
http://fubarlabs.org

_______________________________________________
___________________________________________________

Posted on the Developers mailing list. Go to http://arduino.cc/mailman/listinfo/developers_arduino.cc to subscribe. On 05/01/2011 15:19, Rick Anderson wrote:

> ----
> Another problem involves gcc's optimizer ignoring the inline request
> for ATS_ReportMemoryUsage. As the comment in the code explains, it
> must be inline to avoid measuring its own stack frame. I believe
> adding this line in ArduinoTestSuite.h fixes the problem by forcing
> gcc to inline.
>
> inline void ATS_ReportMemoryUsage(int _memoryUsageAtStart)
> __attribute__((always_inline, unused));

Yes, that's one of the problems. And even the __attribute__
'workaround' is a fragile hack.

> The last problem is a tiny bit of dynamic memory permanently held for
> the free list. To allow for this, the test really should call
> malloc() and free() once, so the allocator is fully initialized before

That's part of a problem, but an initial call malloc/free call isn't
guaranteed to make all the issues go away either. From looking at the
avr-libc malloc implementation it does try to coalesce the heap, but
relying on multiple malloc implementation artefacts is a really bad idea
- there's no guarantee that future malloc implementations will always
coalesce on every free, and there's no guarantee that __bss_end or
__brkval will always be adjusted on each malloc/free call.

The other issue is that of object lifetimes. The test code has
instances of String objects which are allocated on the stack and that
are still in scope when the 'leak' memory check is performed. That
means the String destructors won't have been called and the dynamically
allocated part of the String will still be allocated.

A true memory leak is a block of allocated memory that has no references
to it. However that's not what the test code is checking for. If a
library routine used malloc to perform a one-time library-private buffer
allocation where the buffer is retained for the lifetime of the program,
the current leak checking would incorrectly report that as a leak. It
isn't a leak because there's still a reference to the block inside the
library.

The only semi-reliable way to do what you want is to use an instrumented
malloc implementation, and that's going to be very difficult to
implement on a constrained platform such as the AVR. If you want to
test the String implementation for leaks, my advice is to do it on a
more capable platform (e.g. *nix) and use one of the many instrumented
mallocs that are available.

--
Alan Burlison
--

_______________________________________________
___________________________________________________

Posted on the Developers mailing list. Go to http://arduino.cc/mailman/listinfo/developers_arduino.cc to subscribe. Slightly unrelated to what you guys are discussing now but:
I'm not sure if I've made this clear, but the new version of String that I'm
working on now does not use malloc or any other c function for dynamic
memory. What happens is that I allocate memory statically on the stack and
serve that memory dynamically to the instances of String.

I have some time on my hands now and have a look at getting the += not to
break the code

On Wed, Jan 5, 2011 at 7:10 PM, Alan Burlison <>wrote:

> On 05/01/2011 15:19, Rick Anderson wrote:
>
> ----
>> Another problem involves gcc's optimizer ignoring the inline request
>> for ATS_ReportMemoryUsage. As the comment in the code explains, it
>> must be inline to avoid measuring its own stack frame. I believe
>> adding this line in ArduinoTestSuite.h fixes the problem by forcing
>> gcc to inline.
>>
>> inline void ATS_ReportMemoryUsage(int _memoryUsageAtStart)
>> __attribute__((always_inline, unused));
>>
>
> Yes, that's one of the problems. And even the __attribute__ 'workaround'
> is a fragile hack.
>
>
> The last problem is a tiny bit of dynamic memory permanently held for
>> the free list. To allow for this, the test really should call
>> malloc() and free() once, so the allocator is fully initialized before
>>
>
> That's part of a problem, but an initial call malloc/free call isn't
> guaranteed to make all the issues go away either. From looking at the
> avr-libc malloc implementation it does try to coalesce the heap, but relying
> on multiple malloc implementation artefacts is a really bad idea - there's
> no guarantee that future malloc implementations will always coalesce on
> every free, and there's no guarantee that __bss_end or __brkval will always
> be adjusted on each malloc/free call.
>
> The other issue is that of object lifetimes. The test code has instances
> of String objects which are allocated on the stack and that are still in
> scope when the 'leak' memory check is performed. That means the String
> destructors won't have been called and the dynamically allocated part of the
> String will still be allocated.
>
> A true memory leak is a block of allocated memory that has no references to
> it. However that's not what the test code is checking for. If a library
> routine used malloc to perform a one-time library-private buffer allocation
> where the buffer is retained for the lifetime of the program, the current
> leak checking would incorrectly report that as a leak. It isn't a leak
> because there's still a reference to the block inside the library.
>
> The only semi-reliable way to do what you want is to use an instrumented
> malloc implementation, and that's going to be very difficult to implement on
> a constrained platform such as the AVR. If you want to test the String
> implementation for leaks, my advice is to do it on a more capable platform
> (e.g. *nix) and use one of the many instrumented mallocs that are available.
>
> --
> Alan Burlison
> --
>
>
> _______________________________________________
___________________________________________________

Posted on the Developers mailing list. Go to http://arduino.cc/mailman/listinfo/developers_arduino.cc to subscribe. On 05/01/2011 18:25, Alexander Brevig wrote:

> Slightly unrelated to what you guys are discussing now but:
> I'm not sure if I've made this clear, but the new version of String that I'm
> working on now does not use malloc or any other c function for dynamic
> memory. What happens is that I allocate memory statically on the stack and
> serve that memory dynamically to the instances of String.

Does that mean that the total space occupied by all Strings has to be
decided up front? If so, what is the behaviour when an allocation fails?

To be honest I don't really see the point of doing this - all you are
doing is re-implementing malloc.

--
Alan Burlison
--

_______________________________________________
___________________________________________________

Posted on the Developers mailing list. Go to http://arduino.cc/mailman/listinfo/developers_arduino.cc to subscribe. No, actually I am not reimplementing malloc, because my algorithm guarantees
no fragmentation and always 100% effective use of the allocated memory.

"Does that mean that the total space occupied by all Strings has to be
decided up front? "
Yes, just like the buffer for the serial ++

I know I would opt to have the restriction for a predetermined allocated
space WITH error reporting (how we do is up to you guys, feed me with ideas
I'll implement whatever we agree is best) than having
seemingly infinite memory that crashes and burns.

On Wed, Jan 5, 2011 at 7:33 PM, Alan Burlison <>wrote:

> On 05/01/2011 18:25, Alexander Brevig wrote:
>
> Slightly unrelated to what you guys are discussing now but:
>> I'm not sure if I've made this clear, but the new version of String that
>> I'm
>> working on now does not use malloc or any other c function for dynamic
>> memory. What happens is that I allocate memory statically on the stack and
>> serve that memory dynamically to the instances of String.
>>
>
> Does that mean that the total space occupied by all Strings has to be
> decided up front? If so, what is the behaviour when an allocation fails?
>
> To be honest I don't really see the point of doing this - all you are doing
> is re-implementing malloc.
>
> --
> Alan Burlison
> --
> Well, that was easy (seemingly, probably just jinxed myself...) but here the
test does no longer break, and the usage of memory never exceeds 11 bytes.

It would be awesome if someone would test it.


Also, please tell me now if this effort will lead to nowhere. Is the cost of
being constrained to a buffer size a deal-breaker?

On Wed, Jan 5, 2011 at 7:42 PM, Alexander Brevig
<>wrote:

> No, actually I am not reimplementing malloc, because my algorithm
> guarantees no fragmentation and always 100% effective use of the allocated
> memory.
>
> "Does that mean that the total space occupied by all Strings has to be
> decided up front? "
> Yes, just like the buffer for the serial ++
>
> I know I would opt to have the restriction for a predetermined allocated
> space WITH error reporting (how we do is up to you guys, feed me with ideas
> I'll implement whatever we agree is best) than having
> seemingly infinite memory that crashes and burns.
>
> On Wed, Jan 5, 2011 at 7:33 PM, Alan Burlison <>wrote:
>
>> On 05/01/2011 18:25, Alexander Brevig wrote:
>>
>> Slightly unrelated to what you guys are discussing now but:
>>> I'm not sure if I've made this clear, but the new version of String that
>>> I'm
>>> working on now does not use malloc or any other c function for dynamic
>>> memory. What happens is that I allocate memory statically on the stack
>>> and
>>> serve that memory dynamically to the instances of String.
>>>
>>
>> Does that mean that the total space occupied by all Strings has to be
>> decided up front? If so, what is the behaviour when an allocation fails?
>>
>> To be honest I don't really see the point of doing this - all you are
>> doing is re-implementing malloc.
>>
>> --
>> Alan Burlison
>> --
>>
>
> So sorry you all! I shipped my test code (for msvc++ compiler) in five
minutes I'll post an arduino compatible version. So sorry for this spam!

On Wed, Jan 5, 2011 at 8:01 PM, Alexander Brevig
<>wrote:

> Well, that was easy (seemingly, probably just jinxed myself...) but here
> the test does no longer break, and the usage of memory never exceeds 11
> bytes.
>
> It would be awesome if someone would test it.
>
>
> Also, please tell me now if this effort will lead to nowhere. Is the cost
> of being constrained to a buffer size a deal-breaker?
>
>
> On Wed, Jan 5, 2011 at 7:42 PM, Alexander Brevig <
> > wrote:
>
>> No, actually I am not reimplementing malloc, because my algorithm
>> guarantees no fragmentation and always 100% effective use of the allocated
>> memory.
>>
>> "Does that mean that the total space occupied by all Strings has to be
>> decided up front? "
>> Yes, just like the buffer for the serial ++
>>
>> I know I would opt to have the restriction for a predetermined allocated
>> space WITH error reporting (how we do is up to you guys, feed me with ideas
>> I'll implement whatever we agree is best) than having
>> seemingly infinite memory that crashes and burns.
>>
>> On Wed, Jan 5, 2011 at 7:33 PM, Alan Burlison <>wrote:
>>
>>> On 05/01/2011 18:25, Alexander Brevig wrote:
>>>
>>> Slightly unrelated to what you guys are discussing now but:
>>>> I'm not sure if I've made this clear, but the new version of String that
>>>> I'm
>>>> working on now does not use malloc or any other c function for dynamic
>>>> memory. What happens is that I allocate memory statically on the stack
>>>> and
>>>> serve that memory dynamically to the instances of String.
>>>>
>>>
>>> Does that mean that the total space occupied by all Strings has to be
>>> decided up front? If so, what is the behaviour when an allocation fails?
>>>
>>> To be honest I don't really see the point of doing this - all you are
>>> doing is re-implementing malloc.
>>>
>>> --
>>> Alan Burlison
>>> --
>>>
>>
>>
> > The other issue is that of object lifetimes. The test code has
> instances of String objects which are allocated on the stack and that
> are still in scope when the 'leak' memory check is performed.

That was also in my (off list) email a few days ago, though that bit
didn't make it here.

I believe the plan is to move the tests and object(s) they use to a
function, so the objects will be out of scope when the memory check is made.

There might also another copy of the test which pre-allocates a string
large enough to hold all the data. I'm not sure exactly how I feel
about that approach, but it seems like at least worth trying. Currently
the string library does not have a reserve() function. I've proposed it
before, and today I put it in issue #449.

> If a library routine used malloc to perform a one-time library-private
> buffer allocation where the buffer is retained for the lifetime of the
> program, the current leak checking would incorrectly report that as a
> leak. It isn't a leak because there's still a reference to the block
> inside the library.

Yes, you are correct, the test makes some assumptions about the internal
implementation, and yes, an ideal test wouldn't make any such
assumptions, and yes, it's probably impractical to completely avoid
assumptions on such limited hardware.

But there's a lot of value in actually testing on the real hardware,
with all its limitations and slight differences from running on a PC.
Personally, I think making some assumptions is a pretty good trade-off
for testing in the actual environment. Of course, there's plenty of
room for smart ideas to minimize such assumptions, or perhaps test in
multiple ways.

As someone who's spent a lot of time coding on the string class (and has
more planned), the real value isn't a perfect score if my code is bug
free, but rather a FAIL coming up when I make some mistake that
unexpectedly breaks something. Sure it's annoying if a FAIL comes up
erroneously because the internal implementation changed,

There are so many functions, with so many cases, that subtle errors can
happen (eg, does lastIndexOf work when the search string is the entire
original string... I broke that recently, but everything else worked.....)

If you have ideas about how to catch more types of errors, even if
imperfect, I'd really love to hear.




>
>
> The only semi-reliable way to do what you want is to use an
> instrumented malloc implementation, and that's going to be very
> difficult to implement on a constrained platform such as the AVR. If
> you want to test the String implementation for leaks, my advice is to
> do it on a more capable platform (e.g. *nix) and use one of the many
> instrumented mallocs that are available.
>


_______________________________________________
___________________________________________________

Posted on the Developers mailing list. Go to http://arduino.cc/mailman/listinfo/developers_arduino.cc to subscribe. I'm not sure I follow, string.read(); what would that do?
How do you imagine String to use Stream ? :)

Attached: new version arduino compitable

On Wed, Jan 5, 2011 at 8:20 PM, Tom Igoe <> wrote:

> Could you then just use Stream as a basis for String? Sorry, I didn't look
> into the details of your DMA class, but as long as we're setting a limit to
> begin with, and if we know Stream's pretty solid, why not restructure String
> a bit to use it?
>
> t.
>
>
> On Jan 5, 2011, at 1:42 PM, Alexander Brevig wrote:
>
> > No, actually I am not reimplementing malloc, because my algorithm
> guarantees no fragmentation and always 100% effective use of the allocated
> memory.
> >
> > "Does that mean that the total space occupied by all Strings has to be
> decided up front? "
> > Yes, just like the buffer for the serial ++
> >
> > I know I would opt to have the restriction for a predetermined allocated
> space WITH error reporting (how we do is up to you guys, feed me with ideas
> I'll implement whatever we agree is best) than having seemingly infinite
> memory that crashes and burns.
> >
> > On Wed, Jan 5, 2011 at 7:33 PM, Alan Burlison <>
> wrote:
> > On 05/01/2011 18:25, Alexander Brevig wrote:
> >
> > Slightly unrelated to what you guys are discussing now but:
> > I'm not sure if I've made this clear, but the new version of String that
> I'm
> > working on now does not use malloc or any other c function for dynamic
> > memory. What happens is that I allocate memory statically on the stack
> and
> > serve that memory dynamically to the instances of String.
> >
> > Does that mean that the total space occupied by all Strings has to be
> decided up front? If so, what is the behaviour when an allocation fails?
> >
> > To be honest I don't really see the point of doing this - all you are
> doing is re-implementing malloc.
> >
> > --
> > Alan Burlison
> > --
> >
> > _______________________________________________
___________________________________________________

Posted on the Developers mailing list. Go to http://arduino.cc/mailman/listinfo/developers_arduino.cc to subscribe. > I'm not sure I follow, string.read(); what would that do?
> How do you imagine String to use Stream ? :)

I also do not understand? In fact, I'm completely mystified. Please
explain...

But I would like to let you know I've been working on debugging the
string class, and in the last few days together with the test suite.
I'll likely post code sometimes next week.


>
> Attached: new version arduino compitable
>
> On Wed, Jan 5, 2011 at 8:20 PM, Tom Igoe <
> > wrote:
>
> Could you then just use Stream as a basis for String? Sorry, I
> didn't look into the details of your DMA class, but as long as
> we're setting a limit to begin with, and if we know Stream's
> pretty solid, why not restructure String a bit to use it?
>
> t.
>
>
> On Jan 5, 2011, at 1:42 PM, Alexander Brevig wrote:
>
> > No, actually I am not reimplementing malloc, because my
> algorithm guarantees no fragmentation and always 100% effective
> use of the allocated memory.
> >
> > "Does that mean that the total space occupied by all Strings has
> to be decided up front? "
> > Yes, just like the buffer for the serial ++
> >
> > I know I would opt to have the restriction for a predetermined
> allocated space WITH error reporting (how we do is up to you guys,
> feed me with ideas I'll implement whatever we agree is best) than
> having seemingly infinite memory that crashes and burns.
> >
> > On Wed, Jan 5, 2011 at 7:33 PM, Alan Burlison
> < > wrote:
> > On 05/01/2011 18:25, Alexander Brevig wrote:
> >
> > Slightly unrelated to what you guys are discussing now but:
> > I'm not sure if I've made this clear, but the new version of
> String that I'm
> > working on now does not use malloc or any other c function for
> dynamic
> > memory. What happens is that I allocate memory statically on the
> stack and
> > serve that memory dynamically to the instances of String.
> >
> > Does that mean that the total space occupied by all Strings has
> to be decided up front? If so, what is the behaviour when an
> allocation fails?
> >
> > To be honest I don't really see the point of doing this - all
> you are doing is re-implementing malloc.
> >
> > --
> > Alan Burlison
> > --
> >
> > _______________________________________________
___________________________________________________

Posted on the Developers mailing list. Go to http://arduino.cc/mailman/listinfo/developers_arduino.cc to subscribe. I'm very interested to see if one of your tests break the new version of the
String class Paul! the version with _3. If you manage to break it I'll shut
up about statically allocating a buffer forever, until then I'll probably
try to push for at least some more time :)

+1 internet to the one who first breaks the new lib, -1 for me (and I
promise, this is the first and last time I gamble in internets)

On Wed, Jan 5, 2011 at 8:09 PM, Paul Stoffregen <> wrote:

>
> The other issue is that of object lifetimes. The test code has instances
>> of String objects which are allocated on the stack and that are still in
>> scope when the 'leak' memory check is performed.
>>
>
> That was also in my (off list) email a few days ago, though that bit didn't
> make it here.
>
> I believe the plan is to move the tests and object(s) they use to a
> function, so the objects will be out of scope when the memory check is made.
>
> There might also another copy of the test which pre-allocates a string
> large enough to hold all the data. I'm not sure exactly how I feel about
> that approach, but it seems like at least worth trying. Currently the
> string library does not have a reserve() function. I've proposed it before,
> and today I put it in issue #449.
>
>
> If a library routine used malloc to perform a one-time library-private
>> buffer allocation where the buffer is retained for the lifetime of the
>> program, the current leak checking would incorrectly report that as a leak.
>> It isn't a leak because there's still a reference to the block inside the
>> library.
>>
>
> Yes, you are correct, the test makes some assumptions about the internal
> implementation, and yes, an ideal test wouldn't make any such assumptions,
> and yes, it's probably impractical to completely avoid assumptions on such
> limited hardware.
>
> But there's a lot of value in actually testing on the real hardware, with
> all its limitations and slight differences from running on a PC.
> Personally, I think making some assumptions is a pretty good trade-off for
> testing in the actual environment. Of course, there's plenty of room for
> smart ideas to minimize such assumptions, or perhaps test in multiple ways.
>
> As someone who's spent a lot of time coding on the string class (and has
> more planned), the real value isn't a perfect score if my code is bug free,
> but rather a FAIL coming up when I make some mistake that unexpectedly
> breaks something. Sure it's annoying if a FAIL comes up erroneously because
> the internal implementation changed,
>
> There are so many functions, with so many cases, that subtle errors can
> happen (eg, does lastIndexOf work when the search string is the entire
> original string... I broke that recently, but everything else worked.....)
>
> If you have ideas about how to catch more types of errors, even if
> imperfect, I'd really love to hear.
>
>
>
>
>
>
>>
>> The only semi-reliable way to do what you want is to use an instrumented
>> malloc implementation, and that's going to be very difficult to implement on
>> a constrained platform such as the AVR. If you want to test the String
>> implementation for leaks, my advice is to do it on a more capable platform
>> (e.g. *nix) and use one of the many instrumented mallocs that are available.
>>
>>
>
> _______________________________________________
___________________________________________________

Posted on the Developers mailing list. Go to http://arduino.cc/mailman/listinfo/developers_arduino.cc to subscribe. > If you manage to break it I'll shut
> up about statically allocating a buffer forever, until then I'll probably
> try to push for at least some more time :)
> +1 internet to the one who first breaks the new lib, -1 for me (and I
> promise, this is the first and last time I gamble in internets)

I'm sorry but your implementation is really badly broken. I can come
up with multiple potential ways to break it after only a cursory
inspection, plus the performance will be abysmal as you copy
everything around all the time.

Here are some things to think about:

1. What happens if a String contains an embedded null character?
2. What assumptions are you making about the maximum length of a
String, and the maximum number of allocated Strings?

--
Alan Burlison
--

_______________________________________________
___________________________________________________

Posted on the Developers mailing list. Go to http://arduino.cc/mailman/listinfo/developers_arduino.cc to subscribe.

  #19  
06-01-2011 01:26 AM
Developers member admin is online now
User
 

That breaking of String, does it only occur with the SDM version?

If not, did you find any way to break it? Maybe any of the old faults
related to memory?


I actually have no time to check this myself right now, so I opted to just
ask you.

On Mon, Jan 3, 2011 at 10:35 PM, Tom Igoe <> wrote:

> Thanks, Alexander, and sorry for the delay.
>
> A few tests:
>
> For code that doesn't change the strings much, there's not a big
> difference, a couple dozen bytes' difference in code size. However, when
> you start to do dynamic things, it does add up. For example, the
> StringAppendOperator example is 4910 bytes in 0022, and 5148 bytes with the
> StaticDynamicMemory version. So it does start to take its toll, memory-wise.
>
> On some sketches it actually takes less memory. For example, the one below
> is 3738 bytes using the StaticDynamicMemory version, and 3986 bytes in 0022.
> However, it fails entirely on upload. When the value of (analog 0)/4 is
> high (0xFF), it never gets out of the setup(). So there's still a pretty
> easy way to break String, even with these improvements.
>
>
> void setup() {
> Serial.begin(9600);
> Serial.println("Beginning");
> }
>
> void loop() {
>
> String webColor = "#";
>
> int red = analogRead(A0)/4;
> webColor += String(red, HEX);
> int green = analogRead(A1)/4;
> webColor += String(green, HEX);
> int blue = analogRead(A2)/4;
>
> webColor += String(blue, HEX);
> Serial.println(webColor);
> }
>
>
>
>
>
> On Dec 16, 2010, at 1:27 AM, Alexander Brevig wrote:
>
> > Attached is a zip containing WString.h and .cpp plus
> StaticDynamicMemory.h.
> > Take a backup of the original WString files, and extract this zip into
> the hardware/arduino/cores/arduino folder.
> >
> > Now you're ready to test the modified String library, that does not
> fragment the heap.
> >
> >
> > In the WString header there is a #define called STRING_BUFFER which is
> set to 100 for now, change this to suit your test needs.
> >
> >
> > No error handling is implemented, what do you think we need?
> >
> > I plan to add an availableMemory():int method to the SDM library, and
> maybe some error flags and checks like hasError():int error
> >
> > I also suspect that this library is a bit slower performance wise, but I
> think that's just a cost we'll have to pay to being able to play with
> dynamic strings.
> >
> >
> > Hope to get feedback from someone!
> >
> > On Thu, Dec 16, 2010 at 1:11 AM, Alan Burlison <>
> wrote:
> > On 15/12/2010 16:19, David A. Mellis wrote:
> >
> > I think you're right, but I also don't think that telling people to
> > use the standard C library functions is a solution either. Trying out
> > this String class seems like one way of pushing forwards towards a
> > compromise that provides both an easy-to-use API and a robust
> > implementation. For example, perhaps the buffer sizes need to be
> > specified or provided when the String is instantiated. Or we need an
> > alternative implementation that does more reliable memory allocation
> > (since we're not assuming that the internal buffer is continuous).
> > Other ideas welcome.
> >
> > I think the problem is that the failure modes are not benign. I haven't
> been through all the use cases so this might not work, but perhaps using a
> statically-allocated string ("NOMEM" ?) as a sentinel value instead of null
> when malloc fails might be one way? Also, there might be some benefit in
> making String immutable a la Java - overloaded operators in C++ have a
> tendency to generate anonymous temporaries, which is going to lead to heap
> fragmentation as well.
> >
> > --
> > Alan Burlison
> > --
> >
> > _______________________________________________
___________________________________________________

Posted on the Developers mailing list. Go to http://arduino.cc/mailman/listinfo/developers_arduino.cc to subscribe. It broke in the non-SDM version too, but it took longer to break. In the SDM version it breaks immediately. So it looks like whatever you did highlights the faults sooner, which is good. It also points to a need for an error response of some sort, in answer to your question last mail.

t.

On Jan 3, 2011, at 4:44 PM, Alexander Brevig wrote:

> That breaking of String, does it only occur with the SDM version?
>
> If not, did you find any way to break it? Maybe any of the old faults related to memory?
>
>
> I actually have no time to check this myself right now, so I opted to just ask you.
>
> On Mon, Jan 3, 2011 at 10:35 PM, Tom Igoe <> wrote:
> Thanks, Alexander, and sorry for the delay.
>
> A few tests:
>
> For code that doesn't change the strings much, there's not a big difference, a couple dozen bytes' difference in code size. However, when you start to do dynamic things, it does add up. For example, the StringAppendOperator example is 4910 bytes in 0022, and 5148 bytes with the StaticDynamicMemory version. So it does start to take its toll, memory-wise.
>
> On some sketches it actually takes less memory. For example, the one below is 3738 bytes using the StaticDynamicMemory version, and 3986 bytes in 0022. However, it fails entirely on upload. When the value of (analog 0)/4 is high (0xFF), it never gets out of the setup(). So there's still a pretty easy way to break String, even with these improvements.
>
>
> void setup() {
> Serial.begin(9600);
> Serial.println("Beginning");
> }
>
> void loop() {
>
> String webColor = "#";
>
> int red = analogRead(A0)/4;
> webColor += String(red, HEX);
> int green = analogRead(A1)/4;
> webColor += String(green, HEX);
> int blue = analogRead(A2)/4;
>
> webColor += String(blue, HEX);
> Serial.println(webColor);
> }
>
>
>
>
>
> On Dec 16, 2010, at 1:27 AM, Alexander Brevig wrote:
>
> > Attached is a zip containing WString.h and .cpp plus StaticDynamicMemory.h.
> > Take a backup of the original WString files, and extract this zip into the hardware/arduino/cores/arduino folder.
> >
> > Now you're ready to test the modified String library, that does not fragment the heap.
> >
> >
> > In the WString header there is a #define called STRING_BUFFER which is set to 100 for now, change this to suit your test needs.
> >
> >
> > No error handling is implemented, what do you think we need?
> >
> > I plan to add an availableMemory():int method to the SDM library, and maybe some error flags and checks like hasError():int error
> >
> > I also suspect that this library is a bit slower performance wise, but I think that's just a cost we'll have to pay to being able to play with dynamic strings.
> >
> >
> > Hope to get feedback from someone!
> >
> > On Thu, Dec 16, 2010 at 1:11 AM, Alan Burlison <> wrote:
> > On 15/12/2010 16:19, David A. Mellis wrote:
> >
> > I think you're right, but I also don't think that telling people to
> > use the standard C library functions is a solution either. Trying out
> > this String class seems like one way of pushing forwards towards a
> > compromise that provides both an easy-to-use API and a robust
> > implementation. For example, perhaps the buffer sizes need to be
> > specified or provided when the String is instantiated. Or we need an
> > alternative implementation that does more reliable memory allocation
> > (since we're not assuming that the internal buffer is continuous).
> > Other ideas welcome.
> >
> > I think the problem is that the failure modes are not benign. I haven't been through all the use cases so this might not work, but perhaps using a statically-allocated string ("NOMEM" ?) as a sentinel value instead of null when malloc fails might be one way? Also, there might be some benefit in making String immutable a la Java - overloaded operators in C++ have a tendency to generate anonymous temporaries, which is going to lead to heap fragmentation as well.
> >
> > --
> > Alan Burlison
> > --
> >
> > _______________________________________________
___________________________________________________

Posted on the Developers mailing list. Go to http://arduino.cc/mailman/listinfo/developers_arduino.cc to subscribe. There seems to be a bug with the assignment operator, I'm on it and I'll get
back to you as soon as I get something done.

Thank you for your tests and feedback.


I'll do some tests on my own before I repost it here.

On Tue, Jan 4, 2011 at 6:53 PM, Rick Anderson
<>wrote:

> I just created a test and unpacked and tested it. I also created a
> test based on Tom's code. Not sure I caught the maximum value error
> for 0xFF.
>
> I also ran the tests for bug 411. All the tests compile, but there is
> still memory loss.
>
> I'm attaching the Arduino Test suite, and the test code so you can run
> them as you debug. Let me know if this was helpful.
>
> --Rick
>
> Test run results:
> Example: ATS_StringAssignmentTest.pde
> info.MANUFACTURER = Arduino
> info.CPU-NAME = ATmega328P
> info.GCC-Version = 4.3.2
> info.AVR-LibC-Ver = 1.6.4
> info.Compiled-date = Jan 4 2011
> info.Test-Suite-Name = ATS_StringAssignmentTest
> info.Free-memory = 1110 bytes
> Memory Usage (lost 59 bytes) ... FAIL
> --------------------------
> Ran 1 tests in 1.378s
>
> FAILED (failures=1)
>
>
> Example: ATS_StringMemoryTestPassByReference.pde
>
> info.MANUFACTURER = Arduino
> info.CPU-NAME = ATmega328P
> info.GCC-Version = 4.3.2
> info.AVR-LibC-Ver = 1.6.4
> info.Compiled-date = Jan 4 2011
> info.Test-Suite-Name = ATS_StringMemoryTestPassByReference
> info.Free-memory = 1120 bytes
> Memory Usage (lost 59 bytes) ... FAIL
> --------------------------
> Ran 1 tests in 1.389s
>
> FAILED (failures=1)
>
>
> Example: Tom Igoe Memory Test
> info.MANUFACTURER = Arduino
> info.CPU-NAME = ATmega328P
> info.GCC-Version = 4.3.2
> info.AVR-LibC-Ver = 1.6.4
> info.Compiled-date = Jan 4 2011
> info.Test-Suite-Name = Tom Igoe Memory Test
> info.Free-memory = 1328 bytes
> Memory Usage (lost 9 bytes) ... FAIL
> --------------------------
> Ran 1 tests in 1.374s
>
> FAILED (failures=1)
>
>
>
> --Rick
>
> Tom, rewrote your example as a test.
>
> //************************************************************************
> //* Arduino Tom Igoe Memory Test
> //* (C) 2010 by Rick Anderson
> //* Open source as per standard Arduino code
> //*
> //************************************************************************
> //* Jan 4, 2011 Started on Tom Igoe Memory Test
> //************************************************************************
>
> #include "WProgram.h"
> #include "HardwareSerial.h"
> #include
>
> //************************************************************************
> void setup()
> {
> int startMemoryUsage;
> /*
> * Create variable for the tests.
> */
>
> String webColor = "#000000";
>
> int red = 1023/4;
> int blue = 512/4;
> int green = 128/4;
>
> /*
> * initiate the test run
> */
> //Record starting memory amount
> startMemoryUsage = ATS_GetFreeMemory();
> //Begin test run
> ATS_begin("Arduino", "Tom Igoe Memory Test");
>
> webColor = "#";
> webColor += String(red, HEX);
> webColor += String(green, HEX);
> webColor += String(blue, HEX);
>
> ATS_ReportMemoryUsage(startMemoryUsage);
>
> /*
> * Test complete
> */
>
> ATS_end();
> }
>
>
> //************************************************************************
> void loop()
> {
>
>
> }
>
>
>
>
> On Mon, Jan 3, 2011 at 9:35 PM, Tom Igoe <> wrote:
> > It broke in the non-SDM version too, but it took longer to break. In the
> SDM version it breaks immediately. So it looks like whatever you did
> highlights the faults sooner, which is good. It also points to a need for an
> error response of some sort, in answer to your question last mail.
> >
> > t.
> >
> > On Jan 3, 2011, at 4:44 PM, Alexander Brevig wrote:
> >
> >> That breaking of String, does it only occur with the SDM version?
> >>
> >> If not, did you find any way to break it? Maybe any of the old faults
> related to memory?
> >>
> >>
> >> I actually have no time to check this myself right now, so I opted to
> just ask you.
> >>
> >> On Mon, Jan 3, 2011 at 10:35 PM, Tom Igoe <> wrote:
> >> Thanks, Alexander, and sorry for the delay.
> >>
> >> A few tests:
> >>
> >> For code that doesn't change the strings much, there's not a big
> difference, a couple dozen bytes' difference in code size. However, when
> you start to do dynamic things, it does add up. For example, the
> StringAppendOperator example is 4910 bytes in 0022, and 5148 bytes with the
> StaticDynamicMemory version. So it does start to take its toll, memory-wise.
> >>
> >> On some sketches it actually takes less memory. For example, the one
> below is 3738 bytes using the StaticDynamicMemory version, and 3986 bytes in
> 0022. However, it fails entirely on upload. When the value of (analog 0)/4
> is high (0xFF), it never gets out of the setup(). So there's still a pretty
> easy way to break String, even with these improvements.
> >>
> >>
> >> void setup() {
> >> Serial.begin(9600);
> >> Serial.println("Beginning");
> >> }
> >>
> >> void loop() {
> >>
> >> String webColor = "#";
> >>
> >> int red = analogRead(A0)/4;
> >> webColor += String(red, HEX);
> >> int green = analogRead(A1)/4;
> >> webColor += String(green, HEX);
> >> int blue = analogRead(A2)/4;
> >>
> >> webColor += String(blue, HEX);
> >> Serial.println(webColor);
> >> }
> >>
> >>
> >>
> >>
> >>
> >> On Dec 16, 2010, at 1:27 AM, Alexander Brevig wrote:
> >>
> >> > Attached is a zip containing WString.h and .cpp plus
> StaticDynamicMemory.h.
> >> > Take a backup of the original WString files, and extract this zip into
> the hardware/arduino/cores/arduino folder.
> >> >
> >> > Now you're ready to test the modified String library, that does not
> fragment the heap.
> >> >
> >> >
> >> > In the WString header there is a #define called STRING_BUFFER which is
> set to 100 for now, change this to suit your test needs.
> >> >
> >> >
> >> > No error handling is implemented, what do you think we need?
> >> >
> >> > I plan to add an availableMemory():int method to the SDM library, and
> maybe some error flags and checks like hasError():int error
> >> >
> >> > I also suspect that this library is a bit slower performance wise, but
> I think that's just a cost we'll have to pay to being able to play with
> dynamic strings.
> >> >
> >> >
> >> > Hope to get feedback from someone!
> >> >
> >> > On Thu, Dec 16, 2010 at 1:11 AM, Alan Burlison <
> > wrote:
> >> > On 15/12/2010 16:19, David A. Mellis wrote:
> >> >
> >> > I think you're right, but I also don't think that telling people to
> >> > use the standard C library functions is a solution either. Trying out
> >> > this String class seems like one way of pushing forwards towards a
> >> > compromise that provides both an easy-to-use API and a robust
> >> > implementation. For example, perhaps the buffer sizes need to be
> >> > specified or provided when the String is instantiated. Or we need an
> >> > alternative implementation that does more reliable memory allocation
> >> > (since we're not assuming that the internal buffer is continuous).
> >> > Other ideas welcome.
> >> >
> >> > I think the problem is that the failure modes are not benign. I
> haven't been through all the use cases so this might not work, but perhaps
> using a statically-allocated string ("NOMEM" ?) as a sentinel value instead
> of null when malloc fails might be one way? Also, there might be some
> benefit in making String immutable a la Java - overloaded operators in C++
> have a tendency to generate anonymous temporaries, which is going to lead to
> heap fragmentation as well.
> >> >
> >> > --
> >> > Alan Burlison
> >> > --
> >> >
> >> > _______________________________________________
___________________________________________________

Posted on the Developers mailing list. Go to http://arduino.cc/mailman/listinfo/developers_arduino.cc to subscribe. Is this test suite any different than the one in the github repo?

t.

On Jan 4, 2011, at 12:53 PM, Rick Anderson wrote:

> I just created a test and unpacked and tested it. I also created a
> test based on Tom's code. Not sure I caught the maximum value error
> for 0xFF.
>
> I also ran the tests for bug 411. All the tests compile, but there is
> still memory loss.
>
> I'm attaching the Arduino Test suite, and the test code so you can run
> them as you debug. Let me know if this was helpful.
>
> --Rick
>
> Test run results:
> Example: ATS_StringAssignmentTest.pde
> info.MANUFACTURER = Arduino
> info.CPU-NAME = ATmega328P
> info.GCC-Version = 4.3.2
> info.AVR-LibC-Ver = 1.6.4
> info.Compiled-date = Jan 4 2011
> info.Test-Suite-Name = ATS_StringAssignmentTest
> info.Free-memory = 1110 bytes
> Memory Usage (lost 59 bytes) ... FAIL
> --------------------------
> Ran 1 tests in 1.378s
>
> FAILED (failures=1)
>
>
> Example: ATS_StringMemoryTestPassByReference.pde
>
> info.MANUFACTURER = Arduino
> info.CPU-NAME = ATmega328P
> info.GCC-Version = 4.3.2
> info.AVR-LibC-Ver = 1.6.4
> info.Compiled-date = Jan 4 2011
> info.Test-Suite-Name = ATS_StringMemoryTestPassByReference
> info.Free-memory = 1120 bytes
> Memory Usage (lost 59 bytes) ... FAIL
> --------------------------
> Ran 1 tests in 1.389s
>
> FAILED (failures=1)
>
>
> Example: Tom Igoe Memory Test
> info.MANUFACTURER = Arduino
> info.CPU-NAME = ATmega328P
> info.GCC-Version = 4.3.2
> info.AVR-LibC-Ver = 1.6.4
> info.Compiled-date = Jan 4 2011
> info.Test-Suite-Name = Tom Igoe Memory Test
> info.Free-memory = 1328 bytes
> Memory Usage (lost 9 bytes) ... FAIL
> --------------------------
> Ran 1 tests in 1.374s
>
> FAILED (failures=1)
>
>
>
> --Rick
>
> Tom, rewrote your example as a test.
>
> //************************************************************************
> //* Arduino Tom Igoe Memory Test
> //* (C) 2010 by Rick Anderson
> //* Open source as per standard Arduino code
> //*
> //************************************************************************
> //* Jan 4, 2011 Started on Tom Igoe Memory Test
> //************************************************************************
>
> #include "WProgram.h"
> #include "HardwareSerial.h"
> #include
>
> //************************************************************************
> void setup()
> {
> int startMemoryUsage;
> /*
> * Create variable for the tests.
> */
>
> String webColor = "#000000";
>
> int red = 1023/4;
> int blue = 512/4;
> int green = 128/4;
>
> /*
> * initiate the test run
> */
> //Record starting memory amount
> startMemoryUsage = ATS_GetFreeMemory();
> //Begin test run
> ATS_begin("Arduino", "Tom Igoe Memory Test");
>
> webColor = "#";
> webColor += String(red, HEX);
> webColor += String(green, HEX);
> webColor += String(blue, HEX);
>
> ATS_ReportMemoryUsage(startMemoryUsage);
>
> /*
> * Test complete
> */
>
> ATS_end();
> }
>
>
> //************************************************************************
> void loop()
> {
>
>
> }
>
>
>
>
> On Mon, Jan 3, 2011 at 9:35 PM, Tom Igoe <> wrote:
>> It broke in the non-SDM version too, but it took longer to break. In the SDM version it breaks immediately. So it looks like whatever you did highlights the faults sooner, which is good. It also points to a need for an error response of some sort, in answer to your question last mail.
>>
>> t.
>>
>> On Jan 3, 2011, at 4:44 PM, Alexander Brevig wrote:
>>
>>> That breaking of String, does it only occur with the SDM version?
>>>
>>> If not, did you find any way to break it? Maybe any of the old faults related to memory?
>>>
>>>
>>> I actually have no time to check this myself right now, so I opted to just ask you.
>>>
>>> On Mon, Jan 3, 2011 at 10:35 PM, Tom Igoe <> wrote:
>>> Thanks, Alexander, and sorry for the delay.
>>>
>>> A few tests:
>>>
>>> For code that doesn't change the strings much, there's not a big difference, a couple dozen bytes' difference in code size. However, when you start to do dynamic things, it does add up. For example, the StringAppendOperator example is 4910 bytes in 0022, and 5148 bytes with the StaticDynamicMemory version. So it does start to take its toll, memory-wise.
>>>
>>> On some sketches it actually takes less memory. For example, the one below is 3738 bytes using the StaticDynamicMemory version, and 3986 bytes in 0022. However, it fails entirely on upload. When the value of (analog 0)/4 is high (0xFF), it never gets out of the setup(). So there's still a pretty easy way to break String, even with these improvements.
>>>
>>>
>>> void setup() {
>>> Serial.begin(9600);
>>> Serial.println("Beginning");
>>> }
>>>
>>> void loop() {
>>>
>>> String webColor = "#";
>>>
>>> int red = analogRead(A0)/4;
>>> webColor += String(red, HEX);
>>> int green = analogRead(A1)/4;
>>> webColor += String(green, HEX);
>>> int blue = analogRead(A2)/4;
>>>
>>> webColor += String(blue, HEX);
>>> Serial.println(webColor);
>>> }
>>>
>>>
>>>
>>>
>>>
>>> On Dec 16, 2010, at 1:27 AM, Alexander Brevig wrote:
>>>
>>>> Attached is a zip containing WString.h and .cpp plus StaticDynamicMemory.h.
>>>> Take a backup of the original WString files, and extract this zip into the hardware/arduino/cores/arduino folder.
>>>>
>>>> Now you're ready to test the modified String library, that does not fragment the heap.
>>>>
>>>>
>>>> In the WString header there is a #define called STRING_BUFFER which is set to 100 for now, change this to suit your test needs.
>>>>
>>>>
>>>> No error handling is implemented, what do you think we need?
>>>>
>>>> I plan to add an availableMemory():int method to the SDM library, and maybe some error flags and checks like hasError():int error
>>>>
>>>> I also suspect that this library is a bit slower performance wise, but I think that's just a cost we'll have to pay to being able to play with dynamic strings.
>>>>
>>>>
>>>> Hope to get feedback from someone!
>>>>
>>>> On Thu, Dec 16, 2010 at 1:11 AM, Alan Burlison <> wrote:
>>>> On 15/12/2010 16:19, David A. Mellis wrote:
>>>>
>>>> I think you're right, but I also don't think that telling people to
>>>> use the standard C library functions is a solution either. Trying out
>>>> this String class seems like one way of pushing forwards towards a
>>>> compromise that provides both an easy-to-use API and a robust
>>>> implementation. For example, perhaps the buffer sizes need to be
>>>> specified or provided when the String is instantiated. Or we need an
>>>> alternative implementation that does more reliable memory allocation
>>>> (since we're not assuming that the internal buffer is continuous).
>>>> Other ideas welcome.
>>>>
>>>> I think the problem is that the failure modes are not benign. I haven't been through all the use cases so this might not work, but perhaps using a statically-allocated string ("NOMEM" ?) as a sentinel value instead of null when malloc fails might be one way? Also, there might be some benefit in making String immutable a la Java - overloaded operators in C++ have a tendency to generate anonymous temporaries, which is going to lead to heap fragmentation as well.
>>>>
>>>> --
>>>> Alan Burlison
>>>> --
>>>>
>>>> _______________________________________________
___________________________________________________

Posted on the Developers mailing list. Go to http://arduino.cc/mailman/listinfo/developers_arduino.cc to subscribe. Same exact one. I just included it just in case.

--Rick

On Tue, Jan 4, 2011 at 9:01 PM, Tom Igoe <> wrote:
> Is this test suite any different than the one in the github repo?
>
> t.
>
> On Jan 4, 2011, at 12:53 PM, Rick Anderson wrote:
>
>> I just created a test and unpacked and tested it. I also created a
>> test based on Tom's code. Not sure I caught the maximum value error
>> for 0xFF.
>>
>> I also ran the tests for bug 411. All the tests compile, but there is
>> still memory loss.
>>
>> I'm attaching the Arduino Test suite, and the test code so you can run
>> them as you debug. Let me know if this was helpful.
>>
>> --Rick
>>
>> Test run results:
>> Example:  ATS_StringAssignmentTest.pde
>> info.MANUFACTURER    = Arduino
>> info.CPU-NAME        = ATmega328P
>> info.GCC-Version     = 4.3.2
>> info.AVR-LibC-Ver    = 1.6.4
>> info.Compiled-date   = Jan  4 2011
>> info.Test-Suite-Name = ATS_StringAssignmentTest
>> info.Free-memory     = 1110 bytes
>> Memory Usage (lost 59 bytes)                                ... FAIL
>> --------------------------
>> Ran 1 tests in 1.378s
>>
>> FAILED (failures=1)
>>
>>
>> Example: ATS_StringMemoryTestPassByReference.pde
>>
>> info.MANUFACTURER    = Arduino
>> info.CPU-NAME        = ATmega328P
>> info.GCC-Version     = 4.3.2
>> info.AVR-LibC-Ver    = 1.6.4
>> info.Compiled-date   = Jan  4 2011
>> info.Test-Suite-Name = ATS_StringMemoryTestPassByReference
>> info.Free-memory     = 1120 bytes
>> Memory Usage (lost 59 bytes)                                ... FAIL
>> --------------------------
>> Ran 1 tests in 1.389s
>>
>> FAILED (failures=1)
>>
>>
>> Example: Tom Igoe Memory Test
>> info.MANUFACTURER    = Arduino
>> info.CPU-NAME        = ATmega328P
>> info.GCC-Version     = 4.3.2
>> info.AVR-LibC-Ver    = 1.6.4
>> info.Compiled-date   = Jan  4 2011
>> info.Test-Suite-Name = Tom Igoe Memory Test
>> info.Free-memory     = 1328 bytes
>> Memory Usage (lost 9 bytes)                                 ... FAIL
>> --------------------------
>> Ran 1 tests in 1.374s
>>
>> FAILED (failures=1)
>>
>>
>>
>> --Rick
>>
>> Tom, rewrote your example as a test.
>>
>> //************************************************************************
>> //*   Arduino Tom Igoe Memory Test
>> //*           (C) 2010 by Rick Anderson
>> //*           Open source as per standard Arduino code
>> //*
>> //************************************************************************
>> //*   Jan 4,  2011     Started on Tom Igoe Memory Test
>> //************************************************************************
>>
>> #include      "WProgram.h"
>> #include      "HardwareSerial.h"
>> #include      
>>
>> //************************************************************************
>> void setup()
>> {
>>  int          startMemoryUsage;
>>  /*
>>    * Create variable for the tests.
>>   */
>>
>>  String webColor = "#000000";
>>
>>  int red = 1023/4;
>>  int blue = 512/4;
>>  int green = 128/4;
>>
>>  /*
>>  * initiate the test run
>>   */
>>  //Record starting memory amount
>>  startMemoryUsage     =       ATS_GetFreeMemory();
>>  //Begin test run
>>  ATS_begin("Arduino", "Tom Igoe Memory Test");
>>
>>  webColor = "#";
>>  webColor += String(red, HEX);
>>  webColor += String(green, HEX);
>>  webColor += String(blue, HEX);
>>
>>  ATS_ReportMemoryUsage(startMemoryUsage);
>>
>>  /*
>>   * Test complete
>>   */
>>
>>  ATS_end();
>> }
>>
>>
>> //************************************************************************
>> void loop()
>> {
>>
>>
>> }
>>
>>
>>
>>
>> On Mon, Jan 3, 2011 at 9:35 PM, Tom Igoe <> wrote:
>>> It broke in the non-SDM version too, but it took longer to break. In the SDM version it breaks immediately. So it looks like whatever you did highlights the faults sooner, which is good. It also points to a need for an error response of some sort, in answer to your question last mail.
>>>
>>> t.
>>>
>>> On Jan 3, 2011, at 4:44 PM, Alexander Brevig wrote:
>>>
>>>> That breaking of String, does it only occur with the SDM version?
>>>>
>>>> If not, did you find any way to break it? Maybe any of the old faults related to memory?
>>>>
>>>>
>>>> I actually have no time to check this myself right now, so I opted to just ask you.
>>>>
>>>> On Mon, Jan 3, 2011 at 10:35 PM, Tom Igoe <> wrote:
>>>> Thanks, Alexander, and sorry for the delay.
>>>>
>>>> A few tests:
>>>>
>>>> For code that doesn't change the strings much, there's not a big difference, a couple dozen bytes' difference in code size.  However, when you start to do dynamic things, it does add up.  For example, the StringAppendOperator example is  4910 bytes in 0022, and 5148 bytes with the StaticDynamicMemory version. So it does start to take its toll, memory-wise.
>>>>
>>>> On some sketches it actually takes less memory.  For example, the one below is 3738 bytes using the StaticDynamicMemory version, and 3986 bytes in 0022.  However, it fails entirely on upload.  When the value of (analog 0)/4 is high (0xFF), it never gets out of the setup(). So there's still a pretty easy way to break String, even with these improvements.
>>>>
>>>>
>>>> void setup() {
>>>>  Serial.begin(9600);
>>>>  Serial.println("Beginning");
>>>> }
>>>>
>>>> void loop() {
>>>>
>>>>  String webColor = "#";
>>>>
>>>>  int red = analogRead(A0)/4;
>>>>  webColor += String(red, HEX);
>>>>  int green = analogRead(A1)/4;
>>>>  webColor += String(green, HEX);
>>>>  int blue = analogRead(A2)/4;
>>>>
>>>>  webColor += String(blue, HEX);
>>>>  Serial.println(webColor);
>>>> }
>>>>
>>>>
>>>>
>>>>
>>>>
>>>> On Dec 16, 2010, at 1:27 AM, Alexander Brevig wrote:
>>>>
>>>>> Attached is a zip containing WString.h and .cpp plus StaticDynamicMemory.h.
>>>>> Take a backup of the original WString files, and extract this zip into the hardware/arduino/cores/arduino folder.
>>>>>
>>>>> Now you're ready to test the modified String library, that does not fragment the heap.
>>>>>
>>>>>
>>>>> In the WString header there is a #define called STRING_BUFFER which is set to 100 for now, change this to suit your test needs.
>>>>>
>>>>>
>>>>> No error handling is implemented, what do you think we need?
>>>>>
>>>>> I plan to add an availableMemory():int method to the SDM library, and maybe some error flags and checks like hasError():int error
>>>>>
>>>>> I also suspect that this library is a bit slower performance wise, but I think that's just a cost we'll have to pay to being able to play with dynamic strings.
>>>>>
>>>>>
>>>>> Hope to  get feedback from someone!
>>>>>
>>>>> On Thu, Dec 16, 2010 at 1:11 AM, Alan Burlison <> wrote:
>>>>> On 15/12/2010 16:19, David A. Mellis wrote:
>>>>>
>>>>> I think you're right, but I also don't think that telling people to
>>>>> use the standard C library functions is a solution either.  Trying out
>>>>> this String class seems like one way of pushing forwards towards a
>>>>> compromise that provides both an easy-to-use API and a robust
>>>>> implementation.  For example, perhaps the buffer sizes need to be
>>>>> specified or provided when the String is instantiated.  Or we need an
>>>>> alternative implementation that does more reliable memory allocation
>>>>> (since we're not assuming that the internal buffer is continuous).
>>>>> Other ideas welcome.
>>>>>
>>>>> I think the problem is that the failure modes are not benign.  I haven't been through all the use cases so this might not work, but perhaps using a statically-allocated string ("NOMEM" ?) as a sentinel value instead of null when malloc fails might be one way?  Also, there might be some benefit in making String immutable a la Java - overloaded operators in C++ have a tendency to generate anonymous temporaries, which is going to lead to heap fragmentation as well.
>>>>>
>>>>> --
>>>>> Alan Burlison
>>>>> --
>>>>>
>>>>> _______________________________________________
___________________________________________________

Posted on the Developers mailing list. Go to http://arduino.cc/mailman/listinfo/developers_arduino.cc to subscribe. On 04/01/2011 17:53, Rick Anderson wrote:

> I also ran the tests for bug 411. All the tests compile, but there is
> still memory loss.

Most of the assumptions made by the test harness and test case code are
wrong, any reports of 'lost' memory are therefore likely to be wrong as
well. If you want to do leak detection you can't do it in the naive way
it is being done at present.

--
Alan Burlison
--

_______________________________________________
___________________________________________________

Posted on the Developers mailing list. Go to http://arduino.cc/mailman/listinfo/developers_arduino.cc to subscribe. Alan,

The tests themselves are quick and dirty, and not strategic or
comprehensive. I'd like your input to create a good procedure for
memory testing. I also have feedback from Paul Stoffregen for the test
suite:
----
Another problem involves gcc's optimizer ignoring the inline request
for ATS_ReportMemoryUsage. As the comment in the code explains, it
must be inline to avoid measuring its own stack frame. I believe
adding this line in ArduinoTestSuite.h fixes the problem by forcing
gcc to inline.

inline void ATS_ReportMemoryUsage(int _memoryUsageAtStart)
__attribute__((always_inline, unused));

The last problem is a tiny bit of dynamic memory permanently held for
the free list. To allow for this, the test really should call
malloc() and free() once, so the allocator is fully initialized before
testing.
----

I'd like to combine both sets of feedback, and set up some issues in
the system, then fix them. Is the above the problem you saw? Are their
other assumptions that would impact measuring memory? And updating the
memory test in the the test suite.

In terms of creating tests for memory leaks. It looks best to move all
the memory usage inside a function. What else could be done to
constrain the problem, and measuring more affectively.

I'm traveling back to NJ today, so I can't respond right away.

--Rick

On Wed, Jan 5, 2011 at 8:52 AM, Alan Burlison <> wrote:
> On 04/01/2011 17:53, Rick Anderson wrote:
>
>> I also ran the tests for bug 411. All the tests compile, but there is
>> still memory loss.
>
> Most of the assumptions made by the test harness and test case code are
> wrong, any reports of 'lost' memory are therefore likely to be wrong as
> well.  If you want to do leak detection you can't do it in the naive way it
> is being done at present.
>
> --
> Alan Burlison
> --
>



--
President
Fair Use Building and Research (****) Labs
http://fubarlabs.org

_______________________________________________
___________________________________________________

Posted on the Developers mailing list. Go to http://arduino.cc/mailman/listinfo/developers_arduino.cc to subscribe. On 05/01/2011 15:19, Rick Anderson wrote:

> ----
> Another problem involves gcc's optimizer ignoring the inline request
> for ATS_ReportMemoryUsage. As the comment in the code explains, it
> must be inline to avoid measuring its own stack frame. I believe
> adding this line in ArduinoTestSuite.h fixes the problem by forcing
> gcc to inline.
>
> inline void ATS_ReportMemoryUsage(int _memoryUsageAtStart)
> __attribute__((always_inline, unused));

Yes, that's one of the problems. And even the __attribute__
'workaround' is a fragile hack.

> The last problem is a tiny bit of dynamic memory permanently held for
> the free list. To allow for this, the test really should call
> malloc() and free() once, so the allocator is fully initialized before

That's part of a problem, but an initial call malloc/free call isn't
guaranteed to make all the issues go away either. From looking at the
avr-libc malloc implementation it does try to coalesce the heap, but
relying on multiple malloc implementation artefacts is a really bad idea
- there's no guarantee that future malloc implementations will always
coalesce on every free, and there's no guarantee that __bss_end or
__brkval will always be adjusted on each malloc/free call.

The other issue is that of object lifetimes. The test code has
instances of String objects which are allocated on the stack and that
are still in scope when the 'leak' memory check is performed. That
means the String destructors won't have been called and the dynamically
allocated part of the String will still be allocated.

A true memory leak is a block of allocated memory that has no references
to it. However that's not what the test code is checking for. If a
library routine used malloc to perform a one-time library-private buffer
allocation where the buffer is retained for the lifetime of the program,
the current leak checking would incorrectly report that as a leak. It
isn't a leak because there's still a reference to the block inside the
library.

The only semi-reliable way to do what you want is to use an instrumented
malloc implementation, and that's going to be very difficult to
implement on a constrained platform such as the AVR. If you want to
test the String implementation for leaks, my advice is to do it on a
more capable platform (e.g. *nix) and use one of the many instrumented
mallocs that are available.

--
Alan Burlison
--

_______________________________________________
___________________________________________________

Posted on the Developers mailing list. Go to http://arduino.cc/mailman/listinfo/developers_arduino.cc to subscribe. Slightly unrelated to what you guys are discussing now but:
I'm not sure if I've made this clear, but the new version of String that I'm
working on now does not use malloc or any other c function for dynamic
memory. What happens is that I allocate memory statically on the stack and
serve that memory dynamically to the instances of String.

I have some time on my hands now and have a look at getting the += not to
break the code

On Wed, Jan 5, 2011 at 7:10 PM, Alan Burlison <>wrote:

> On 05/01/2011 15:19, Rick Anderson wrote:
>
> ----
>> Another problem involves gcc's optimizer ignoring the inline request
>> for ATS_ReportMemoryUsage. As the comment in the code explains, it
>> must be inline to avoid measuring its own stack frame. I believe
>> adding this line in ArduinoTestSuite.h fixes the problem by forcing
>> gcc to inline.
>>
>> inline void ATS_ReportMemoryUsage(int _memoryUsageAtStart)
>> __attribute__((always_inline, unused));
>>
>
> Yes, that's one of the problems. And even the __attribute__ 'workaround'
> is a fragile hack.
>
>
> The last problem is a tiny bit of dynamic memory permanently held for
>> the free list. To allow for this, the test really should call
>> malloc() and free() once, so the allocator is fully initialized before
>>
>
> That's part of a problem, but an initial call malloc/free call isn't
> guaranteed to make all the issues go away either. From looking at the
> avr-libc malloc implementation it does try to coalesce the heap, but relying
> on multiple malloc implementation artefacts is a really bad idea - there's
> no guarantee that future malloc implementations will always coalesce on
> every free, and there's no guarantee that __bss_end or __brkval will always
> be adjusted on each malloc/free call.
>
> The other issue is that of object lifetimes. The test code has instances
> of String objects which are allocated on the stack and that are still in
> scope when the 'leak' memory check is performed. That means the String
> destructors won't have been called and the dynamically allocated part of the
> String will still be allocated.
>
> A true memory leak is a block of allocated memory that has no references to
> it. However that's not what the test code is checking for. If a library
> routine used malloc to perform a one-time library-private buffer allocation
> where the buffer is retained for the lifetime of the program, the current
> leak checking would incorrectly report that as a leak. It isn't a leak
> because there's still a reference to the block inside the library.
>
> The only semi-reliable way to do what you want is to use an instrumented
> malloc implementation, and that's going to be very difficult to implement on
> a constrained platform such as the AVR. If you want to test the String
> implementation for leaks, my advice is to do it on a more capable platform
> (e.g. *nix) and use one of the many instrumented mallocs that are available.
>
> --
> Alan Burlison
> --
>
>
> _______________________________________________
___________________________________________________

Posted on the Developers mailing list. Go to http://arduino.cc/mailman/listinfo/developers_arduino.cc to subscribe. On 05/01/2011 18:25, Alexander Brevig wrote:

> Slightly unrelated to what you guys are discussing now but:
> I'm not sure if I've made this clear, but the new version of String that I'm
> working on now does not use malloc or any other c function for dynamic
> memory. What happens is that I allocate memory statically on the stack and
> serve that memory dynamically to the instances of String.

Does that mean that the total space occupied by all Strings has to be
decided up front? If so, what is the behaviour when an allocation fails?

To be honest I don't really see the point of doing this - all you are
doing is re-implementing malloc.

--
Alan Burlison
--

_______________________________________________
___________________________________________________

Posted on the Developers mailing list. Go to http://arduino.cc/mailman/listinfo/developers_arduino.cc to subscribe. No, actually I am not reimplementing malloc, because my algorithm guarantees
no fragmentation and always 100% effective use of the allocated memory.

"Does that mean that the total space occupied by all Strings has to be
decided up front? "
Yes, just like the buffer for the serial ++

I know I would opt to have the restriction for a predetermined allocated
space WITH error reporting (how we do is up to you guys, feed me with ideas
I'll implement whatever we agree is best) than having
seemingly infinite memory that crashes and burns.

On Wed, Jan 5, 2011 at 7:33 PM, Alan Burlison <>wrote:

> On 05/01/2011 18:25, Alexander Brevig wrote:
>
> Slightly unrelated to what you guys are discussing now but:
>> I'm not sure if I've made this clear, but the new version of String that
>> I'm
>> working on now does not use malloc or any other c function for dynamic
>> memory. What happens is that I allocate memory statically on the stack and
>> serve that memory dynamically to the instances of String.
>>
>
> Does that mean that the total space occupied by all Strings has to be
> decided up front? If so, what is the behaviour when an allocation fails?
>
> To be honest I don't really see the point of doing this - all you are doing
> is re-implementing malloc.
>
> --
> Alan Burlison
> --
> Well, that was easy (seemingly, probably just jinxed myself...) but here the
test does no longer break, and the usage of memory never exceeds 11 bytes.

It would be awesome if someone would test it.


Also, please tell me now if this effort will lead to nowhere. Is the cost of
being constrained to a buffer size a deal-breaker?

On Wed, Jan 5, 2011 at 7:42 PM, Alexander Brevig
<>wrote:

> No, actually I am not reimplementing malloc, because my algorithm
> guarantees no fragmentation and always 100% effective use of the allocated
> memory.
>
> "Does that mean that the total space occupied by all Strings has to be
> decided up front? "
> Yes, just like the buffer for the serial ++
>
> I know I would opt to have the restriction for a predetermined allocated
> space WITH error reporting (how we do is up to you guys, feed me with ideas
> I'll implement whatever we agree is best) than having
> seemingly infinite memory that crashes and burns.
>
> On Wed, Jan 5, 2011 at 7:33 PM, Alan Burlison <>wrote:
>
>> On 05/01/2011 18:25, Alexander Brevig wrote:
>>
>> Slightly unrelated to what you guys are discussing now but:
>>> I'm not sure if I've made this clear, but the new version of String that
>>> I'm
>>> working on now does not use malloc or any other c function for dynamic
>>> memory. What happens is that I allocate memory statically on the stack
>>> and
>>> serve that memory dynamically to the instances of String.
>>>
>>
>> Does that mean that the total space occupied by all Strings has to be
>> decided up front? If so, what is the behaviour when an allocation fails?
>>
>> To be honest I don't really see the point of doing this - all you are
>> doing is re-implementing malloc.
>>
>> --
>> Alan Burlison
>> --
>>
>
> So sorry you all! I shipped my test code (for msvc++ compiler) in five
minutes I'll post an arduino compatible version. So sorry for this spam!

On Wed, Jan 5, 2011 at 8:01 PM, Alexander Brevig
<>wrote:

> Well, that was easy (seemingly, probably just jinxed myself...) but here
> the test does no longer break, and the usage of memory never exceeds 11
> bytes.
>
> It would be awesome if someone would test it.
>
>
> Also, please tell me now if this effort will lead to nowhere. Is the cost
> of being constrained to a buffer size a deal-breaker?
>
>
> On Wed, Jan 5, 2011 at 7:42 PM, Alexander Brevig <
> > wrote:
>
>> No, actually I am not reimplementing malloc, because my algorithm
>> guarantees no fragmentation and always 100% effective use of the allocated
>> memory.
>>
>> "Does that mean that the total space occupied by all Strings has to be
>> decided up front? "
>> Yes, just like the buffer for the serial ++
>>
>> I know I would opt to have the restriction for a predetermined allocated
>> space WITH error reporting (how we do is up to you guys, feed me with ideas
>> I'll implement whatever we agree is best) than having
>> seemingly infinite memory that crashes and burns.
>>
>> On Wed, Jan 5, 2011 at 7:33 PM, Alan Burlison <>wrote:
>>
>>> On 05/01/2011 18:25, Alexander Brevig wrote:
>>>
>>> Slightly unrelated to what you guys are discussing now but:
>>>> I'm not sure if I've made this clear, but the new version of String that
>>>> I'm
>>>> working on now does not use malloc or any other c function for dynamic
>>>> memory. What happens is that I allocate memory statically on the stack
>>>> and
>>>> serve that memory dynamically to the instances of String.
>>>>
>>>
>>> Does that mean that the total space occupied by all Strings has to be
>>> decided up front? If so, what is the behaviour when an allocation fails?
>>>
>>> To be honest I don't really see the point of doing this - all you are
>>> doing is re-implementing malloc.
>>>
>>> --
>>> Alan Burlison
>>> --
>>>
>>
>>
> > The other issue is that of object lifetimes. The test code has
> instances of String objects which are allocated on the stack and that
> are still in scope when the 'leak' memory check is performed.

That was also in my (off list) email a few days ago, though that bit
didn't make it here.

I believe the plan is to move the tests and object(s) they use to a
function, so the objects will be out of scope when the memory check is made.

There might also another copy of the test which pre-allocates a string
large enough to hold all the data. I'm not sure exactly how I feel
about that approach, but it seems like at least worth trying. Currently
the string library does not have a reserve() function. I've proposed it
before, and today I put it in issue #449.

> If a library routine used malloc to perform a one-time library-private
> buffer allocation where the buffer is retained for the lifetime of the
> program, the current leak checking would incorrectly report that as a
> leak. It isn't a leak because there's still a reference to the block
> inside the library.

Yes, you are correct, the test makes some assumptions about the internal
implementation, and yes, an ideal test wouldn't make any such
assumptions, and yes, it's probably impractical to completely avoid
assumptions on such limited hardware.

But there's a lot of value in actually testing on the real hardware,
with all its limitations and slight differences from running on a PC.
Personally, I think making some assumptions is a pretty good trade-off
for testing in the actual environment. Of course, there's plenty of
room for smart ideas to minimize such assumptions, or perhaps test in
multiple ways.

As someone who's spent a lot of time coding on the string class (and has
more planned), the real value isn't a perfect score if my code is bug
free, but rather a FAIL coming up when I make some mistake that
unexpectedly breaks something. Sure it's annoying if a FAIL comes up
erroneously because the internal implementation changed,

There are so many functions, with so many cases, that subtle errors can
happen (eg, does lastIndexOf work when the search string is the entire
original string... I broke that recently, but everything else worked.....)

If you have ideas about how to catch more types of errors, even if
imperfect, I'd really love to hear.




>
>
> The only semi-reliable way to do what you want is to use an
> instrumented malloc implementation, and that's going to be very
> difficult to implement on a constrained platform such as the AVR. If
> you want to test the String implementation for leaks, my advice is to
> do it on a more capable platform (e.g. *nix) and use one of the many
> instrumented mallocs that are available.
>


_______________________________________________
___________________________________________________

Posted on the Developers mailing list. Go to http://arduino.cc/mailman/listinfo/developers_arduino.cc to subscribe. I'm not sure I follow, string.read(); what would that do?
How do you imagine String to use Stream ? :)

Attached: new version arduino compitable

On Wed, Jan 5, 2011 at 8:20 PM, Tom Igoe <> wrote:

> Could you then just use Stream as a basis for String? Sorry, I didn't look
> into the details of your DMA class, but as long as we're setting a limit to
> begin with, and if we know Stream's pretty solid, why not restructure String
> a bit to use it?
>
> t.
>
>
> On Jan 5, 2011, at 1:42 PM, Alexander Brevig wrote:
>
> > No, actually I am not reimplementing malloc, because my algorithm
> guarantees no fragmentation and always 100% effective use of the allocated
> memory.
> >
> > "Does that mean that the total space occupied by all Strings has to be
> decided up front? "
> > Yes, just like the buffer for the serial ++
> >
> > I know I would opt to have the restriction for a predetermined allocated
> space WITH error reporting (how we do is up to you guys, feed me with ideas
> I'll implement whatever we agree is best) than having seemingly infinite
> memory that crashes and burns.
> >
> > On Wed, Jan 5, 2011 at 7:33 PM, Alan Burlison <>
> wrote:
> > On 05/01/2011 18:25, Alexander Brevig wrote:
> >
> > Slightly unrelated to what you guys are discussing now but:
> > I'm not sure if I've made this clear, but the new version of String that
> I'm
> > working on now does not use malloc or any other c function for dynamic
> > memory. What happens is that I allocate memory statically on the stack
> and
> > serve that memory dynamically to the instances of String.
> >
> > Does that mean that the total space occupied by all Strings has to be
> decided up front? If so, what is the behaviour when an allocation fails?
> >
> > To be honest I don't really see the point of doing this - all you are
> doing is re-implementing malloc.
> >
> > --
> > Alan Burlison
> > --
> >
> > _______________________________________________
___________________________________________________

Posted on the Developers mailing list. Go to http://arduino.cc/mailman/listinfo/developers_arduino.cc to subscribe. > I'm not sure I follow, string.read(); what would that do?
> How do you imagine String to use Stream ? :)

I also do not understand? In fact, I'm completely mystified. Please
explain...

But I would like to let you know I've been working on debugging the
string class, and in the last few days together with the test suite.
I'll likely post code sometimes next week.


>
> Attached: new version arduino compitable
>
> On Wed, Jan 5, 2011 at 8:20 PM, Tom Igoe <
> > wrote:
>
> Could you then just use Stream as a basis for String? Sorry, I
> didn't look into the details of your DMA class, but as long as
> we're setting a limit to begin with, and if we know Stream's
> pretty solid, why not restructure String a bit to use it?
>
> t.
>
>
> On Jan 5, 2011, at 1:42 PM, Alexander Brevig wrote:
>
> > No, actually I am not reimplementing malloc, because my
> algorithm guarantees no fragmentation and always 100% effective
> use of the allocated memory.
> >
> > "Does that mean that the total space occupied by all Strings has
> to be decided up front? "
> > Yes, just like the buffer for the serial ++
> >
> > I know I would opt to have the restriction for a predetermined
> allocated space WITH error reporting (how we do is up to you guys,
> feed me with ideas I'll implement whatever we agree is best) than
> having seemingly infinite memory that crashes and burns.
> >
> > On Wed, Jan 5, 2011 at 7:33 PM, Alan Burlison
> < > wrote:
> > On 05/01/2011 18:25, Alexander Brevig wrote:
> >
> > Slightly unrelated to what you guys are discussing now but:
> > I'm not sure if I've made this clear, but the new version of
> String that I'm
> > working on now does not use malloc or any other c function for
> dynamic
> > memory. What happens is that I allocate memory statically on the
> stack and
> > serve that memory dynamically to the instances of String.
> >
> > Does that mean that the total space occupied by all Strings has
> to be decided up front? If so, what is the behaviour when an
> allocation fails?
> >
> > To be honest I don't really see the point of doing this - all
> you are doing is re-implementing malloc.
> >
> > --
> > Alan Burlison
> > --
> >
> > _______________________________________________
___________________________________________________

Posted on the Developers mailing list. Go to http://arduino.cc/mailman/listinfo/developers_arduino.cc to subscribe. I'm very interested to see if one of your tests break the new version of the
String class Paul! the version with _3. If you manage to break it I'll shut
up about statically allocating a buffer forever, until then I'll probably
try to push for at least some more time :)

+1 internet to the one who first breaks the new lib, -1 for me (and I
promise, this is the first and last time I gamble in internets)

On Wed, Jan 5, 2011 at 8:09 PM, Paul Stoffregen <> wrote:

>
> The other issue is that of object lifetimes. The test code has instances
>> of String objects which are allocated on the stack and that are still in
>> scope when the 'leak' memory check is performed.
>>
>
> That was also in my (off list) email a few days ago, though that bit didn't
> make it here.
>
> I believe the plan is to move the tests and object(s) they use to a
> function, so the objects will be out of scope when the memory check is made.
>
> There might also another copy of the test which pre-allocates a string
> large enough to hold all the data. I'm not sure exactly how I feel about
> that approach, but it seems like at least worth trying. Currently the
> string library does not have a reserve() function. I've proposed it before,
> and today I put it in issue #449.
>
>
> If a library routine used malloc to perform a one-time library-private
>> buffer allocation where the buffer is retained for the lifetime of the
>> program, the current leak checking would incorrectly report that as a leak.
>> It isn't a leak because there's still a reference to the block inside the
>> library.
>>
>
> Yes, you are correct, the test makes some assumptions about the internal
> implementation, and yes, an ideal test wouldn't make any such assumptions,
> and yes, it's probably impractical to completely avoid assumptions on such
> limited hardware.
>
> But there's a lot of value in actually testing on the real hardware, with
> all its limitations and slight differences from running on a PC.
> Personally, I think making some assumptions is a pretty good trade-off for
> testing in the actual environment. Of course, there's plenty of room for
> smart ideas to minimize such assumptions, or perhaps test in multiple ways.
>
> As someone who's spent a lot of time coding on the string class (and has
> more planned), the real value isn't a perfect score if my code is bug free,
> but rather a FAIL coming up when I make some mistake that unexpectedly
> breaks something. Sure it's annoying if a FAIL comes up erroneously because
> the internal implementation changed,
>
> There are so many functions, with so many cases, that subtle errors can
> happen (eg, does lastIndexOf work when the search string is the entire
> original string... I broke that recently, but everything else worked.....)
>
> If you have ideas about how to catch more types of errors, even if
> imperfect, I'd really love to hear.
>
>
>
>
>
>
>>
>> The only semi-reliable way to do what you want is to use an instrumented
>> malloc implementation, and that's going to be very difficult to implement on
>> a constrained platform such as the AVR. If you want to test the String
>> implementation for leaks, my advice is to do it on a more capable platform
>> (e.g. *nix) and use one of the many instrumented mallocs that are available.
>>
>>
>
> _______________________________________________
___________________________________________________

Posted on the Developers mailing list. Go to http://arduino.cc/mailman/listinfo/developers_arduino.cc to subscribe. > If you manage to break it I'll shut
> up about statically allocating a buffer forever, until then I'll probably
> try to push for at least some more time :)
> +1 internet to the one who first breaks the new lib, -1 for me (and I
> promise, this is the first and last time I gamble in internets)

I'm sorry but your implementation is really badly broken. I can come
up with multiple potential ways to break it after only a cursory
inspection, plus the performance will be abysmal as you copy
everything around all the time.

Here are some things to think about:

1. What happens if a String contains an embedded null character?
2. What assumptions are you making about the maximum length of a
String, and the maximum number of allocated Strings?

--
Alan Burlison
--

_______________________________________________
___________________________________________________

Posted on the Developers mailing list. Go to http://arduino.cc/mailman/listinfo/developers_arduino.cc to subscribe. First off; I've not tried to say anything bad about the String library! And
when I say that it breaks I really mean to say that the implementation of
the memory allocation fails as it causes fragmentation and as such, you end
up with 'no available memory' even though you the available memory is there
only fragmented.

Have anyone tested the new version? It works here, with the old code that
created and manipulated multiple string instances in the loop(). It prints
the expected color endlessly. If the old version (really, *alloc/free)
breaks, then it has to at least be an indication of something potentially
good?

I can explain the algorithm if you guys are interested. It uses a kind of a
variation of http://en.wikipedia.org/wiki/Skip_list I think OpenGL uses the
same scheme for searching.
Basically each block knows its size so when searching you only access one
field per block, so in a memory of 100 cells and 5 blocks of 10 you would
need 4 iterations (as opposed to 40) in order to find the last block.
Furthermore, whenever a block need to grow it gets placed on the 'end' of
the memory and every block gets shifted towards the start. This way if the
memory was A B C D 0 0 0 (where 0 is availbale memory) and B had to grow to
become B B then the new memory would look like A C D B B 0 0, and as such,
the memory will always be maximized because there will never be
fragmentation.
For even more detail, just ask.


On Thu, Jan 6, 2011 at 2:08 AM, Alan Burlison <>wrote:

> > If you manage to break it I'll shut
> > up about statically allocating a buffer forever, until then I'll probably
> > try to push for at least some more time :)
> > +1 internet to the one who first breaks the new lib, -1 for me (and I
> > promise, this is the first and last time I gamble in internets)
>
> I'm sorry but your implementation is really badly broken. I can come
> up with multiple potential ways to break it after only a cursory
> inspection, plus the performance will be abysmal as you copy
> everything around all the time.
>
The only changes I have made is that I replaced all the old allocation calls
with a new.
The other codes you see are there to keep the pointer to the data updated as
it can now move in memory

I have added no copying, I only ever pass around addresses to objects. Have
you even looked at the source?

>
> Here are some things to think about:
>
> 1. What happens if a String contains an embedded null character?
>
Nothing other than what always happen, when you print it it will be capped
where the terminating 0 is


> 2. What assumptions are you making about the maximum length of a
> String, and the maximum number of allocated Strings?
>
I have made no assumptions yet, as I figured you guys wanted to be a part of
such a process.
I've just declared a buffer of 100 bytes.

We could potentially make the serial objects also use the SDM library as to
only allocate one buffer that all instances could share. This way the total
amount of memory allocated could be minimized.


> --
> Alan Burlison
> --
>

  #20  
06-01-2011 02:10 AM
Developers member admin is online now
User
 

That breaking of String, does it only occur with the SDM version?

If not, did you find any way to break it? Maybe any of the old faults
related to memory?


I actually have no time to check this myself right now, so I opted to just
ask you.

On Mon, Jan 3, 2011 at 10:35 PM, Tom Igoe <> wrote:

> Thanks, Alexander, and sorry for the delay.
>
> A few tests:
>
> For code that doesn't change the strings much, there's not a big
> difference, a couple dozen bytes' difference in code size. However, when
> you start to do dynamic things, it does add up. For example, the
> StringAppendOperator example is 4910 bytes in 0022, and 5148 bytes with the
> StaticDynamicMemory version. So it does start to take its toll, memory-wise.
>
> On some sketches it actually takes less memory. For example, the one below
> is 3738 bytes using the StaticDynamicMemory version, and 3986 bytes in 0022.
> However, it fails entirely on upload. When the value of (analog 0)/4 is
> high (0xFF), it never gets out of the setup(). So there's still a pretty
> easy way to break String, even with these improvements.
>
>
> void setup() {
> Serial.begin(9600);
> Serial.println("Beginning");
> }
>
> void loop() {
>
> String webColor = "#";
>
> int red = analogRead(A0)/4;
> webColor += String(red, HEX);
> int green = analogRead(A1)/4;
> webColor += String(green, HEX);
> int blue = analogRead(A2)/4;
>
> webColor += String(blue, HEX);
> Serial.println(webColor);
> }
>
>
>
>
>
> On Dec 16, 2010, at 1:27 AM, Alexander Brevig wrote:
>
> > Attached is a zip containing WString.h and .cpp plus
> StaticDynamicMemory.h.
> > Take a backup of the original WString files, and extract this zip into
> the hardware/arduino/cores/arduino folder.
> >
> > Now you're ready to test the modified String library, that does not
> fragment the heap.
> >
> >
> > In the WString header there is a #define called STRING_BUFFER which is
> set to 100 for now, change this to suit your test needs.
> >
> >
> > No error handling is implemented, what do you think we need?
> >
> > I plan to add an availableMemory():int method to the SDM library, and
> maybe some error flags and checks like hasError():int error
> >
> > I also suspect that this library is a bit slower performance wise, but I
> think that's just a cost we'll have to pay to being able to play with
> dynamic strings.
> >
> >
> > Hope to get feedback from someone!
> >
> > On Thu, Dec 16, 2010 at 1:11 AM, Alan Burlison <>
> wrote:
> > On 15/12/2010 16:19, David A. Mellis wrote:
> >
> > I think you're right, but I also don't think that telling people to
> > use the standard C library functions is a solution either. Trying out
> > this String class seems like one way of pushing forwards towards a
> > compromise that provides both an easy-to-use API and a robust
> > implementation. For example, perhaps the buffer sizes need to be
> > specified or provided when the String is instantiated. Or we need an
> > alternative implementation that does more reliable memory allocation
> > (since we're not assuming that the internal buffer is continuous).
> > Other ideas welcome.
> >
> > I think the problem is that the failure modes are not benign. I haven't
> been through all the use cases so this might not work, but perhaps using a
> statically-allocated string ("NOMEM" ?) as a sentinel value instead of null
> when malloc fails might be one way? Also, there might be some benefit in
> making String immutable a la Java - overloaded operators in C++ have a
> tendency to generate anonymous temporaries, which is going to lead to heap
> fragmentation as well.
> >
> > --
> > Alan Burlison
> > --
> >
> > _______________________________________________
___________________________________________________

Posted on the Developers mailing list. Go to http://arduino.cc/mailman/listinfo/developers_arduino.cc to subscribe. It broke in the non-SDM version too, but it took longer to break. In the SDM version it breaks immediately. So it looks like whatever you did highlights the faults sooner, which is good. It also points to a need for an error response of some sort, in answer to your question last mail.

t.

On Jan 3, 2011, at 4:44 PM, Alexander Brevig wrote:

> That breaking of String, does it only occur with the SDM version?
>
> If not, did you find any way to break it? Maybe any of the old faults related to memory?
>
>
> I actually have no time to check this myself right now, so I opted to just ask you.
>
> On Mon, Jan 3, 2011 at 10:35 PM, Tom Igoe <> wrote:
> Thanks, Alexander, and sorry for the delay.
>
> A few tests:
>
> For code that doesn't change the strings much, there's not a big difference, a couple dozen bytes' difference in code size. However, when you start to do dynamic things, it does add up. For example, the StringAppendOperator example is 4910 bytes in 0022, and 5148 bytes with the StaticDynamicMemory version. So it does start to take its toll, memory-wise.
>
> On some sketches it actually takes less memory. For example, the one below is 3738 bytes using the StaticDynamicMemory version, and 3986 bytes in 0022. However, it fails entirely on upload. When the value of (analog 0)/4 is high (0xFF), it never gets out of the setup(). So there's still a pretty easy way to break String, even with these improvements.
>
>
> void setup() {
> Serial.begin(9600);
> Serial.println("Beginning");
> }
>
> void loop() {
>
> String webColor = "#";
>
> int red = analogRead(A0)/4;
> webColor += String(red, HEX);
> int green = analogRead(A1)/4;
> webColor += String(green, HEX);
> int blue = analogRead(A2)/4;
>
> webColor += String(blue, HEX);
> Serial.println(webColor);
> }
>
>
>
>
>
> On Dec 16, 2010, at 1:27 AM, Alexander Brevig wrote:
>
> > Attached is a zip containing WString.h and .cpp plus StaticDynamicMemory.h.
> > Take a backup of the original WString files, and extract this zip into the hardware/arduino/cores/arduino folder.
> >
> > Now you're ready to test the modified String library, that does not fragment the heap.
> >
> >
> > In the WString header there is a #define called STRING_BUFFER which is set to 100 for now, change this to suit your test needs.
> >
> >
> > No error handling is implemented, what do you think we need?
> >
> > I plan to add an availableMemory():int method to the SDM library, and maybe some error flags and checks like hasError():int error
> >
> > I also suspect that this library is a bit slower performance wise, but I think that's just a cost we'll have to pay to being able to play with dynamic strings.
> >
> >
> > Hope to get feedback from someone!
> >
> > On Thu, Dec 16, 2010 at 1:11 AM, Alan Burlison <> wrote:
> > On 15/12/2010 16:19, David A. Mellis wrote:
> >
> > I think you're right, but I also don't think that telling people to
> > use the standard C library functions is a solution either. Trying out
> > this String class seems like one way of pushing forwards towards a
> > compromise that provides both an easy-to-use API and a robust
> > implementation. For example, perhaps the buffer sizes need to be
> > specified or provided when the String is instantiated. Or we need an
> > alternative implementation that does more reliable memory allocation
> > (since we're not assuming that the internal buffer is continuous).
> > Other ideas welcome.
> >
> > I think the problem is that the failure modes are not benign. I haven't been through all the use cases so this might not work, but perhaps using a statically-allocated string ("NOMEM" ?) as a sentinel value instead of null when malloc fails might be one way? Also, there might be some benefit in making String immutable a la Java - overloaded operators in C++ have a tendency to generate anonymous temporaries, which is going to lead to heap fragmentation as well.
> >
> > --
> > Alan Burlison
> > --
> >
> > _______________________________________________
___________________________________________________

Posted on the Developers mailing list. Go to http://arduino.cc/mailman/listinfo/developers_arduino.cc to subscribe. There seems to be a bug with the assignment operator, I'm on it and I'll get
back to you as soon as I get something done.

Thank you for your tests and feedback.


I'll do some tests on my own before I repost it here.

On Tue, Jan 4, 2011 at 6:53 PM, Rick Anderson
<>wrote:

> I just created a test and unpacked and tested it. I also created a
> test based on Tom's code. Not sure I caught the maximum value error
> for 0xFF.
>
> I also ran the tests for bug 411. All the tests compile, but there is
> still memory loss.
>
> I'm attaching the Arduino Test suite, and the test code so you can run
> them as you debug. Let me know if this was helpful.
>
> --Rick
>
> Test run results:
> Example: ATS_StringAssignmentTest.pde
> info.MANUFACTURER = Arduino
> info.CPU-NAME = ATmega328P
> info.GCC-Version = 4.3.2
> info.AVR-LibC-Ver = 1.6.4
> info.Compiled-date = Jan 4 2011
> info.Test-Suite-Name = ATS_StringAssignmentTest
> info.Free-memory = 1110 bytes
> Memory Usage (lost 59 bytes) ... FAIL
> --------------------------
> Ran 1 tests in 1.378s
>
> FAILED (failures=1)
>
>
> Example: ATS_StringMemoryTestPassByReference.pde
>
> info.MANUFACTURER = Arduino
> info.CPU-NAME = ATmega328P
> info.GCC-Version = 4.3.2
> info.AVR-LibC-Ver = 1.6.4
> info.Compiled-date = Jan 4 2011
> info.Test-Suite-Name = ATS_StringMemoryTestPassByReference
> info.Free-memory = 1120 bytes
> Memory Usage (lost 59 bytes) ... FAIL
> --------------------------
> Ran 1 tests in 1.389s
>
> FAILED (failures=1)
>
>
> Example: Tom Igoe Memory Test
> info.MANUFACTURER = Arduino
> info.CPU-NAME = ATmega328P
> info.GCC-Version = 4.3.2
> info.AVR-LibC-Ver = 1.6.4
> info.Compiled-date = Jan 4 2011
> info.Test-Suite-Name = Tom Igoe Memory Test
> info.Free-memory = 1328 bytes
> Memory Usage (lost 9 bytes) ... FAIL
> --------------------------
> Ran 1 tests in 1.374s
>
> FAILED (failures=1)
>
>
>
> --Rick
>
> Tom, rewrote your example as a test.
>
> //************************************************************************
> //* Arduino Tom Igoe Memory Test
> //* (C) 2010 by Rick Anderson
> //* Open source as per standard Arduino code
> //*
> //************************************************************************
> //* Jan 4, 2011 Started on Tom Igoe Memory Test
> //************************************************************************
>
> #include "WProgram.h"
> #include "HardwareSerial.h"
> #include
>
> //************************************************************************
> void setup()
> {
> int startMemoryUsage;
> /*
> * Create variable for the tests.
> */
>
> String webColor = "#000000";
>
> int red = 1023/4;
> int blue = 512/4;
> int green = 128/4;
>
> /*
> * initiate the test run
> */
> //Record starting memory amount
> startMemoryUsage = ATS_GetFreeMemory();
> //Begin test run
> ATS_begin("Arduino", "Tom Igoe Memory Test");
>
> webColor = "#";
> webColor += String(red, HEX);
> webColor += String(green, HEX);
> webColor += String(blue, HEX);
>
> ATS_ReportMemoryUsage(startMemoryUsage);
>
> /*
> * Test complete
> */
>
> ATS_end();
> }
>
>
> //************************************************************************
> void loop()
> {
>
>
> }
>
>
>
>
> On Mon, Jan 3, 2011 at 9:35 PM, Tom Igoe <> wrote:
> > It broke in the non-SDM version too, but it took longer to break. In the
> SDM version it breaks immediately. So it looks like whatever you did
> highlights the faults sooner, which is good. It also points to a need for an
> error response of some sort, in answer to your question last mail.
> >
> > t.
> >
> > On Jan 3, 2011, at 4:44 PM, Alexander Brevig wrote:
> >
> >> That breaking of String, does it only occur with the SDM version?
> >>
> >> If not, did you find any way to break it? Maybe any of the old faults
> related to memory?
> >>
> >>
> >> I actually have no time to check this myself right now, so I opted to
> just ask you.
> >>
> >> On Mon, Jan 3, 2011 at 10:35 PM, Tom Igoe <> wrote:
> >> Thanks, Alexander, and sorry for the delay.
> >>
> >> A few tests:
> >>
> >> For code that doesn't change the strings much, there's not a big
> difference, a couple dozen bytes' difference in code size. However, when
> you start to do dynamic things, it does add up. For example, the
> StringAppendOperator example is 4910 bytes in 0022, and 5148 bytes with the
> StaticDynamicMemory version. So it does start to take its toll, memory-wise.
> >>
> >> On some sketches it actually takes less memory. For example, the one
> below is 3738 bytes using the StaticDynamicMemory version, and 3986 bytes in
> 0022. However, it fails entirely on upload. When the value of (analog 0)/4
> is high (0xFF), it never gets out of the setup(). So there's still a pretty
> easy way to break String, even with these improvements.
> >>
> >>
> >> void setup() {
> >> Serial.begin(9600);
> >> Serial.println("Beginning");
> >> }
> >>
> >> void loop() {
> >>
> >> String webColor = "#";
> >>
> >> int red = analogRead(A0)/4;
> >> webColor += String(red, HEX);
> >> int green = analogRead(A1)/4;
> >> webColor += String(green, HEX);
> >> int blue = analogRead(A2)/4;
> >>
> >> webColor += String(blue, HEX);
> >> Serial.println(webColor);
> >> }
> >>
> >>
> >>
> >>
> >>
> >> On Dec 16, 2010, at 1:27 AM, Alexander Brevig wrote:
> >>
> >> > Attached is a zip containing WString.h and .cpp plus
> StaticDynamicMemory.h.
> >> > Take a backup of the original WString files, and extract this zip into
> the hardware/arduino/cores/arduino folder.
> >> >
> >> > Now you're ready to test the modified String library, that does not
> fragment the heap.
> >> >
> >> >
> >> > In the WString header there is a #define called STRING_BUFFER which is
> set to 100 for now, change this to suit your test needs.
> >> >
> >> >
> >> > No error handling is implemented, what do you think we need?
> >> >
> >> > I plan to add an availableMemory():int method to the SDM library, and
> maybe some error flags and checks like hasError():int error
> >> >
> >> > I also suspect that this library is a bit slower performance wise, but
> I think that's just a cost we'll have to pay to being able to play with
> dynamic strings.
> >> >
> >> >
> >> > Hope to get feedback from someone!
> >> >
> >> > On Thu, Dec 16, 2010 at 1:11 AM, Alan Burlison <
> > wrote:
> >> > On 15/12/2010 16:19, David A. Mellis wrote:
> >> >
> >> > I think you're right, but I also don't think that telling people to
> >> > use the standard C library functions is a solution either. Trying out
> >> > this String class seems like one way of pushing forwards towards a
> >> > compromise that provides both an easy-to-use API and a robust
> >> > implementation. For example, perhaps the buffer sizes need to be
> >> > specified or provided when the String is instantiated. Or we need an
> >> > alternative implementation that does more reliable memory allocation
> >> > (since we're not assuming that the internal buffer is continuous).
> >> > Other ideas welcome.
> >> >
> >> > I think the problem is that the failure modes are not benign. I
> haven't been through all the use cases so this might not work, but perhaps
> using a statically-allocated string ("NOMEM" ?) as a sentinel value instead
> of null when malloc fails might be one way? Also, there might be some
> benefit in making String immutable a la Java - overloaded operators in C++
> have a tendency to generate anonymous temporaries, which is going to lead to
> heap fragmentation as well.
> >> >
> >> > --
> >> > Alan Burlison
> >> > --
> >> >
> >> > _______________________________________________
___________________________________________________

Posted on the Developers mailing list. Go to http://arduino.cc/mailman/listinfo/developers_arduino.cc to subscribe. Is this test suite any different than the one in the github repo?

t.

On Jan 4, 2011, at 12:53 PM, Rick Anderson wrote:

> I just created a test and unpacked and tested it. I also created a
> test based on Tom's code. Not sure I caught the maximum value error
> for 0xFF.
>
> I also ran the tests for bug 411. All the tests compile, but there is
> still memory loss.
>
> I'm attaching the Arduino Test suite, and the test code so you can run
> them as you debug. Let me know if this was helpful.
>
> --Rick
>
> Test run results:
> Example: ATS_StringAssignmentTest.pde
> info.MANUFACTURER = Arduino
> info.CPU-NAME = ATmega328P
> info.GCC-Version = 4.3.2
> info.AVR-LibC-Ver = 1.6.4
> info.Compiled-date = Jan 4 2011
> info.Test-Suite-Name = ATS_StringAssignmentTest
> info.Free-memory = 1110 bytes
> Memory Usage (lost 59 bytes) ... FAIL
> --------------------------
> Ran 1 tests in 1.378s
>
> FAILED (failures=1)
>
>
> Example: ATS_StringMemoryTestPassByReference.pde
>
> info.MANUFACTURER = Arduino
> info.CPU-NAME = ATmega328P
> info.GCC-Version = 4.3.2
> info.AVR-LibC-Ver = 1.6.4
> info.Compiled-date = Jan 4 2011
> info.Test-Suite-Name = ATS_StringMemoryTestPassByReference
> info.Free-memory = 1120 bytes
> Memory Usage (lost 59 bytes) ... FAIL
> --------------------------
> Ran 1 tests in 1.389s
>
> FAILED (failures=1)
>
>
> Example: Tom Igoe Memory Test
> info.MANUFACTURER = Arduino
> info.CPU-NAME = ATmega328P
> info.GCC-Version = 4.3.2
> info.AVR-LibC-Ver = 1.6.4
> info.Compiled-date = Jan 4 2011
> info.Test-Suite-Name = Tom Igoe Memory Test
> info.Free-memory = 1328 bytes
> Memory Usage (lost 9 bytes) ... FAIL
> --------------------------
> Ran 1 tests in 1.374s
>
> FAILED (failures=1)
>
>
>
> --Rick
>
> Tom, rewrote your example as a test.
>
> //************************************************************************
> //* Arduino Tom Igoe Memory Test
> //* (C) 2010 by Rick Anderson
> //* Open source as per standard Arduino code
> //*
> //************************************************************************
> //* Jan 4, 2011 Started on Tom Igoe Memory Test
> //************************************************************************
>
> #include "WProgram.h"
> #include "HardwareSerial.h"
> #include
>
> //************************************************************************
> void setup()
> {
> int startMemoryUsage;
> /*
> * Create variable for the tests.
> */
>
> String webColor = "#000000";
>
> int red = 1023/4;
> int blue = 512/4;
> int green = 128/4;
>
> /*
> * initiate the test run
> */
> //Record starting memory amount
> startMemoryUsage = ATS_GetFreeMemory();
> //Begin test run
> ATS_begin("Arduino", "Tom Igoe Memory Test");
>
> webColor = "#";
> webColor += String(red, HEX);
> webColor += String(green, HEX);
> webColor += String(blue, HEX);
>
> ATS_ReportMemoryUsage(startMemoryUsage);
>
> /*
> * Test complete
> */
>
> ATS_end();
> }
>
>
> //************************************************************************
> void loop()
> {
>
>
> }
>
>
>
>
> On Mon, Jan 3, 2011 at 9:35 PM, Tom Igoe <> wrote:
>> It broke in the non-SDM version too, but it took longer to break. In the SDM version it breaks immediately. So it looks like whatever you did highlights the faults sooner, which is good. It also points to a need for an error response of some sort, in answer to your question last mail.
>>
>> t.
>>
>> On Jan 3, 2011, at 4:44 PM, Alexander Brevig wrote:
>>
>>> That breaking of String, does it only occur with the SDM version?
>>>
>>> If not, did you find any way to break it? Maybe any of the old faults related to memory?
>>>
>>>
>>> I actually have no time to check this myself right now, so I opted to just ask you.
>>>
>>> On Mon, Jan 3, 2011 at 10:35 PM, Tom Igoe <> wrote:
>>> Thanks, Alexander, and sorry for the delay.
>>>
>>> A few tests:
>>>
>>> For code that doesn't change the strings much, there's not a big difference, a couple dozen bytes' difference in code size. However, when you start to do dynamic things, it does add up. For example, the StringAppendOperator example is 4910 bytes in 0022, and 5148 bytes with the StaticDynamicMemory version. So it does start to take its toll, memory-wise.
>>>
>>> On some sketches it actually takes less memory. For example, the one below is 3738 bytes using the StaticDynamicMemory version, and 3986 bytes in 0022. However, it fails entirely on upload. When the value of (analog 0)/4 is high (0xFF), it never gets out of the setup(). So there's still a pretty easy way to break String, even with these improvements.
>>>
>>>
>>> void setup() {
>>> Serial.begin(9600);
>>> Serial.println("Beginning");
>>> }
>>>
>>> void loop() {
>>>
>>> String webColor = "#";
>>>
>>> int red = analogRead(A0)/4;
>>> webColor += String(red, HEX);
>>> int green = analogRead(A1)/4;
>>> webColor += String(green, HEX);
>>> int blue = analogRead(A2)/4;
>>>
>>> webColor += String(blue, HEX);
>>> Serial.println(webColor);
>>> }
>>>
>>>
>>>
>>>
>>>
>>> On Dec 16, 2010, at 1:27 AM, Alexander Brevig wrote:
>>>
>>>> Attached is a zip containing WString.h and .cpp plus StaticDynamicMemory.h.
>>>> Take a backup of the original WString files, and extract this zip into the hardware/arduino/cores/arduino folder.
>>>>
>>>> Now you're ready to test the modified String library, that does not fragment the heap.
>>>>
>>>>
>>>> In the WString header there is a #define called STRING_BUFFER which is set to 100 for now, change this to suit your test needs.
>>>>
>>>>
>>>> No error handling is implemented, what do you think we need?
>>>>
>>>> I plan to add an availableMemory():int method to the SDM library, and maybe some error flags and checks like hasError():int error
>>>>
>>>> I also suspect that this library is a bit slower performance wise, but I think that's just a cost we'll have to pay to being able to play with dynamic strings.
>>>>
>>>>
>>>> Hope to get feedback from someone!
>>>>
>>>> On Thu, Dec 16, 2010 at 1:11 AM, Alan Burlison <> wrote:
>>>> On 15/12/2010 16:19, David A. Mellis wrote:
>>>>
>>>> I think you're right, but I also don't think that telling people to
>>>> use the standard C library functions is a solution either. Trying out
>>>> this String class seems like one way of pushing forwards towards a
>>>> compromise that provides both an easy-to-use API and a robust
>>>> implementation. For example, perhaps the buffer sizes need to be
>>>> specified or provided when the String is instantiated. Or we need an
>>>> alternative implementation that does more reliable memory allocation
>>>> (since we're not assuming that the internal buffer is continuous).
>>>> Other ideas welcome.
>>>>
>>>> I think the problem is that the failure modes are not benign. I haven't been through all the use cases so this might not work, but perhaps using a statically-allocated string ("NOMEM" ?) as a sentinel value instead of null when malloc fails might be one way? Also, there might be some benefit in making String immutable a la Java - overloaded operators in C++ have a tendency to generate anonymous temporaries, which is going to lead to heap fragmentation as well.
>>>>
>>>> --
>>>> Alan Burlison
>>>> --
>>>>
>>>> _______________________________________________
___________________________________________________

Posted on the Developers mailing list. Go to http://arduino.cc/mailman/listinfo/developers_arduino.cc to subscribe. Same exact one. I just included it just in case.

--Rick

On Tue, Jan 4, 2011 at 9:01 PM, Tom Igoe <> wrote:
> Is this test suite any different than the one in the github repo?
>
> t.
>
> On Jan 4, 2011, at 12:53 PM, Rick Anderson wrote:
>
>> I just created a test and unpacked and tested it. I also created a
>> test based on Tom's code. Not sure I caught the maximum value error
>> for 0xFF.
>>
>> I also ran the tests for bug 411. All the tests compile, but there is
>> still memory loss.
>>
>> I'm attaching the Arduino Test suite, and the test code so you can run
>> them as you debug. Let me know if this was helpful.
>>
>> --Rick
>>
>> Test run results:
>> Example:  ATS_StringAssignmentTest.pde
>> info.MANUFACTURER    = Arduino
>> info.CPU-NAME        = ATmega328P
>> info.GCC-Version     = 4.3.2
>> info.AVR-LibC-Ver    = 1.6.4
>> info.Compiled-date   = Jan  4 2011
>> info.Test-Suite-Name = ATS_StringAssignmentTest
>> info.Free-memory     = 1110 bytes
>> Memory Usage (lost 59 bytes)                                ... FAIL
>> --------------------------
>> Ran 1 tests in 1.378s
>>
>> FAILED (failures=1)
>>
>>
>> Example: ATS_StringMemoryTestPassByReference.pde
>>
>> info.MANUFACTURER    = Arduino
>> info.CPU-NAME        = ATmega328P
>> info.GCC-Version     = 4.3.2
>> info.AVR-LibC-Ver    = 1.6.4
>> info.Compiled-date   = Jan  4 2011
>> info.Test-Suite-Name = ATS_StringMemoryTestPassByReference
>> info.Free-memory     = 1120 bytes
>> Memory Usage (lost 59 bytes)                                ... FAIL
>> --------------------------
>> Ran 1 tests in 1.389s
>>
>> FAILED (failures=1)
>>
>>
>> Example: Tom Igoe Memory Test
>> info.MANUFACTURER    = Arduino
>> info.CPU-NAME        = ATmega328P
>> info.GCC-Version     = 4.3.2
>> info.AVR-LibC-Ver    = 1.6.4
>> info.Compiled-date   = Jan  4 2011
>> info.Test-Suite-Name = Tom Igoe Memory Test
>> info.Free-memory     = 1328 bytes
>> Memory Usage (lost 9 bytes)                                 ... FAIL
>> --------------------------
>> Ran 1 tests in 1.374s
>>
>> FAILED (failures=1)
>>
>>
>>
>> --Rick
>>
>> Tom, rewrote your example as a test.
>>
>> //************************************************************************
>> //*   Arduino Tom Igoe Memory Test
>> //*           (C) 2010 by Rick Anderson
>> //*           Open source as per standard Arduino code
>> //*
>> //************************************************************************
>> //*   Jan 4,  2011     Started on Tom Igoe Memory Test
>> //************************************************************************
>>
>> #include      "WProgram.h"
>> #include      "HardwareSerial.h"
>> #include      
>>
>> //************************************************************************
>> void setup()
>> {
>>  int          startMemoryUsage;
>>  /*
>>    * Create variable for the tests.
>>   */
>>
>>  String webColor = "#000000";
>>
>>  int red = 1023/4;
>>  int blue = 512/4;
>>  int green = 128/4;
>>
>>  /*
>>  * initiate the test run
>>   */
>>  //Record starting memory amount
>>  startMemoryUsage     =       ATS_GetFreeMemory();
>>  //Begin test run
>>  ATS_begin("Arduino", "Tom Igoe Memory Test");
>>
>>  webColor = "#";
>>  webColor += String(red, HEX);
>>  webColor += String(green, HEX);
>>  webColor += String(blue, HEX);
>>
>>  ATS_ReportMemoryUsage(startMemoryUsage);
>>
>>  /*
>>   * Test complete
>>   */
>>
>>  ATS_end();
>> }
>>
>>
>> //************************************************************************
>> void loop()
>> {
>>
>>
>> }
>>
>>
>>
>>
>> On Mon, Jan 3, 2011 at 9:35 PM, Tom Igoe <> wrote:
>>> It broke in the non-SDM version too, but it took longer to break. In the SDM version it breaks immediately. So it looks like whatever you did highlights the faults sooner, which is good. It also points to a need for an error response of some sort, in answer to your question last mail.
>>>
>>> t.
>>>
>>> On Jan 3, 2011, at 4:44 PM, Alexander Brevig wrote:
>>>
>>>> That breaking of String, does it only occur with the SDM version?
>>>>
>>>> If not, did you find any way to break it? Maybe any of the old faults related to memory?
>>>>
>>>>
>>>> I actually have no time to check this myself right now, so I opted to just ask you.
>>>>
>>>> On Mon, Jan 3, 2011 at 10:35 PM, Tom Igoe <> wrote:
>>>> Thanks, Alexander, and sorry for the delay.
>>>>
>>>> A few tests:
>>>>
>>>> For code that doesn't change the strings much, there's not a big difference, a couple dozen bytes' difference in code size.  However, when you start to do dynamic things, it does add up.  For example, the StringAppendOperator example is  4910 bytes in 0022, and 5148 bytes with the StaticDynamicMemory version. So it does start to take its toll, memory-wise.
>>>>
>>>> On some sketches it actually takes less memory.  For example, the one below is 3738 bytes using the StaticDynamicMemory version, and 3986 bytes in 0022.  However, it fails entirely on upload.  When the value of (analog 0)/4 is high (0xFF), it never gets out of the setup(). So there's still a pretty easy way to break String, even with these improvements.
>>>>
>>>>
>>>> void setup() {
>>>>  Serial.begin(9600);
>>>>  Serial.println("Beginning");
>>>> }
>>>>
>>>> void loop() {
>>>>
>>>>  String webColor = "#";
>>>>
>>>>  int red = analogRead(A0)/4;
>>>>  webColor += String(red, HEX);
>>>>  int green = analogRead(A1)/4;
>>>>  webColor += String(green, HEX);
>>>>  int blue = analogRead(A2)/4;
>>>>
>>>>  webColor += String(blue, HEX);
>>>>  Serial.println(webColor);
>>>> }
>>>>
>>>>
>>>>
>>>>
>>>>
>>>> On Dec 16, 2010, at 1:27 AM, Alexander Brevig wrote:
>>>>
>>>>> Attached is a zip containing WString.h and .cpp plus StaticDynamicMemory.h.
>>>>> Take a backup of the original WString files, and extract this zip into the hardware/arduino/cores/arduino folder.
>>>>>
>>>>> Now you're ready to test the modified String library, that does not fragment the heap.
>>>>>
>>>>>
>>>>> In the WString header there is a #define called STRING_BUFFER which is set to 100 for now, change this to suit your test needs.
>>>>>
>>>>>
>>>>> No error handling is implemented, what do you think we need?
>>>>>
>>>>> I plan to add an availableMemory():int method to the SDM library, and maybe some error flags and checks like hasError():int error
>>>>>
>>>>> I also suspect that this library is a bit slower performance wise, but I think that's just a cost we'll have to pay to being able to play with dynamic strings.
>>>>>
>>>>>
>>>>> Hope to  get feedback from someone!
>>>>>
>>>>> On Thu, Dec 16, 2010 at 1:11 AM, Alan Burlison <> wrote:
>>>>> On 15/12/2010 16:19, David A. Mellis wrote:
>>>>>
>>>>> I think you're right, but I also don't think that telling people to
>>>>> use the standard C library functions is a solution either.  Trying out
>>>>> this String class seems like one way of pushing forwards towards a
>>>>> compromise that provides both an easy-to-use API and a robust
>>>>> implementation.  For example, perhaps the buffer sizes need to be
>>>>> specified or provided when the String is instantiated.  Or we need an
>>>>> alternative implementation that does more reliable memory allocation
>>>>> (since we're not assuming that the internal buffer is continuous).
>>>>> Other ideas welcome.
>>>>>
>>>>> I think the problem is that the failure modes are not benign.  I haven't been through all the use cases so this might not work, but perhaps using a statically-allocated string ("NOMEM" ?) as a sentinel value instead of null when malloc fails might be one way?  Also, there might be some benefit in making String immutable a la Java - overloaded operators in C++ have a tendency to generate anonymous temporaries, which is going to lead to heap fragmentation as well.
>>>>>
>>>>> --
>>>>> Alan Burlison
>>>>> --
>>>>>
>>>>> _______________________________________________
___________________________________________________

Posted on the Developers mailing list. Go to http://arduino.cc/mailman/listinfo/developers_arduino.cc to subscribe. On 04/01/2011 17:53, Rick Anderson wrote:

> I also ran the tests for bug 411. All the tests compile, but there is
> still memory loss.

Most of the assumptions made by the test harness and test case code are
wrong, any reports of 'lost' memory are therefore likely to be wrong as
well. If you want to do leak detection you can't do it in the naive way
it is being done at present.

--
Alan Burlison
--

_______________________________________________
___________________________________________________

Posted on the Developers mailing list. Go to http://arduino.cc/mailman/listinfo/developers_arduino.cc to subscribe. Alan,

The tests themselves are quick and dirty, and not strategic or
comprehensive. I'd like your input to create a good procedure for
memory testing. I also have feedback from Paul Stoffregen for the test
suite:
----
Another problem involves gcc's optimizer ignoring the inline request
for ATS_ReportMemoryUsage. As the comment in the code explains, it
must be inline to avoid measuring its own stack frame. I believe
adding this line in ArduinoTestSuite.h fixes the problem by forcing
gcc to inline.

inline void ATS_ReportMemoryUsage(int _memoryUsageAtStart)
__attribute__((always_inline, unused));

The last problem is a tiny bit of dynamic memory permanently held for
the free list. To allow for this, the test really should call
malloc() and free() once, so the allocator is fully initialized before
testing.
----

I'd like to combine both sets of feedback, and set up some issues in
the system, then fix them. Is the above the problem you saw? Are their
other assumptions that would impact measuring memory? And updating the
memory test in the the test suite.

In terms of creating tests for memory leaks. It looks best to move all
the memory usage inside a function. What else could be done to
constrain the problem, and measuring more affectively.

I'm traveling back to NJ today, so I can't respond right away.

--Rick

On Wed, Jan 5, 2011 at 8:52 AM, Alan Burlison <> wrote:
> On 04/01/2011 17:53, Rick Anderson wrote:
>
>> I also ran the tests for bug 411. All the tests compile, but there is
>> still memory loss.
>
> Most of the assumptions made by the test harness and test case code are
> wrong, any reports of 'lost' memory are therefore likely to be wrong as
> well.  If you want to do leak detection you can't do it in the naive way it
> is being done at present.
>
> --
> Alan Burlison
> --
>



--
President
Fair Use Building and Research (****) Labs
http://fubarlabs.org

_______________________________________________
___________________________________________________

Posted on the Developers mailing list. Go to http://arduino.cc/mailman/listinfo/developers_arduino.cc to subscribe. On 05/01/2011 15:19, Rick Anderson wrote:

> ----
> Another problem involves gcc's optimizer ignoring the inline request
> for ATS_ReportMemoryUsage. As the comment in the code explains, it
> must be inline to avoid measuring its own stack frame. I believe
> adding this line in ArduinoTestSuite.h fixes the problem by forcing
> gcc to inline.
>
> inline void ATS_ReportMemoryUsage(int _memoryUsageAtStart)
> __attribute__((always_inline, unused));

Yes, that's one of the problems. And even the __attribute__
'workaround' is a fragile hack.

> The last problem is a tiny bit of dynamic memory permanently held for
> the free list. To allow for this, the test really should call
> malloc() and free() once, so the allocator is fully initialized before

That's part of a problem, but an initial call malloc/free call isn't
guaranteed to make all the issues go away either. From looking at the
avr-libc malloc implementation it does try to coalesce the heap, but
relying on multiple malloc implementation artefacts is a really bad idea
- there's no guarantee that future malloc implementations will always
coalesce on every free, and there's no guarantee that __bss_end or
__brkval will always be adjusted on each malloc/free call.

The other issue is that of object lifetimes. The test code has
instances of String objects which are allocated on the stack and that
are still in scope when the 'leak' memory check is performed. That
means the String destructors won't have been called and the dynamically
allocated part of the String will still be allocated.

A true memory leak is a block of allocated memory that has no references
to it. However that's not what the test code is checking for. If a
library routine used malloc to perform a one-time library-private buffer
allocation where the buffer is retained for the lifetime of the program,
the current leak checking would incorrectly report that as a leak. It
isn't a leak because there's still a reference to the block inside the
library.

The only semi-reliable way to do what you want is to use an instrumented
malloc implementation, and that's going to be very difficult to
implement on a constrained platform such as the AVR. If you want to
test the String implementation for leaks, my advice is to do it on a
more capable platform (e.g. *nix) and use one of the many instrumented
mallocs that are available.

--
Alan Burlison
--

_______________________________________________
___________________________________________________

Posted on the Developers mailing list. Go to http://arduino.cc/mailman/listinfo/developers_arduino.cc to subscribe. Slightly unrelated to what you guys are discussing now but:
I'm not sure if I've made this clear, but the new version of String that I'm
working on now does not use malloc or any other c function for dynamic
memory. What happens is that I allocate memory statically on the stack and
serve that memory dynamically to the instances of String.

I have some time on my hands now and have a look at getting the += not to
break the code

On Wed, Jan 5, 2011 at 7:10 PM, Alan Burlison <>wrote:

> On 05/01/2011 15:19, Rick Anderson wrote:
>
> ----
>> Another problem involves gcc's optimizer ignoring the inline request
>> for ATS_ReportMemoryUsage. As the comment in the code explains, it
>> must be inline to avoid measuring its own stack frame. I believe
>> adding this line in ArduinoTestSuite.h fixes the problem by forcing
>> gcc to inline.
>>
>> inline void ATS_ReportMemoryUsage(int _memoryUsageAtStart)
>> __attribute__((always_inline, unused));
>>
>
> Yes, that's one of the problems. And even the __attribute__ 'workaround'
> is a fragile hack.
>
>
> The last problem is a tiny bit of dynamic memory permanently held for
>> the free list. To allow for this, the test really should call
>> malloc() and free() once, so the allocator is fully initialized before
>>
>
> That's part of a problem, but an initial call malloc/free call isn't
> guaranteed to make all the issues go away either. From looking at the
> avr-libc malloc implementation it does try to coalesce the heap, but relying
> on multiple malloc implementation artefacts is a really bad idea - there's
> no guarantee that future malloc implementations will always coalesce on
> every free, and there's no guarantee that __bss_end or __brkval will always
> be adjusted on each malloc/free call.
>
> The other issue is that of object lifetimes. The test code has instances
> of String objects which are allocated on the stack and that are still in
> scope when the 'leak' memory check is performed. That means the String
> destructors won't have been called and the dynamically allocated part of the
> String will still be allocated.
>
> A true memory leak is a block of allocated memory that has no references to
> it. However that's not what the test code is checking for. If a library
> routine used malloc to perform a one-time library-private buffer allocation
> where the buffer is retained for the lifetime of the program, the current
> leak checking would incorrectly report that as a leak. It isn't a leak
> because there's still a reference to the block inside the library.
>
> The only semi-reliable way to do what you want is to use an instrumented
> malloc implementation, and that's going to be very difficult to implement on
> a constrained platform such as the AVR. If you want to test the String
> implementation for leaks, my advice is to do it on a more capable platform
> (e.g. *nix) and use one of the many instrumented mallocs that are available.
>
> --
> Alan Burlison
> --
>
>
> _______________________________________________
___________________________________________________

Posted on the Developers mailing list. Go to http://arduino.cc/mailman/listinfo/developers_arduino.cc to subscribe. On 05/01/2011 18:25, Alexander Brevig wrote:

> Slightly unrelated to what you guys are discussing now but:
> I'm not sure if I've made this clear, but the new version of String that I'm
> working on now does not use malloc or any other c function for dynamic
> memory. What happens is that I allocate memory statically on the stack and
> serve that memory dynamically to the instances of String.

Does that mean that the total space occupied by all Strings has to be
decided up front? If so, what is the behaviour when an allocation fails?

To be honest I don't really see the point of doing this - all you are
doing is re-implementing malloc.

--
Alan Burlison
--

_______________________________________________
___________________________________________________

Posted on the Developers mailing list. Go to http://arduino.cc/mailman/listinfo/developers_arduino.cc to subscribe. No, actually I am not reimplementing malloc, because my algorithm guarantees
no fragmentation and always 100% effective use of the allocated memory.

"Does that mean that the total space occupied by all Strings has to be
decided up front? "
Yes, just like the buffer for the serial ++

I know I would opt to have the restriction for a predetermined allocated
space WITH error reporting (how we do is up to you guys, feed me with ideas
I'll implement whatever we agree is best) than having
seemingly infinite memory that crashes and burns.

On Wed, Jan 5, 2011 at 7:33 PM, Alan Burlison <>wrote:

> On 05/01/2011 18:25, Alexander Brevig wrote:
>
> Slightly unrelated to what you guys are discussing now but:
>> I'm not sure if I've made this clear, but the new version of String that
>> I'm
>> working on now does not use malloc or any other c function for dynamic
>> memory. What happens is that I allocate memory statically on the stack and
>> serve that memory dynamically to the instances of String.
>>
>
> Does that mean that the total space occupied by all Strings has to be
> decided up front? If so, what is the behaviour when an allocation fails?
>
> To be honest I don't really see the point of doing this - all you are doing
> is re-implementing malloc.
>
> --
> Alan Burlison
> --
> Well, that was easy (seemingly, probably just jinxed myself...) but here the
test does no longer break, and the usage of memory never exceeds 11 bytes.

It would be awesome if someone would test it.


Also, please tell me now if this effort will lead to nowhere. Is the cost of
being constrained to a buffer size a deal-breaker?

On Wed, Jan 5, 2011 at 7:42 PM, Alexander Brevig
<>wrote:

> No, actually I am not reimplementing malloc, because my algorithm
> guarantees no fragmentation and always 100% effective use of the allocated
> memory.
>
> "Does that mean that the total space occupied by all Strings has to be
> decided up front? "
> Yes, just like the buffer for the serial ++
>
> I know I would opt to have the restriction for a predetermined allocated
> space WITH error reporting (how we do is up to you guys, feed me with ideas
> I'll implement whatever we agree is best) than having
> seemingly infinite memory that crashes and burns.
>
> On Wed, Jan 5, 2011 at 7:33 PM, Alan Burlison <>wrote:
>
>> On 05/01/2011 18:25, Alexander Brevig wrote:
>>
>> Slightly unrelated to what you guys are discussing now but:
>>> I'm not sure if I've made this clear, but the new version of String that
>>> I'm
>>> working on now does not use malloc or any other c function for dynamic
>>> memory. What happens is that I allocate memory statically on the stack
>>> and
>>> serve that memory dynamically to the instances of String.
>>>
>>
>> Does that mean that the total space occupied by all Strings has to be
>> decided up front? If so, what is the behaviour when an allocation fails?
>>
>> To be honest I don't really see the point of doing this - all you are
>> doing is re-implementing malloc.
>>
>> --
>> Alan Burlison
>> --
>>
>
> So sorry you all! I shipped my test code (for msvc++ compiler) in five
minutes I'll post an arduino compatible version. So sorry for this spam!

On Wed, Jan 5, 2011 at 8:01 PM, Alexander Brevig
<>wrote:

> Well, that was easy (seemingly, probably just jinxed myself...) but here
> the test does no longer break, and the usage of memory never exceeds 11
> bytes.
>
> It would be awesome if someone would test it.
>
>
> Also, please tell me now if this effort will lead to nowhere. Is the cost
> of being constrained to a buffer size a deal-breaker?
>
>
> On Wed, Jan 5, 2011 at 7:42 PM, Alexander Brevig <
> > wrote:
>
>> No, actually I am not reimplementing malloc, because my algorithm
>> guarantees no fragmentation and always 100% effective use of the allocated
>> memory.
>>
>> "Does that mean that the total space occupied by all Strings has to be
>> decided up front? "
>> Yes, just like the buffer for the serial ++
>>
>> I know I would opt to have the restriction for a predetermined allocated
>> space WITH error reporting (how we do is up to you guys, feed me with ideas
>> I'll implement whatever we agree is best) than having
>> seemingly infinite memory that crashes and burns.
>>
>> On Wed, Jan 5, 2011 at 7:33 PM, Alan Burlison <>wrote:
>>
>>> On 05/01/2011 18:25, Alexander Brevig wrote:
>>>
>>> Slightly unrelated to what you guys are discussing now but:
>>>> I'm not sure if I've made this clear, but the new version of String that
>>>> I'm
>>>> working on now does not use malloc or any other c function for dynamic
>>>> memory. What happens is that I allocate memory statically on the stack
>>>> and
>>>> serve that memory dynamically to the instances of String.
>>>>
>>>
>>> Does that mean that the total space occupied by all Strings has to be
>>> decided up front? If so, what is the behaviour when an allocation fails?
>>>
>>> To be honest I don't really see the point of doing this - all you are
>>> doing is re-implementing malloc.
>>>
>>> --
>>> Alan Burlison
>>> --
>>>
>>
>>
> > The other issue is that of object lifetimes. The test code has
> instances of String objects which are allocated on the stack and that
> are still in scope when the 'leak' memory check is performed.

That was also in my (off list) email a few days ago, though that bit
didn't make it here.

I believe the plan is to move the tests and object(s) they use to a
function, so the objects will be out of scope when the memory check is made.

There might also another copy of the test which pre-allocates a string
large enough to hold all the data. I'm not sure exactly how I feel
about that approach, but it seems like at least worth trying. Currently
the string library does not have a reserve() function. I've proposed it
before, and today I put it in issue #449.

> If a library routine used malloc to perform a one-time library-private
> buffer allocation where the buffer is retained for the lifetime of the
> program, the current leak checking would incorrectly report that as a
> leak. It isn't a leak because there's still a reference to the block
> inside the library.

Yes, you are correct, the test makes some assumptions about the internal
implementation, and yes, an ideal test wouldn't make any such
assumptions, and yes, it's probably impractical to completely avoid
assumptions on such limited hardware.

But there's a lot of value in actually testing on the real hardware,
with all its limitations and slight differences from running on a PC.
Personally, I think making some assumptions is a pretty good trade-off
for testing in the actual environment. Of course, there's plenty of
room for smart ideas to minimize such assumptions, or perhaps test in
multiple ways.

As someone who's spent a lot of time coding on the string class (and has
more planned), the real value isn't a perfect score if my code is bug
free, but rather a FAIL coming up when I make some mistake that
unexpectedly breaks something. Sure it's annoying if a FAIL comes up
erroneously because the internal implementation changed,

There are so many functions, with so many cases, that subtle errors can
happen (eg, does lastIndexOf work when the search string is the entire
original string... I broke that recently, but everything else worked.....)

If you have ideas about how to catch more types of errors, even if
imperfect, I'd really love to hear.




>
>
> The only semi-reliable way to do what you want is to use an
> instrumented malloc implementation, and that's going to be very
> difficult to implement on a constrained platform such as the AVR. If
> you want to test the String implementation for leaks, my advice is to
> do it on a more capable platform (e.g. *nix) and use one of the many
> instrumented mallocs that are available.
>


_______________________________________________
___________________________________________________

Posted on the Developers mailing list. Go to http://arduino.cc/mailman/listinfo/developers_arduino.cc to subscribe. I'm not sure I follow, string.read(); what would that do?
How do you imagine String to use Stream ? :)

Attached: new version arduino compitable

On Wed, Jan 5, 2011 at 8:20 PM, Tom Igoe <> wrote:

> Could you then just use Stream as a basis for String? Sorry, I didn't look
> into the details of your DMA class, but as long as we're setting a limit to
> begin with, and if we know Stream's pretty solid, why not restructure String
> a bit to use it?
>
> t.
>
>
> On Jan 5, 2011, at 1:42 PM, Alexander Brevig wrote:
>
> > No, actually I am not reimplementing malloc, because my algorithm
> guarantees no fragmentation and always 100% effective use of the allocated
> memory.
> >
> > "Does that mean that the total space occupied by all Strings has to be
> decided up front? "
> > Yes, just like the buffer for the serial ++
> >
> > I know I would opt to have the restriction for a predetermined allocated
> space WITH error reporting (how we do is up to you guys, feed me with ideas
> I'll implement whatever we agree is best) than having seemingly infinite
> memory that crashes and burns.
> >
> > On Wed, Jan 5, 2011 at 7:33 PM, Alan Burlison <>
> wrote:
> > On 05/01/2011 18:25, Alexander Brevig wrote:
> >
> > Slightly unrelated to what you guys are discussing now but:
> > I'm not sure if I've made this clear, but the new version of String that
> I'm
> > working on now does not use malloc or any other c function for dynamic
> > memory. What happens is that I allocate memory statically on the stack
> and
> > serve that memory dynamically to the instances of String.
> >
> > Does that mean that the total space occupied by all Strings has to be
> decided up front? If so, what is the behaviour when an allocation fails?
> >
> > To be honest I don't really see the point of doing this - all you are
> doing is re-implementing malloc.
> >
> > --
> > Alan Burlison
> > --
> >
> > _______________________________________________
___________________________________________________

Posted on the Developers mailing list. Go to http://arduino.cc/mailman/listinfo/developers_arduino.cc to subscribe. > I'm not sure I follow, string.read(); what would that do?
> How do you imagine String to use Stream ? :)

I also do not understand? In fact, I'm completely mystified. Please
explain...

But I would like to let you know I've been working on debugging the
string class, and in the last few days together with the test suite.
I'll likely post code sometimes next week.


>
> Attached: new version arduino compitable
>
> On Wed, Jan 5, 2011 at 8:20 PM, Tom Igoe <
> > wrote:
>
> Could you then just use Stream as a basis for String? Sorry, I
> didn't look into the details of your DMA class, but as long as
> we're setting a limit to begin with, and if we know Stream's
> pretty solid, why not restructure String a bit to use it?
>
> t.
>
>
> On Jan 5, 2011, at 1:42 PM, Alexander Brevig wrote:
>
> > No, actually I am not reimplementing malloc, because my
> algorithm guarantees no fragmentation and always 100% effective
> use of the allocated memory.
> >
> > "Does that mean that the total space occupied by all Strings has
> to be decided up front? "
> > Yes, just like the buffer for the serial ++
> >
> > I know I would opt to have the restriction for a predetermined
> allocated space WITH error reporting (how we do is up to you guys,
> feed me with ideas I'll implement whatever we agree is best) than
> having seemingly infinite memory that crashes and burns.
> >
> > On Wed, Jan 5, 2011 at 7:33 PM, Alan Burlison
> < > wrote:
> > On 05/01/2011 18:25, Alexander Brevig wrote:
> >
> > Slightly unrelated to what you guys are discussing now but:
> > I'm not sure if I've made this clear, but the new version of
> String that I'm
> > working on now does not use malloc or any other c function for
> dynamic
> > memory. What happens is that I allocate memory statically on the
> stack and
> > serve that memory dynamically to the instances of String.
> >
> > Does that mean that the total space occupied by all Strings has
> to be decided up front? If so, what is the behaviour when an
> allocation fails?
> >
> > To be honest I don't really see the point of doing this - all
> you are doing is re-implementing malloc.
> >
> > --
> > Alan Burlison
> > --
> >
> > _______________________________________________
___________________________________________________

Posted on the Developers mailing list. Go to http://arduino.cc/mailman/listinfo/developers_arduino.cc to subscribe. I'm very interested to see if one of your tests break the new version of the
String class Paul! the version with _3. If you manage to break it I'll shut
up about statically allocating a buffer forever, until then I'll probably
try to push for at least some more time :)

+1 internet to the one who first breaks the new lib, -1 for me (and I
promise, this is the first and last time I gamble in internets)

On Wed, Jan 5, 2011 at 8:09 PM, Paul Stoffregen <> wrote:

>
> The other issue is that of object lifetimes. The test code has instances
>> of String objects which are allocated on the stack and that are still in
>> scope when the 'leak' memory check is performed.
>>
>
> That was also in my (off list) email a few days ago, though that bit didn't
> make it here.
>
> I believe the plan is to move the tests and object(s) they use to a
> function, so the objects will be out of scope when the memory check is made.
>
> There might also another copy of the test which pre-allocates a string
> large enough to hold all the data. I'm not sure exactly how I feel about
> that approach, but it seems like at least worth trying. Currently the
> string library does not have a reserve() function. I've proposed it before,
> and today I put it in issue #449.
>
>
> If a library routine used malloc to perform a one-time library-private
>> buffer allocation where the buffer is retained for the lifetime of the
>> program, the current leak checking would incorrectly report that as a leak.
>> It isn't a leak because there's still a reference to the block inside the
>> library.
>>
>
> Yes, you are correct, the test makes some assumptions about the internal
> implementation, and yes, an ideal test wouldn't make any such assumptions,
> and yes, it's probably impractical to completely avoid assumptions on such
> limited hardware.
>
> But there's a lot of value in actually testing on the real hardware, with
> all its limitations and slight differences from running on a PC.
> Personally, I think making some assumptions is a pretty good trade-off for
> testing in the actual environment. Of course, there's plenty of room for
> smart ideas to minimize such assumptions, or perhaps test in multiple ways.
>
> As someone who's spent a lot of time coding on the string class (and has
> more planned), the real value isn't a perfect score if my code is bug free,
> but rather a FAIL coming up when I make some mistake that unexpectedly
> breaks something. Sure it's annoying if a FAIL comes up erroneously because
> the internal implementation changed,
>
> There are so many functions, with so many cases, that subtle errors can
> happen (eg, does lastIndexOf work when the search string is the entire
> original string... I broke that recently, but everything else worked.....)
>
> If you have ideas about how to catch more types of errors, even if
> imperfect, I'd really love to hear.
>
>
>
>
>
>
>>
>> The only semi-reliable way to do what you want is to use an instrumented
>> malloc implementation, and that's going to be very difficult to implement on
>> a constrained platform such as the AVR. If you want to test the String
>> implementation for leaks, my advice is to do it on a more capable platform
>> (e.g. *nix) and use one of the many instrumented mallocs that are available.
>>
>>
>
> _______________________________________________
___________________________________________________

Posted on the Developers mailing list. Go to http://arduino.cc/mailman/listinfo/developers_arduino.cc to subscribe. > If you manage to break it I'll shut
> up about statically allocating a buffer forever, until then I'll probably
> try to push for at least some more time :)
> +1 internet to the one who first breaks the new lib, -1 for me (and I
> promise, this is the first and last time I gamble in internets)

I'm sorry but your implementation is really badly broken. I can come
up with multiple potential ways to break it after only a cursory
inspection, plus the performance will be abysmal as you copy
everything around all the time.

Here are some things to think about:

1. What happens if a String contains an embedded null character?
2. What assumptions are you making about the maximum length of a
String, and the maximum number of allocated Strings?

--
Alan Burlison
--

_______________________________________________
___________________________________________________

Posted on the Developers mailing list. Go to http://arduino.cc/mailman/listinfo/developers_arduino.cc to subscribe. First off; I've not tried to say anything bad about the String library! And
when I say that it breaks I really mean to say that the implementation of
the memory allocation fails as it causes fragmentation and as such, you end
up with 'no available memory' even though you the available memory is there
only fragmented.

Have anyone tested the new version? It works here, with the old code that
created and manipulated multiple string instances in the loop(). It prints
the expected color endlessly. If the old version (really, *alloc/free)
breaks, then it has to at least be an indication of something potentially
good?

I can explain the algorithm if you guys are interested. It uses a kind of a
variation of http://en.wikipedia.org/wiki/Skip_list I think OpenGL uses the
same scheme for searching.
Basically each block knows its size so when searching you only access one
field per block, so in a memory of 100 cells and 5 blocks of 10 you would
need 4 iterations (as opposed to 40) in order to find the last block.
Furthermore, whenever a block need to grow it gets placed on the 'end' of
the memory and every block gets shifted towards the start. This way if the
memory was A B C D 0 0 0 (where 0 is availbale memory) and B had to grow to
become B B then the new memory would look like A C D B B 0 0, and as such,
the memory will always be maximized because there will never be
fragmentation.
For even more detail, just ask.


On Thu, Jan 6, 2011 at 2:08 AM, Alan Burlison <>wrote:

> > If you manage to break it I'll shut
> > up about statically allocating a buffer forever, until then I'll probably
> > try to push for at least some more time :)
> > +1 internet to the one who first breaks the new lib, -1 for me (and I
> > promise, this is the first and last time I gamble in internets)
>
> I'm sorry but your implementation is really badly broken. I can come
> up with multiple potential ways to break it after only a cursory
> inspection, plus the performance will be abysmal as you copy
> everything around all the time.
>
The only changes I have made is that I replaced all the old allocation calls
with a new.
The other codes you see are there to keep the pointer to the data updated as
it can now move in memory

I have added no copying, I only ever pass around addresses to objects. Have
you even looked at the source?

>
> Here are some things to think about:
>
> 1. What happens if a String contains an embedded null character?
>
Nothing other than what always happen, when you print it it will be capped
where the terminating 0 is


> 2. What assumptions are you making about the maximum length of a
> String, and the maximum number of allocated Strings?
>
I have made no assumptions yet, as I figured you guys wanted to be a part of
such a process.
I've just declared a buffer of 100 bytes.

We could potentially make the serial objects also use the SDM library as to
only allocate one buffer that all instances could share. This way the total
amount of memory allocated could be minimized.


> --
> Alan Burlison
> --
> On 06/01/2011 01:26, Alexander Brevig wrote:

> First off; I've not tried to say anything bad about the String library! And
> when I say that it breaks I really mean to say that the implementation of
> the memory allocation fails as it causes fragmentation and as such, you end
> up with 'no available memory' even though you the available memory is there
> only fragmented.

Yes, as with all allocators there's a tradeoff between speed and
potential fragmentation. the avr-glibc implementation takes a balanced
approach - it coalesces when it can, but keeps the cost of such attempts
low. Your implementation is at the other extreme, it always coalesces
and ignores the resulting performance consequences.

> Have anyone tested the new version? It works here, with the old code that
> created and manipulated multiple string instances in the loop(). It prints
> the expected color endlessly. If the old version (really, *alloc/free)
> breaks, then it has to at least be an indication of something potentially
> good?

The 'breakages' in the malloc version are almost certainly spurious as
they were caused by flaws in the test harness.

> The other codes you see are there to keep the pointer to the data updated as
> it can now move in memory
>
> I have added no copying, I only ever pass around addresses to objects. Have
> you even looked at the source?

Yes I've looked at the source, as I said in my previous mail. The
'moving in memory' is precisely what I'm talking about - you copy
everything around to coalesce free space.

>> 2. What assumptions are you making about the maximum length of a
>> String, and the maximum number of allocated Strings?
>>
> I have made no assumptions yet, as I figured you guys wanted to be a part of
> such a process. I've just declared a buffer of 100 bytes.

typedef char blockId;

static int currentID = 1

--
Alan Burlison
--

_______________________________________________
___________________________________________________

Posted on the Developers mailing list. Go to http://arduino.cc/mailman/listinfo/developers_arduino.cc to subscribe.





NewsArc Lists  |  Culture Pages   |  Computing Archive  |  Media-Pages
Link to this page on your blog or website by copying the HTML code below and pasting it into your site: