Go Down

Topic: Memory leak in WString / TextString Library? (Read 4568 times) previous topic - next topic

tigoe

I just posted version 0.7 of the String lib, which is basically the bug fix Mikal Hart posted.  Sorry for the long delay. String is not part of the core, so it's always been a side project for me, and one I only get to once in a blue moon. The memory bug,at least, should now be gone. Thanks Mikal.

This is an interim version. Hernando Barragan made some nice API changes for a Wiring version, but they change the core libraries a bit, and have not yet been ported over fully. There are also some changes I want to make, because there's some nomenclature and behavior I'm not happy with.   Xiaoyang Feng is working on this.  The major issue he's working on is to make the library portable without need to modify the core, and to reduce memory usage somewhat.  If anyone wants to jump in on this task, mail me.

retrolefty

Quote
I just posted version 0.7 of the String lib


Where might I find the link/posting for this new version?

Thanks;
Lefty

TBAr

#17
Mar 29, 2010, 11:40 pm Last Edit: Mar 29, 2010, 11:44 pm by TBAr Reason: 1
Lefty, it looks like it's linked off of http://www.arduino.cc/en/Tutorial/TextString.

The page history shows it was updated today, and the WString.h file in the .ZIP file reflects version 0.7.

scrambler

#18
Jun 18, 2010, 04:21 pm Last Edit: Jun 18, 2010, 04:29 pm by scrambler Reason: 1
Destructor need inicializate vars:

Code: [Select]

String::~String() {
     free(_array);
     _capacity = 0;
     _length = 0;  
}

http://www.megaupload.com/?d=7TAT552N


Do you lost memory with substring?

NealT

#19
Jun 23, 2010, 01:37 am Last Edit: Jun 23, 2010, 01:44 am by ntovsen Reason: 1
Many thanks for this thread. It has helped a very frustrating problem!


But once I place the destructor in my code (or download the new zip...same thing), it doesn't function the same any more. Here's the relevant code:
Code: [Select]

void somefunction()
{
 char* timestamp = isoTimestamp();
 
 Serial.println(timestamp);
}


// iso8601 timestamp of current time
char* isoTimestamp(){
 Serial.println("in isoTimestamp");
 time_t t = now();

 Serial.println("Allocating String(20)");
 String str = String(20);

 Serial.println("Formatting timestamp");
 str.append(year(t));
 str.append("-");
 if(month(t) < 10) str.append("0");
 str.append(month(t));
 str.append("-");
 if(day(t) < 10) str.append("0");
 str.append(day(t));
 str.append("T");
 if(hour(t) < 10) str.append("0");
 str.append(hour(t));
 str.append(":");
 if(minute(t) < 10) str.append("0");
 str.append(minute(t));
 str.append(":");
 if(second(t) < 10) str.append("0");
 str.append(second(t));
 str.append("Z");

 Serial.print("isoTimestamp: ");
 Serial.println(str);
 
 char* outputChars = str.getChars();

 Serial.print("char isoTimestamp: ");
 Serial.println(outputChars);

 return str;
}


The above prints:
in isoTimestamp
Allocating String(20)
Formatting timestamp
isoTimestamp: 2010-06-22T23:33:23Z
char isoTimestamp: 2010-06-22T23:33:23Z
+?10-06-22T23:33:23Z

Note the two first bytes in the returned char* are wrong/odd (it isn't really a '?', but it was interpreted as a newline in the forum post). This occurs whether I "return str;" or "return str.toChars();"

I'm still pretty new to Arduino, and haven't messed with C-based stuff (aka pointers) since college long ago, so hopefully this is just a newbie mistake. But it worked fine before adding the String destructor. Well, other than the memory leak, anyway! Can someone help?

Thanks in advance.

PaulS

In the isoTimestamp function, you have:
Code: [Select]
String str = String(20);
.
.
.
 return str;

str is a local variable. It does out of scope at the end of the function. And, yet, you return a pointer to internally allocated memory of that string. The memory no longer is reserved by the variable (because the variable is out of scope). The memory was released, but has not yet been entirely) overwritten.

You could have isoTimestamp return the output of the strdup function, which allocates memory and copies the string:

Code: [Select]
return strdup(str);

tehjrow

I used the new library download and mine still freezes.  Takes about 20min running the following code.  Any suggestions?
I leave the webpage open and it refreshes the get8 and get3 every 2 seconds.



Code: [Select]
#include <WString.h>
#include <Ethernet.h>
#include <stdlib.h>
byte mac[] = { 0x00, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
byte ip[] = { 192, 168, 1, 30 }; // MY IP change to your needs
Server server(80);
String readString = String(100);


void setup(){
 
 Serial.begin(9600);
 pinMode(8, OUTPUT);
 pinMode(7, OUTPUT);
 pinMode(3, OUTPUT);
 Ethernet.begin(mac, ip);
 digitalWrite(7, HIGH);
}

void loop(){
 Client client = server.available();
 if (client)
 {
   while (client.connected())
   {
     if (client.available())
       {
       char c = client.read();
       if (readString.length() < 100)
           {
           readString.append(c);
         }
       if (c == '\n')
           {
             //code for pin 8
           if(readString.contains("toggle8"))
               {
             toggle(8);
                 //client.println("<html><head>");
                 //client.println("<meta http-equiv=REFRESH content=0;url='http://192.168.1.31/frontend.php'>");
                 //client.println("</head></html>");
               }
             if(readString.contains("get8")){
         // Now output HTML data starting with standart header
         client.println("HTTP/1.1 200 OK");
         client.println("Content-Type: text/html");
         client.println();
         //client.println("led 8 is");
           //client.println(digitalRead(8));
           if(digitalRead(8) == 0){
             client.print("<IMG SRC=images/lightoff.png>");}
             else if(digitalRead(8) == 1){
             client.print("<IMG SRC=images/lighton.png>");}
           Serial.println("pin 8 is");
           Serial.println(digitalRead(8));
             }
       
           //code for pin 3
           if(readString.contains("toggle3"))
               {
             toggle(3);
                 //client.println("<html><head>");
                 //client.println("<meta http-equiv=REFRESH content=0;url='http://192.168.1.31/frontend.php'>");
                 //client.println("</head></html>");
               }
           if(readString.contains("get3")){
         // Now output HTML data starting with standart header
         client.println("HTTP/1.1 200 OK");
         client.println("Content-Type: text/html");
         client.println();
         //client.println("led 8 is");
           //client.println(digitalRead(3));
           if(digitalRead(3) == 0){
             client.print("<IMG SRC=images/lightoff.png>");}
             else if(digitalRead(3) == 1){
             client.print("<IMG SRC=images/lighton.png>");}
           Serial.println("pin 3 is");
           Serial.println(digitalRead(3));
             }
           
           
           
           
           readString="";
         client.stop();
           
             }
           }
       }
     }
   
 
}

int toggle(int pinnumber){
 if(digitalRead(pinnumber) == HIGH){
   Serial.print("toggle functions says ");
   Serial.print(pinnumber);
   Serial.print(" is on");
   Serial.println();
   // if light is on turn it off
   digitalWrite(pinnumber, LOW);
   return(0);
 }
 if(digitalRead(pinnumber) == LOW){
   Serial.print("toggle functions says ");
   Serial.print(pinnumber);
   Serial.print(" is off");
   Serial.println();
   // if light is off turn it on
   digitalWrite(pinnumber, HIGH);
   return(0);
 }
}



Go Up