question about memory allocation and DmWrite()

question about memory allocation and DmWrite()

Post by Ethan Shayn » Mon, 01 Apr 2002 11:45:58



I am a little confused over how to handle memory allocation when
writing new records to a database. I understand that the basic flow
is:

1. open a database handle using DmOpenDatabaseByTypeCreator()
2. create a new record and get a handle to it using DmNewRecord()
3. lock the record using MemHandleLock()
4. fill in the new record with my new data using DmWrite()
5. unlock the record using MemHandleUnlock()
6. release the record handle using DmReleaseRecord()
7. close the database handle using DmCloseDatabase()

First, please correct me if the above is wrong. But assuming it's not
- my problem is with step #4.

Let's say that for example my database records consist of structures
like this:

typedef struct MyDatabaseEntryType
{
        Char* pszValOne;
        Char* pszValTwo;

Quote:} MyDatabaseEntryType;

Before I can call DmWrite(), I need to create a new instance of
MyDatabaseEntryType and fill in the two string values. Here's the
questions:

1. How should I allocate memory for pszValOne and pszValTwo, knowing
I'm going to be putting the overall structure in a database?

2. Should/can I deallocate the memory allocated to pszValOne and
pszValTwo immediately after I call DmWrite()? And if not, when is it
safe to do so? In other words, is DmWrite() making a copy of the data,
or is it simply storing a pointer to it?

To make this more complicated/concrete, what if I am specifically
getting pszValOne and pszValTwo from a form? In other words, I have a
form with two string fields on it and an "ok" button. In the form's
event handler, if the user clicked the "ok" button, I want to write
code to generate a new record in my database to store these two string
values, using the MyDatabaseEntryType struct described above. Can
someone give me a simple code snippet example of how I would do just
this part without causing memory issues?

        Thanks,
                Ethan Shayne

 
 
 

question about memory allocation and DmWrite()

Post by Ben Combe » Mon, 01 Apr 2002 14:13:07




Quote:> I am a little confused over how to handle memory allocation when
> writing new records to a database. I understand that the basic flow
> is:

> 1. open a database handle using DmOpenDatabaseByTypeCreator()
> 2. create a new record and get a handle to it using DmNewRecord()
> 3. lock the record using MemHandleLock()
> 4. fill in the new record with my new data using DmWrite()
> 5. unlock the record using MemHandleUnlock()
> 6. release the record handle using DmReleaseRecord()
> 7. close the database handle using DmCloseDatabase()

> First, please correct me if the above is wrong. But assuming it's not
> - my problem is with step #4.

> Let's say that for example my database records consist of structures
> like this:

> typedef struct MyDatabaseEntryType
> {
>    Char* pszValOne;
>    Char* pszValTwo;
> } MyDatabaseEntryType;

First mistake.  You can't really store pointers in a database record,
because its very likely that when you reopen the record, say in a future
launch of the program, the pointers won't be valid anymore.

Here, you're saving off two strings.  To do that, first compute the
space you need for the strings.  That can be done by

StrLen(entry.pszValOne) + StrLen(entry.pszValTwo) + 2

which computes the length of both strings and then adds two bytes for
two NUL terminators.

Quote:> Before I can call DmWrite(), I need to create a new instance of
> MyDatabaseEntryType and fill in the two string values. Here's the
> questions:

Nope.  Instead, you will store a packed copy of both strings.  So,
allocate using DmNewRecord to the size just computed, then use DmStrCopy
to copy the first string at offset 0.  Use DmStrCopy again to copy the
second string of offset StrLen(entry.pszValOne) + 1 to skip over the
just written first string.

Hope this helps...
--

CodeWarrior for Palm OS technical lead

 
 
 

question about memory allocation and DmWrite()

Post by Ethan Shayn » Tue, 02 Apr 2002 06:22:23


Thank you. That does help clarify how this works.

However, now I'm running into an error when I run my application on
the emulator:

MyApplication (1.0) just read from memory location 0x80001B80, causing
a bus error

So I must still be doing something wrong memory-wise. I suspect it may
have more to do with how I'm getting the text out of the form fields
than my original database questions, but I don't know for sure.

Here's the code I'm using to grab the fields off a form and write them
to the database:

        // get handles to the name and URL fields' text
        FormType* frmP = FrmGetActiveForm();

        FieldPtr pField1 = (FieldPtr) FrmGetObjectPtr(frmP,
FrmGetObjectIndex(frmP, Field1Field));
        UInt32 uiField1Length = FldGetTextLength(pField1);
        MemHandle hField1Text = FldGetTextHandle(pField1);

        FieldPtr pField2 = (FieldPtr) FrmGetObjectPtr(frmP,
FrmGetObjectIndex(frmP, Field2Field));
        UInt32 uiField2Length = FldGetTextLength(pField2);
        MemHandle hField2Text = FldGetTextHandle(pField2);

        // generate a new database entry
        UInt16 uiRecordIndex = 0;
        MemHandle hRecord = DmNewRecord(g_dbRef, &uiRecordIndex,
uiField1Length + uiField2Length + 2);

        // lock the (new) record and get a pointer to its contents
        MemPtr pRecordData = MemHandleLock(hRecord);

        // copy the data into the record
        DmStrCopy(pRecordData, 0, (Char*)hField1Text);
        DmStrCopy(pRecordData, uiField1Length + 1,
(Char*)hField2Text);

        // cleanup
        MemHandleUnlock(hRecord);
        DmReleaseRecord(g_dbRef, uiRecordIndex, true);

Any idea what I'm doing wrong?

        Thanks,
                Ethan Shayne





>> I am a little confused over how to handle memory allocation when
>> writing new records to a database. I understand that the basic flow
>> is:

>> 1. open a database handle using DmOpenDatabaseByTypeCreator()
>> 2. create a new record and get a handle to it using DmNewRecord()
>> 3. lock the record using MemHandleLock()
>> 4. fill in the new record with my new data using DmWrite()
>> 5. unlock the record using MemHandleUnlock()
>> 6. release the record handle using DmReleaseRecord()
>> 7. close the database handle using DmCloseDatabase()

>> First, please correct me if the above is wrong. But assuming it's not
>> - my problem is with step #4.

>> Let's say that for example my database records consist of structures
>> like this:

>> typedef struct MyDatabaseEntryType
>> {
>>        Char* pszValOne;
>>        Char* pszValTwo;
>> } MyDatabaseEntryType;

>First mistake.  You can't really store pointers in a database record,
>because its very likely that when you reopen the record, say in a future
>launch of the program, the pointers won't be valid anymore.

>Here, you're saving off two strings.  To do that, first compute the
>space you need for the strings.  That can be done by

>StrLen(entry.pszValOne) + StrLen(entry.pszValTwo) + 2

>which computes the length of both strings and then adds two bytes for
>two NUL terminators.

>> Before I can call DmWrite(), I need to create a new instance of
>> MyDatabaseEntryType and fill in the two string values. Here's the
>> questions:

>Nope.  Instead, you will store a packed copy of both strings.  So,
>allocate using DmNewRecord to the size just computed, then use DmStrCopy
>to copy the first string at offset 0.  Use DmStrCopy again to copy the
>second string of offset StrLen(entry.pszValOne) + 1 to skip over the
>just written first string.

>Hope this helps...

 
 
 

question about memory allocation and DmWrite()

Post by Ben Combe » Tue, 02 Apr 2002 07:14:50




Quote:> Thank you. That does help clarify how this works.

> However, now I'm running into an error when I run my application on
> the emulator:

> MyApplication (1.0) just read from memory location 0x80001B80, causing
> a bus error

Whenever you see a read from an address that starts with 0x8, it means
you've tried to dereference a handle without locking it.

Quote:> So I must still be doing something wrong memory-wise. I suspect it may
> have more to do with how I'm getting the text out of the form fields
> than my original database questions, but I don't know for sure.

> Here's the code I'm using to grab the fields off a form and write them
> to the database:

>    // get handles to the name and URL fields' text
>    FormType* frmP = FrmGetActiveForm();

>    FieldPtr pField1 = (FieldPtr) FrmGetObjectPtr(frmP,
> FrmGetObjectIndex(frmP, Field1Field));
>    UInt32 uiField1Length = FldGetTextLength(pField1);
>    MemHandle hField1Text = FldGetTextHandle(pField1);

>    FieldPtr pField2 = (FieldPtr) FrmGetObjectPtr(frmP,
> FrmGetObjectIndex(frmP, Field2Field));
>    UInt32 uiField2Length = FldGetTextLength(pField2);
>    MemHandle hField2Text = FldGetTextHandle(pField2);

Here, you should use FldGetTextPtr instead of FldGetTextHandle.  As long
as you don't keep the pointers around through an event loop, they will
be valid.

Quote:>    // generate a new database entry
>    UInt16 uiRecordIndex = 0;
>    MemHandle hRecord = DmNewRecord(g_dbRef, &uiRecordIndex,
> uiField1Length + uiField2Length + 2);

>    // lock the (new) record and get a pointer to its contents
>    MemPtr pRecordData = MemHandleLock(hRecord);

>    // copy the data into the record
>    DmStrCopy(pRecordData, 0, (Char*)hField1Text);

Having to do this cast should have set off warning bells?  Normally, a
cast is the wrong way to get one type turned into another.

Quote:>    DmStrCopy(pRecordData, uiField1Length + 1,
> (Char*)hField2Text);

>    // cleanup
>    MemHandleUnlock(hRecord);
>    DmReleaseRecord(g_dbRef, uiRecordIndex, true);

--

CodeWarrior for Palm OS technical lead
 
 
 

question about memory allocation and DmWrite()

Post by Ethan Shayn » Tue, 02 Apr 2002 07:34:08


Thank you.

I am unclear from the documentation about FldGetTextPtr, though - it
says that this returns a locked pointer to the text. Does that mean I
need to unlock it when I'm done? If so, would that be via
"MemHandleUnlock(pField1)"? Or some other call?

        Thanks,
                Ethan Shayne





>> Thank you. That does help clarify how this works.

>> However, now I'm running into an error when I run my application on
>> the emulator:

>> MyApplication (1.0) just read from memory location 0x80001B80, causing
>> a bus error

>Whenever you see a read from an address that starts with 0x8, it means
>you've tried to dereference a handle without locking it.

>> So I must still be doing something wrong memory-wise. I suspect it may
>> have more to do with how I'm getting the text out of the form fields
>> than my original database questions, but I don't know for sure.

>> Here's the code I'm using to grab the fields off a form and write them
>> to the database:

>>        // get handles to the name and URL fields' text
>>        FormType* frmP = FrmGetActiveForm();

>>        FieldPtr pField1 = (FieldPtr) FrmGetObjectPtr(frmP,
>> FrmGetObjectIndex(frmP, Field1Field));
>>        UInt32 uiField1Length = FldGetTextLength(pField1);
>>        MemHandle hField1Text = FldGetTextHandle(pField1);

>>        FieldPtr pField2 = (FieldPtr) FrmGetObjectPtr(frmP,
>> FrmGetObjectIndex(frmP, Field2Field));
>>        UInt32 uiField2Length = FldGetTextLength(pField2);
>>        MemHandle hField2Text = FldGetTextHandle(pField2);

>Here, you should use FldGetTextPtr instead of FldGetTextHandle.  As long
>as you don't keep the pointers around through an event loop, they will
>be valid.

>>        // generate a new database entry
>>        UInt16 uiRecordIndex = 0;
>>        MemHandle hRecord = DmNewRecord(g_dbRef, &uiRecordIndex,
>> uiField1Length + uiField2Length + 2);

>>        // lock the (new) record and get a pointer to its contents
>>        MemPtr pRecordData = MemHandleLock(hRecord);

>>        // copy the data into the record
>>        DmStrCopy(pRecordData, 0, (Char*)hField1Text);

>Having to do this cast should have set off warning bells?  Normally, a
>cast is the wrong way to get one type turned into another.

>>        DmStrCopy(pRecordData, uiField1Length + 1,
>> (Char*)hField2Text);

>>        // cleanup
>>        MemHandleUnlock(hRecord);
>>        DmReleaseRecord(g_dbRef, uiRecordIndex, true);

 
 
 

question about memory allocation and DmWrite()

Post by Ben Combe » Tue, 02 Apr 2002 13:05:13




Quote:> Thank you.

> I am unclear from the documentation about FldGetTextPtr, though - it
> says that this returns a locked pointer to the text. Does that mean I
> need to unlock it when I'm done? If so, would that be via
> "MemHandleUnlock(pField1)"? Or some other call?

Internally, when a form is open, Palm OS keeps a locked pointer to the
text of the field at all times.  When Palm OS wants to resize the field,
it unlocks this pointer, resizes, then locks it again.  When you call
FldGetTextPtr, you get a copy of this locked pointer -- this is why I
said its safe to use until the next event, as the OS doesn't get a
chance to play with the underlying handle again until it gets control.
--

CodeWarrior for Palm OS technical lead
 
 
 

1. Memory Allocation Question....

Hi,

Would you be able to answer the followings?

1)  How do you verify deallocation of memory pool?  If one dynamically
allocates a fixed size memory say 10 intigers and writes the values 1
through 9 into this place,  does one see nothing there when you free()?
Does this mean that the values are erased or what.  My experience showed

the numbers were still there doing memShow().

2)  How can I verify that the size of memory pool is configurable at
startup time and that the pool does not need to be contigous memory
areas.

If you can give a code example, it is also fine.

Thank you very much..

2. Modem compatibility

3. Memory Allocation and Deallication in VxWorks question

4. I get the all attachments twice!

5. Question(s) re VxWorks System Memory Pool addresses allocation on

6. The best modem on the marker ....?

7. Newbie question - debugging memory allocation problems

8. Need help using Wizard as remote terminal

9. Memory Allocation Question

10. Question about memory allocation and Vinoski's book

11. question about memory allocation with Minix PC

12. Minix 1.5 Memory Allocation Question

13. Pixmap memory allocation question.