开发者

sysctl in a NSAutoreleasePool -> bus errors & segfaults

Thanks in advance to everyone trying to help me. I'm having a big issue here, I've found some example code about sysctl and extended it so I can query the network interfaces for their in/out data. When I run this code directly in main() (without any NSAutoreleasePool) everything works fine. However, once I add it to my class and execute it I get bus errors & segfaults. I've tracked the issue down to NSAutoreleasePools. Can anybody please help? (If you don't believe it, just place a NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; before the code 开发者_StackOverflow中文版and place the whole thing into main())

int mib[] = { CTL_NET, PF_ROUTE, 0, 0, NET_RT_IFLIST, 0 };

    int alloc;

    struct if_msghdr    *ifm, *nextifm;
    struct sockaddr_dl  *sdl;
    char        *lim, *next;
    size_t      needed;
    char        s[32];

    char* buf;
    if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0)
        return 0;

    if (alloc < needed) {
        buf = malloc(needed);
        if (buf == NULL)
            return 0;
        alloc = needed;
    }

    if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0)
        return 0;
    lim = buf + needed;

    next = buf;
    while (next < lim) {
        ifm = (struct if_msghdr *)next;

        if (ifm->ifm_type != RTM_IFINFO)
            return 0;
        next += ifm->ifm_msglen;

        while (next < lim) {
            nextifm = (struct if_msghdr *)next;
            if (nextifm->ifm_type != RTM_NEWADDR)
                break;
            next += nextifm->ifm_msglen;
        }        

        if (ifm != NULL && ifm->ifm_flags & IFF_UP) {
            sdl = (struct sockaddr_dl *)(ifm + 1);
            if (sdl->sdl_family != AF_LINK)
                continue;
            strncpy(s, sdl->sdl_data, sdl->sdl_nlen);
            s[sdl->sdl_nlen] = '\0';
            NSLog(@"interface %s in %qu out %qu \n", s,(UInt64)ifm->ifm_data.ifi_ibytes, (UInt64)ifm->ifm_data.ifi_obytes );
        }
    }


The NSAutoreleasePool isn't the problem. It just reveals that you have a problem with memory allocation, double releases, dangling pointers or uninitialized data.

In your case, it's uninitialized data. You don't initialize the alloc variable. As a consequence, it's completely random whether buf is allocated or is pointing to some random memory location.


My hunch is it's to do with your misuse of strncpy(). You're copying sdl->sdl_nlen characters. If this is larger than 32, then you're overflowing your buffer. If it's exactly 32, then your assignment of \0 is outside of s[] (likely in buf).

In either case, you're passing some kind of illegal memory to NSLog(), which itself generates autoreleased variables. Likely one of those is responsible for the crash when the pool drains.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜