objective-c - 使用 kinfo_proc 时出现 EXC_BAD_ACCESS 错误

标签 objective-c xcode bsd

我尝试使用 KVMBSD 获取正在运行的进程列表。但是我的 NSLog 语句中出现了 EXC_BAD_ACCESS 错误。我该如何处理?

int main(int argc, char *argv[]) {
    @autoreleasepool {
        struct kinfo_proc *procs;
        size_t count;
        int err = GetBSDProcessList(&procs, &count);
        if (err) return err;
        for (size_t i=0; i!=count; ++i) {
            NSLog(@"%d\n", procs[i].kp_proc.p_pid);
        }
        free(procs);
    }
}

请帮忙。

最佳答案

我不知道你从哪里得到 GetBSDProcessList 函数,但通过一些搜索我找到了一个 implementation并且以下代码工作正常:

#import <Foundation/Foundation.h>
#import <sys/sysctl.h>

typedef struct kinfo_proc kinfo_proc;

static int GetBSDProcessList(kinfo_proc **procList, size_t *procCount);

int main(int argc, const char *argv[]) {
    @autoreleasepool {
        kinfo_proc *procList;
        size_t count;
        int err = GetBSDProcessList(&procList, &count);
        if (err) return err;
        for (size_t i = 0; i != count; ++i) {
            NSLog(@"%d\n", procList[i].kp_proc.p_pid);
        }
        free(procList);
    }
    return 0;
}

static int GetBSDProcessList(kinfo_proc **procList, size_t *procCount)
// Returns a list of all BSD processes on the system.  This routine
// allocates the list and puts it in *procList and a count of the
// number of entries in *procCount.  You are responsible for freeing
// this list (use "free" from System framework).
// On success, the function returns 0.
// On error, the function returns a BSD errno value.
{
    int err;
    kinfo_proc *result;
    bool done;
    static const int name[] = {CTL_KERN, KERN_PROC, KERN_PROC_ALL, 0};
    // Declaring name as const requires us to cast it when passing it to
    // sysctl because the prototype doesn't include the const modifier.
    size_t length;

    assert(procList != NULL);
    assert(*procList == NULL);
    assert(procCount != NULL);

    *procCount = 0;

    // We start by calling sysctl with result == NULL and length == 0.
    // That will succeed, and set length to the appropriate length.
    // We then allocate a buffer of that size and call sysctl again
    // with that buffer.  If that succeeds, we're done.  If that fails
    // with ENOMEM, we have to throw away our buffer and loop.  Note
    // that the loop causes use to call sysctl with NULL again; this
    // is necessary because the ENOMEM failure case sets length to
    // the amount of data returned, not the amount of data that
    // could have been returned.

    result = NULL;
    done = false;
    do {
        assert(result == NULL);

        // Call sysctl with a NULL buffer.

        length = 0;
        err = sysctl((int *) name, (sizeof(name) / sizeof(*name)) - 1,
                NULL, &length,
                NULL, 0);
        if (err == -1) {
            err = errno;
        }

        // Allocate an appropriately sized buffer based on the results
        // from the previous call.

        if (err == 0) {
            result = malloc(length);
            if (result == NULL) {
                err = ENOMEM;
            }
        }

        // Call sysctl again with the new buffer.  If we get an ENOMEM
        // error, toss away our buffer and start again.

        if (err == 0) {
            err = sysctl((int *) name, (sizeof(name) / sizeof(*name)) - 1,
                    result, &length,
                    NULL, 0);
            if (err == -1) {
                err = errno;
            }
            if (err == 0) {
                done = true;
            } else if (err == ENOMEM) {
                assert(result != NULL);
                free(result);
                result = NULL;
                err = 0;
            }
        }
    } while (err == 0 && !done);

    // Clean up and establish post conditions.

    if (err != 0 && result != NULL) {
        free(result);
        result = NULL;
    }
    *procList = result;
    if (err == 0) {
        *procCount = length / sizeof(kinfo_proc);
    }

    assert((err == 0) == (*procList != NULL));

    return err;
}

我正在使用 Xcode 10 Beta 2 在 Mac OS X Mojave Beta 2 上运行这段代码,这里是简单的控制台输出:

.
.
.
2018-06-22 11:22:59.540990+0300 ProcessList[2407:96970] 58
2018-06-22 11:22:59.541040+0300 ProcessList[2407:96970] 55
2018-06-22 11:22:59.541057+0300 ProcessList[2407:96970] 54
2018-06-22 11:22:59.541067+0300 ProcessList[2407:96970] 52
2018-06-22 11:22:59.541075+0300 ProcessList[2407:96970] 51
2018-06-22 11:22:59.541084+0300 ProcessList[2407:96970] 49
2018-06-22 11:22:59.541092+0300 ProcessList[2407:96970] 47
2018-06-22 11:22:59.541101+0300 ProcessList[2407:96970] 46
2018-06-22 11:22:59.541109+0300 ProcessList[2407:96970] 45
2018-06-22 11:22:59.541134+0300 ProcessList[2407:96970] 42
2018-06-22 11:22:59.541257+0300 ProcessList[2407:96970] 41
2018-06-22 11:22:59.541280+0300 ProcessList[2407:96970] 1
2018-06-22 11:22:59.541290+0300 ProcessList[2407:96970] 0
Program ended with exit code: 0

关于objective-c - 使用 kinfo_proc 时出现 EXC_BAD_ACCESS 错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50795186/

相关文章:

c - 当我阅读 bsd 4.4 的核心代码时,无法处理似乎不必要的指针

ios - 如何使用 iOS 应用程序识别 BTLE 设备的名称、UUID、RSSI 和大致距离

iphone - 在缩放的 MKMapView 上合并注释

ios - 具有方言的字符串中的 NSRange

ios - Xcode 中的键盘快捷键删除约束而不是卸载它?

md5 - BSD md5 与 GNU md5sum 输出格式?

objective-c - 为报亭应用制作应用内商店

objective-c - 如何像时间机器一样创建开/关动画?

arrays - Swift 无法在元组数组中插入 int 值

linux - 在 OSX 上与 git 一起使用时,lesskey 配置不会被 less pager 使用