The following code causes a memory leak (actually, several, since it is run
numerous times). The problem is in the function BuildAnswerString, because
when I comment the call to that function and instead simply copy a new value
into the newData string (in SaveCurrentAnswer) the memory leaks are
eliminated. However, I can't figure out how to fix this. The problem is
definitely the MemPtrNew allocation in BuildAnswerString, but when I try and
free the pointer with MemPtrFree at the very end of the function, the
database doesn't end up with the right values. I believe that this is
because the pointers that have been set in EditQuestionRecord (called at the
end of BuildAnswerString) are no longer valid once the memory is freed. How
do I fix this problem?
****************************************************************************
*********
code
****************************************************************************
*********
/*--------------------------------------------------------------------------
-----------------------------------------------------------
Function: SaveCurrentAnswer
Desccription: saves the answer the user chose on current screen
Parameters: none
Return: none
----------------------------------------------------------------------------
---------------------------------------------------------*/
static void SaveCurrentAnswer(void) {
UInt32 offset;
char* newData;
//create data string
newData = BuildAnswerString();
//determine which screen is current
switch(current_state) {
case screen1:
offset=OffsetOf(questions_record_type, Question1Answer);
break;
case screen2:
offset=OffsetOf(questions_record_type, Question2Answer);
break;
case screen3:
offset=OffsetOf(questions_record_type, Question3Answer);
break;
case screen4:
offset=OffsetOf(questions_record_type, Question4Answer);
break;
case screen5:
offset=OffsetOf(questions_record_type, Question5Answer);
break;
case screen6:
offset=OffsetOf(questions_record_type, Question6Answer);
break;
case screen7:
offset=OffsetOf(questions_record_type, Question7Answer);
break;
case screen8:
offset=OffsetOf(questions_record_type, Question8Answer);
break;
case screen9:
offset=OffsetOf(questions_record_type, Question9Answer);
break;
case screen10:
offset=OffsetOf(questions_record_type, Question10Answer);
break;
case screen11:
offset=OffsetOf(questions_record_type, Question11Answer);
break;
case screen12:
offset=OffsetOf(questions_record_type, Question12Answer);
break;
case screen13:
offset=OffsetOf(questions_record_type, Question13Answer);
break;
case screen14:
offset=OffsetOf(questions_record_type, Question14Answer);
break;
case screen15:
offset=OffsetOf(questions_record_type, Question15Details);
break;
case screen16:
offset=OffsetOf(questions_record_type, Question16Details);
break;
case thanks:
//offset=OffsetOf(questions_record_type, Question1Answer);
break;
}//switch(current_state)
//edit record
EditQuestionRecord(offset,newData,currQuestionIndex);
}//SaveCurrentAnswer
/*--------------------------------------------------------------------------
-----------------------------------------------------------
Function: BuildAnswerString
Desccription: builds string from selected checkboxes
Parameters: none
Return: none
----------------------------------------------------------------------------
---------------------------------------------------------*/
static char* BuildAnswerString(void) {
UInt16 len=0;
char* newString;
Boolean addedSomething=false;
//get pointers to all checkboxes
ControlPtr labelP1=GetObjectPtr(AnswerAnswer1Checkbox);
ControlPtr labelP2=GetObjectPtr(AnswerAnswer2Checkbox);
ControlPtr labelP3=GetObjectPtr(AnswerAnswer3Checkbox);
ControlPtr labelP4=GetObjectPtr(AnswerAnswer4Checkbox);
ControlPtr labelP5=GetObjectPtr(AnswerAnswer5Checkbox);
ControlPtr labelP6=GetObjectPtr(AnswerAnswer6Checkbox);
ControlPtr labelP7=GetObjectPtr(AnswerAnswer7Checkbox);
//read checkbox labels
char* label1=(char*)CtlGetLabel(labelP1);
char* label2=(char*)CtlGetLabel(labelP2);
char* label3=(char*)CtlGetLabel(labelP3);
char* label4=(char*)CtlGetLabel(labelP4);
char* label5=(char*)CtlGetLabel(labelP5);
char* label6=(char*)CtlGetLabel(labelP6);
char* label7=(char*)CtlGetLabel(labelP7);
//find out whether boxes are selected
Boolean label1Selected = (CtlGetValue(labelP1)==1);
Boolean label2Selected = (CtlGetValue(labelP2)==1);
Boolean label3Selected = (CtlGetValue(labelP3)==1);
Boolean label4Selected = (CtlGetValue(labelP4)==1);
Boolean label5Selected = (CtlGetValue(labelP5)==1);
Boolean label6Selected = (CtlGetValue(labelP6)==1);
Boolean label7Selected = (CtlGetValue(labelP7)==1);
//calculate new string length
if(label1Selected) {
len+=StrLen(label1)+2;
}//if(label1Selected)
if(label2Selected) {
len+=StrLen(label2)+2;
}//if(label2Selected)
if(label3Selected) {
len+=StrLen(label3)+2;
}//if(label3Selected)
if(label4Selected) {
len+=StrLen(label4)+2;
}//if(label4Selected)
if(label5Selected) {
len+=StrLen(label5)+2;
}//if(label5Selected)
if(label6Selected) {
len+=StrLen(label6)+2;
}//if(label6Selected)
if(label7Selected) {
len+=StrLen(label7)+2;
}//if(label7Selected)
//allocate memory
newString=MemPtrNew(len);
if (label1Selected) {
StrCat(newString, label1);
addedSomething=true;
}//if (label1Selected)
if (label2Selected) {
if (addedSomething) {
StrCat(newString, "*");
}//if (addedSomething)
StrCat(newString, label2);
addedSomething=true;
}//if (label2Selected)
if (label3Selected) {
if (addedSomething) {
StrCat(newString, "*");
}//if (addedSomething)
StrCat(newString, label3);
addedSomething=true;
}//if (label3Selected)
if (label4Selected) {
if (addedSomething) {
StrCat(newString, "*");
}//if (addedSomething)
StrCat(newString, label4);
addedSomething=true;
}//if (label4Selected)
if (label5Selected) {
if (addedSomething) {
StrCat(newString, "*");
}//if (addedSomething)
StrCat(newString, label5);
addedSomething=true;
}//if (label5Selected)
if (label6Selected) {
if (addedSomething) {
StrCat(newString, "*");
}//if (addedSomething)
StrCat(newString, label6);
addedSomething=true;
}//if (label6Selected)
if (label7Selected) {
if (addedSomething) {
StrCat(newString, "*");
}//if (addedSomething)
StrCat(newString, label7);
addedSomething=true;
}//if (label7Selected)
return newString;
}//BuildAnswerString
/*--------------------------------------------------------------------------
-----------------------------------------------------------
Function: EditQuestionRecord
Desccription: edits a record from the questions database
Parameters: offset (UInt32) part of record to edit
Return: none
----------------------------------------------------------------------------
---------------------------------------------------------*/
Err EditQuestionRecord(UInt32 offset, char* newData, UInt16 index) {
MemHandle h;
questions_record_type *p;
Err error=0;
//grab a handle to the record
h = DmGetRecord(questionDatabaseRef, index);
//if handle was aquired sucesfully
if (h) {
//lock handle and grab pointer
p = (questions_record_type *)MemHandleLock(h);
error=DmWrite(p, offset,&newData, sizeof(char*));
//unlock the handle
MemPtrUnlock(p);
//release record and set dirty bit
DmReleaseRecord(questionDatabaseRef,index,true);
}//if (h)
//return whether op was successful
return error;
}//EditQuestionRecord
--
For information on using the Palm Developer Forums, or to unsubscribe, please see
http://www.palmos.com/dev/support/forums/