discuss-gnustep
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

possible NSInvocation bugs


From: Stephen Brandon
Subject: possible NSInvocation bugs
Date: Tue, 19 Feb 2002 18:16:01 +0000

Hi,

I'm just trying to get my head around the way NSInvocation works on GNUstep, 
cos it seems to not be doing what it should.

I'm trying to do a "retainArguments" on an invocation that will be queued up 
and sent in another thread. The rest of the system works ok - it just that 
the extra retains are not being added to the arguments, and sometimes they go 
and get released before the invocation is sent - kaboom on the other end.

I'm on a fresh install of RedHat linux 7.2, using gcc-2.96. I have compiled 
and installed the ffcall package.

here's the code chunk:
    [anInvocation setSelector:sel];
    [anInvocation setTarget:target];
    [anInvocation setArgument:&arg1 atIndex:2];
    [anInvocation setArgument:&arg2 atIndex:3];
    [anInvocation retainArguments];

Breakpoint 2, _i_NSInvocation__retainArguments (self=0x853fc58, 
_cmd=0x403508e8) at NSInvocation.m:362
362       if (_argsRetained)
(gdb) next
370           _argsRetained = YES;
(gdb)
371           IF_NO_GC(RETAIN(_target));
(gdb)
372           if (_argframe == 0)
(gdb)
374               return;
(gdb)
407     }
(gdb) p *self
$17 = {isa = 0x40646b60, _sig = 0x8341b58, _argframe = 0x0, _cframe = 
0x8167e00, _retval = 0x8167e40,
  _target = 0x813ab88, _selector = 0x40352c10, _numArgs = 4, _info = 
0x8494bb0, _argsRetained = 1 '\001',
  _validReturn = 0 '\000', _sendToSuper = 0 '\000'}

... so the first problem here is that it's checking for _argframe as a proof 
of (perhaps?) whether or not the arguments have been set. I don't completely 
understand how this all works, but it's clear that either _argframe should 
have been set somewhere else, or it should not be checked here.

Suggested solution:
NSInvocation.m:37c
change: if (_argframe == 0)
to: if (_argframe == 0 && _cframe == 0)
since I think that the object will use either argframes or cframes 
depending on which backend implementation is being used.

Second problem:
If I do the -retainArguments call *before* setting the arguments, I get a 
segfault when I set argument atIndex:3. Tracing this through, it does the 
following:

_i_NSInvocation__setArgument_atIndex_ (self=0x8276b78, _cmd=0x403508d8, 
buffer=0xbfffcb10, index=2)
    at NSInvocation.m:250
250       if ((unsigned)index >= _numArgs)
(gdb) step
255       if (index == 0)
(gdb)
259       else if (index == 1)
(gdb)
265           int               i = index+1;    /* Allow for return type in 
'_info' */
(gdb)
266           const char        *type = _info[i].type;
(gdb)
268           if (_argsRetained && (*type == _C_ID || *type == _C_CHARPTR))
(gdb) p type
$4 = 0x8341b67 "@8@12"   (so it's definitely an id type)
(gdb) step
270               if (*type == _C_ID)
(gdb)
274                   _get_arg(self, index, &old);
(gdb) step
_get_arg (inv=0x8276b78, index=2, buffer=0xbfffca9c) at NSInvocation.m:69
69        callframe_get_arg((callframe_t *)inv->_cframe, index, buffer,
(gdb) list
65      #elif defined(USE_FFCALL)
66      static inline void
67      _get_arg(NSInvocation *inv, int index, void *buffer)
68      {
69        callframe_get_arg((callframe_t *)inv->_cframe, index, buffer,
70                          inv->_info[index+1].size);
71      }

(gdb) step
71      }
(gdb)
_i_NSInvocation__setArgument_atIndex_ (self=0x8276b78, _cmd=0x403508d8, 
buffer=0xbfffcb10, index=2)
    at NSInvocation.m:275
275                   _set_arg(self, index, buffer);
(gdb) p *old
Cannot access memory at address 0x680073
(gdb) p old
$12 = 0x680073
(gdb) step
_set_arg (inv=0x8276b78, index=2, buffer=0xbfffcb10) at NSInvocation.m:76
76        callframe_set_arg((callframe_t *)inv->_cframe, index, buffer,
(gdb) step
78      }
(gdb)
_i_NSInvocation__setArgument_atIndex_ (self=0x8276b78, _cmd=0x403508d8, 
buffer=0xbfffcb10, index=2)
    at NSInvocation.m:276
276                   IF_NO_GC(RETAIN(*(id*)buffer));
(gdb) step
277                   if (old != nil)
(gdb) step
279                       RELEASE(old);
(gdb) step

Program received signal SIGSEGV, Segmentation fault.

... Oooops - looks like callframe_get_arg() had grabbed back an invalid 'old' 
value, which causes a crash when released.

Sorry, I have no idea how to address this one!


Any help appreciated. I'm pretty confident I have the 1st problem solved with 
the patch mentioned, but the second one is more difficult!

Cheers,
Stephen Brandon



reply via email to

[Prev in Thread] Current Thread [Next in Thread]