سؤال

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 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.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top