Непрерывный вызов [NSPasteboard canReadObjectForClasses: options:] вызывает переполнение памяти - PullRequest
0 голосов
/ 12 сентября 2018

Я использую следующую простую программу Objective-C для получения сообщений от другого процесса и отображения предупреждений, используя NSPasteboard в качестве средства связи между двумя процессами.Программа работает для меня, но я заметил, что она потребляет огромные объемы оперативной памяти, независимо от того, отправляет ли партнерский процесс новые сообщения на монтажную панель и вводится ли внутренний блок предупреждений.Он генерирует файлы подкачки 1G за /private/var/vm/ каждые несколько минут, пока работает, пока я его не уничтожу.

Я запустил программу с помощью инструментов XCode и вижу, что [NSPasteboard canReadObjectForClasses:options:] создает постоянные __NSArrayI объекты каждый разэто называется, который является источником раздувания ОЗУ.Кто-нибудь еще может это подтвердить?Это ошибка в [NSPasteboard canReadObjectForClasses:options:], или я просто должен выполнить эту задачу по-другому?

РЕДАКТИРОВАТЬ:
Я изначально забыл включить ARC .Однако даже при включенном ARC рост использования памяти все еще значительно опережает автоматическое освобождение памяти, а файлы подкачки все еще создаются со временем.У кого-нибудь есть предложения о том, как я могу переписать этот сценарий, чтобы использовать лучшее соглашение, чем while(true), чтобы [NSPasteboard canReadObjectForClasses:options:] вызывалось меньше?Мне также кажется странным, что эта функция AppKit не освобождает автоматически создаваемые ею __NSArrayI объекты и предполагает, что ARC позаботится об этом;это обычная практика для такой библиотеки?

#import <Foundation/Foundation.h>
#import <CoreFoundation/CoreFoundation.h>
#import <AppKit/Appkit.h>

int main(void) {
    NSPasteboard *pb = [NSPasteboard pasteboardWithName:@"alertBoard"];
    NSArray *clsss = @[[NSString class]];
    while(true) {
        if ([pb canReadObjectForClasses:clsss options:nil]) {
            NSArray *contents = [pb readObjectsForClasses:@[[NSString class]] options: nil];
            CFStringRef msg  = (__bridge CFStringRef) [contents firstObject];
            [pb clearContents];

            CFUserNotificationDisplayNotice(2, 3, NULL, NULL, NULL, CFSTR("Alert"), msg, NULL);
        }   
    }   
    return 0;
}

Я собираю программу примерно так g++ -framework Foundation -framework CoreFoundation -framework AppKit -fobjc-arc alertDaemon.m -o alertDaemon.Проблема возникает независимо от другого процесса, поэтому для наблюдения за созданием файла подкачки достаточно запустить программу в течение нескольких минут.

1 Ответ

0 голосов
/ 13 сентября 2018

Я предложил решение, использующее [NSPasteboard changeCount], чтобы проверить, был ли записан монтажный картон вместо [NSPasteboard canReadObjectForClasses:options:]. Теперь программа использует постоянный небольшой объем памяти вместо того, чтобы использовать оперативную память. Теперь мне просто нужно выяснить, как использовать меньше циклов ЦП, хотя лучшие решения, чем использование непрерывного опроса для проверки NSPasteboard , пугают .

#import <Foundation/Foundation.h>
#import <CoreFoundation/CoreFoundation.h>
#import <AppKit/Appkit.h>

int main(void) {
    NSPasteboard *pb = [NSPasteboard pasteboardWithName:@"alertBoard"];
    NSArray *clsss = @[[NSString class]];
    int chngCnt = [pb changeCount];
    while(true) {
        if (chngCnt != [pb changeCount]) {
            NSArray *contents = [pb readObjectsForClasses:@[[NSString class]] options: nil];
            CFStringRef msg  = (__bridge CFStringRef) [contents firstObject];
            chngCnt = [pb clearContents];

            CFUserNotificationDisplayNotice(2, 3, NULL, NULL, NULL, CFSTR("Alert"), msg, NULL);
        }   
    }   
    return 0;
}
...