Сохраняет ли NSString stringWithCString: length: байтовый массив, который я передаю? - PullRequest
2 голосов
/ 02 июня 2009

Я работаю с AsyncSocket, где объект AsyncSocket вызывает метод делегата ниже всякий раз, когда он получает данные от удаленного конца:

- (void)onSocket:(AsyncSocket*)socket didReadData:(NSData*)data withTag:(long)tag;

Теперь в этом методе я передаю объект NSData в следующую команду, чтобы получить представление NSString полученных данных:

NSString *body = [NSString stringWithCString:[data bytes] length:[data length];

Сохраняет ли NSString stringWithCString: length: байтовый массив, который я передаю? Нужно ли сохранять данные NSData *? Нужно ли выпускать тело NSString * в конце?

Спасибо. Я хочу получить правильное управление памятью с точки зрения методов делегатов ...

Ответы [ 4 ]

2 голосов
/ 03 июня 2009

Сохраняет ли NSString stringWithCString: length: байтовый массив, который я передаю?

Невозможно сохранить байтовый массив. Только объекты могут быть сохранены.

Нужно ли сохранять данные NSData *?

Нет. Поскольку строка не может сохранить данные (о которых она не знает) или их содержимое, строка будет копировать байты. (Подумайте, что бы вы сделали, если бы реализовывали этот метод: вот и все.)

Давайте изменим регистры и посмотрим, что бы вы сделали, если бы передавали объект данных вместо байтов.

Если строка сохраняет данные, вам не нужно беспокоиться о том, что данные исчезнут из-под строки, потому что строка сохраняет их. Если он не сохраняет его, строка либо создала свою собственную копию, либо вообще не хранит ваши данные.

Так что удержание других объектов не имеет значения. Не беспокойся о них. Беспокойся только о том, кому что принадлежит, и сохраняй или не сохраняй соответственно.

Должен ли я выпускать тело NSString * в конце?

Ну, вы не сохранили его, не распределили и не скопировали. Следовательно, вы не являетесь его владельцем. Итак, нет.

Если вы хотите стать владельцем объекта, вы сохраните его или сделаете (а затем и будете владеть) своей собственной копией. Тогда вы бы выпустили его.

1 голос
/ 27 марта 2012

Простой ответ с доказательством. NSString stringWithCString: encoding: копирует байтовый буфер для создания строки. Буфер зависит от вас, чтобы поддерживать.

Доказательство:

Код:

    const char* hardString = "Hello, World";
    char *buffer = nil;

    buffer = calloc(13, 1);
    bzero(buffer, 13);

    memcpy(buffer, hardString, 12);

    NSString *aString = [NSString stringWithCString:buffer encoding:NSUTF8StringEncoding];        
    NSLog(@"aString: %@  \t filled buffer:(%p) [%s]", aString, (void*)buffer, buffer);

    bzero(buffer, 13); 
    NSLog(@"aString: %@  \t zeroed buffer:(%p) [%s]", aString, (void*)buffer, buffer);

    free(buffer);
    NSLog(@"aString: %@  \t free'd buffer:(%p)", aString, (void*)buffer);

    buffer = nil;        
    NSLog(@"aString: %@  \t nulled buffer:(%p)", aString, (void*)buffer);

Результат:

aString: Hello, World    filled buffer:(0x10010a790) [Hello, World]
aString: Hello, World    zeroed buffer:(0x10010a790) []
aString: Hello, World    free'd buffer:(0x10010a790)
aString: Hello, World    nulled buffer:(0x0)
0 голосов
/ 02 июня 2009

Фолкер верен; Вы должны использовать stringWithCString:encoding: вместо.

Сохранение / освобождение требуется только для объектов; поскольку вы передаете C-строку (которая не является объектом, в отличие от NSString), вам нечего сохранять или освобождать.

Поскольку вы используете вспомогательный конструктор , NSString имеет счет сохранения 1, но добавляется в пул автоматического выпуска, поэтому через некоторое время после выхода из блока кода он будет освобожден. Вам не нужно явно использовать методы alloc и init, чтобы иметь возможность его сохранить. Я имею в виду, что он создается с счетом сохранения 1 (но будет автоматически освобожден). Если вы вызовете функцию сохранения на нем, это увеличит счет до 2, но через некоторое время он будет автоматически повторно использован, и счет сохранения уменьшится. до 1.

Если вы не вызываете init, retain, copy или mutableCopy для объекта, вы можете предположить, что он будет автоматически освобожден, и вам не нужно явно освобождать что-либо. Но если вы хотите удерживать объект вне блока кода, вам нужно вызвать retain, а затем отпустить его через некоторое время (обычно в методе dealloc класса, в котором был создан объект).

0 голосов
/ 02 июня 2009

Вам не нужно сохранять массив NSData, поскольку его содержимое будет преобразовано / скопировано в новый объект NSString.

Возвращенный объект NSString имеет счет сохранения 1, но он был добавлен в пул автоматического выпуска.
Это означает, что он будет автоматически освобожден после уничтожения пула автоматического выпуска. Если вы используете пул автоматического выпуска по умолчанию, созданный AppKit, это произойдет в конце текущей обработки цикла событий. Так что, если вы используете этот строковый объект только в этом методе "onsocket: ...", все в порядке.

Если вы хотите сохранить объект NSString после выхода из метода, вы должны сохранить его или создать его экземпляр, выделив и инициализировав его следующим образом:
[[NSString alloc] initWithBytes: [...] длина: [...] кодировка: [...]]
Этот объект NSString также будет иметь счет сохранения 1, но вы должны явно освободить его, когда он вам больше не нужен.

Btw. [NSString stringWithCString: length:] устарела начиная с OSX 10.4

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...