Author Topic: When To Free resbuf?  (Read 3282 times)

0 Members and 1 Guest are viewing this topic.

It's Alive!

  • BricsCAD
  • Needs a day job
  • Posts: 6963
  • AKA Daniel
When To Free resbuf?
« on: December 28, 2006, 02:28:12 AM »
In one of the SDK Samples “fact_dg”, there is code showing how to get a result buffer from lisp then releasing the buffer using acutRelRb
Code: [Select]
struct resbuf *rb = acedGetArgs();
. . .
//release rb
acutRelRb(rb);


sometimes when I add the code to release the resbuf. I get an access violation.
I’m wondering if someone could shed some light on where I am going wrong

Thanks
Dan

Code: [Select]
if (rb != NULL)
acutRelRb(rb);

This works

Code: [Select]
#pragma region crpsysfilesystem
    // ----- ads_crpsysfilesystem symbol (do not rename)
    //(crpsysfilesystem "c")
    static int ads_crpsysfilesystem(void)
    {
        //----- Remove the following line if you do not expect any argument for this ADS function
        CString str;
        CString strout;
        struct resbuf *rb = NULL;
        struct resbuf *pArgs =acedGetArgs () ;
        if (pArgs == NULL)
        {
            str = "C";
        }
        else if (pArgs->restype == RTSTR)
        {
            str = pArgs->resval.rstring;
        }
        else
        {
            str = "C";
        }
        str.Truncate(1);
        str = str + ":\\";
        ACHAR FileSystem[16];
        GetVolumeInformationW(str, NULL, 0, NULL, NULL, NULL, FileSystem, 16 );
        if (!FileSystem == NULL)
        {
            rb = acutBuildList(RTSTR, FileSystem, RTNONE);
            acedRetList(rb);
        }
        else
        {
            acedRetNil();
        }
        if (rb != NULL)
            acutRelRb(rb);
        if (pArgs != NULL)
            acutRelRb(pArgs);
        return (RSRSLT) ;
    }
#pragma endregion


This one fails

Code: [Select]

#pragma region crpmessagebox
    // ----- ads_crpmessagebox symbol (do not rename)
    //(crpMessageBox "What the heck are you doing? " "Error" 5 4 )
    static int ads_crpmessagebox(void)
    {
        wchar_t Text[1024] ;
        wchar_t Caption[256];
        int Button;
        int Icon;
        UINT ButtonF;
        UINT IconF;
        struct resbuf *pArgs = acedGetArgs() ;
        if (pArgs == NULL || pArgs->restype != RTSTR )
        {
            acedRetNil();
            return (RSRSLT);
        }
        else
        {
            wcscpy_s(Text, 1024 , pArgs->resval.rstring);
        }
        if ((pArgs = pArgs->rbnext) == NULL || pArgs->restype != RTSTR )
        {
            acedRetNil();
            return (RSRSLT);
        }
        else
        {
            wcscpy_s(Caption, 256 , pArgs->resval.rstring);
        }
        if ((pArgs = pArgs->rbnext) == NULL || pArgs->restype != RTSHORT  )
        {
            acedRetNil();
            return (RSRSLT);
        }
        else
        {
            Button = (int)pArgs->resval.rint;
            switch (Button)
            {
            case 0:
                ButtonF = MB_OK;
                break;
            case 1:
                ButtonF = MB_OKCANCEL;
                break;
            case 2:
                ButtonF = MB_ABORTRETRYIGNORE;
                break;
            case 3:
                ButtonF = MB_YESNOCANCEL;
                break;
            case 4:
                ButtonF = MB_YESNO;
                break;
            case 5:
                ButtonF = MB_RETRYCANCEL;
                break;
            default:
                ButtonF = 0;
            }
        }
        if ((pArgs = pArgs->rbnext) == NULL || pArgs->restype != RTSHORT)
        {
            acedRetNil();
            return (RSRSLT);
        }
        else
        {
            Icon = (int)pArgs->resval.rint;
            Button = (UINT)pArgs->resval.rint;
            switch (Icon)
            {
            case 1:
                IconF = MB_ICONERROR;
                break;
            case 2:
                IconF = MB_ICONQUESTION;
                break;
            case 3:
                IconF = MB_ICONWARNING;
                break;
            case 4:
                IconF = MB_ICONINFORMATION;
                break;
            default:
                IconF = 0;
            }
        }
        short res = 0;
        HWND hwDocWnd = adsw_acadDocWnd();
        res = MessageBoxW(hwDocWnd , Text , Caption ,  ButtonF | IconF);
        acedRetInt(res);
        //if (pArgs != NULL)
        //    acutRelRb(pArgs); -> causes access violation
        pArgs = NULL;
        return (RSRSLT) ;
    }
#pragma endregion

It's Alive!

  • BricsCAD
  • Needs a day job
  • Posts: 6963
  • AKA Daniel
Re: When To Free resbuf?
« Reply #1 on: December 28, 2006, 02:40:17 AM »
Here is a quote from the docs,
Quote
Unlike the result lists returned by other ARX library functions, the list returned by acedGetArgs() is managed by the ARX library, so the application does not explicitly have to release the list. (A call to acutRelRb() that specifies this list has no effect.) Applications needing data in the list should make copies of it.
If this is the case, I wonder why they use acutRelRb() on acedGetArgs() in the sample? Can I assume that AutoCAD will manage this memory, since I am just using a pointer?
Dan

It's Alive!

  • BricsCAD
  • Needs a day job
  • Posts: 6963
  • AKA Daniel
Re: When To Free resbuf?
« Reply #2 on: December 28, 2006, 02:48:06 AM »
Doh! I think I see what’s going on. I made this call
Code: [Select]
pArgs = pArgs->rbnextI assume this where I am changing things.

I would still like to hear from the ARX Gods for guidance on this

Thanks


PS: I know this looks like I am talking to myself
But I’m just not that way… well maybe I am…
« Last Edit: December 28, 2006, 02:50:42 AM by Danielm103 »

Chuck Gabriel

  • Guest
Re: When To Free resbuf?
« Reply #3 on: December 28, 2006, 08:03:29 AM »
The line you pointed out is certainly a problem.  Just make another pointer to use as you iterate through the list (I believe resbuf is implemented as a linked list).

I've run into the same kind of issue before using pointer arithmetic to iterate over a character array without leaving a base pointer intact.

It's Alive!

  • BricsCAD
  • Needs a day job
  • Posts: 6963
  • AKA Daniel
Re: When To Free resbuf?
« Reply #4 on: December 28, 2006, 11:41:21 AM »
Thanks Chuck,
That’s what the docs are saying. I guess I need to read the docs before the samples   :-o
These resbufs are kind of a pain in unamaged code, especially for a greenhorn like me.

Chuck Gabriel

  • Guest
Re: When To Free resbuf?
« Reply #5 on: December 28, 2006, 01:11:24 PM »
They do kind of seem like some sort of vestigial limb left over from the C days, don't they?