Копирование Objective-C NSMutableString

Я плохо объяснил свой первоначальный вопрос, так что вот второй удар. С точки зрения сверху вниз, вот цель:

У меня есть класс карты, который использует DDXML для анализа и загрузки файла карты XML. В этом файле карты есть несколько строк для отображения персонажа игроку, которые я анализирую и сохраняю в классе карты (как NSMutableString*). Когда событие инициирует загрузку одного из этих сообщений игроку, игровой цикл захватывает эту NSMutableString*, копирует ее во временный объект посредника, который затем при обновлении передает ее, наконец, в свой объект рендеринга. Это кажется безумием, но в этом есть смысл, если вы видите полный набор кода (ха, надеюсь!).

Я испытываю то, что КАЖЕТСЯ как ситуация с перезаписью памяти ... когда я пытаюсь получить доступ к NSMutableString во втором или третьем проходе (либо к временному посреднику, либо к объекту рендеринга), координаты текстуры становятся глупыми. Кажется, что сами струны целы, но память рядом выглядит размытой. Я иногда получаю сбои (EXC_BAD_ADDR или подобные) в той же итерации игрового цикла, когда эти чтения выполняются прямо перед рендерингом.

Я думаю, что это почти наверняка связано с моим (все еще) плохим пониманием NSMutableStrings. Кстати, я использую изменяемую версию, так как мне нужно редактировать строки (например, добавлять символы \n) после их загрузки. Вот некоторые соответствующие фрагменты кода, которые могут помочь лучше объяснить, что я делаю:

У меня есть структура TextSnippet, используемая для рендеринга, которая выглядит примерно так (некоторые данные для краткости опущены):

struct TextSnippet
{
    NSMutableString* string;
}

Я читаю карту (DDXML) и сохраняю текстовые сообщения в объект карты с помощью: (message->text определяется как NSMutableString* text[MAX_TEXT_PER_MESSAGE];

message->text[i] = [NSMutableString stringWithCapacity:50];
        [message->text[i] setString:[[text attributeForName:@"text"] stringValue]];
        [message->text[i] retain];

Затем я делаю следующее (примечание: это может быть действительно глупо и неправильно, и я уверен, что у меня происходит утечка памяти, как будто это никого не касается, но я просто пробую быстро худшие идеи, и это последняя из худших):

Это средний уровень:

// Properly copy the NSMutableString into the local message
for (int i = 0; i < m_message->count; i++)
{
    m_message->text[i] = [message->text[i] mutableCopy];
    [message->text[i] retain];
}

Наконец, позже в цикле я на самом деле пишу в структуру TextSnippet (в данном случае m_msgText), чтобы текст можно было отобразить:

m_msgText->string = [m_message->text[m_currentText] mutableCopy];
[m_msgText->string retain];

Как я уже сказал, я знаю, что делать лишние копии довольно противно... Я изучаю другие, гораздо более обширные перезаписи, чтобы обойти это, но в промежутке... как вам СЛЕДУЕТ делать это, если вы нужно было так много передавать NSMutableString*? Я предполагаю, что проблема по-прежнему МОЖЕТ быть чем-то другим, но всякий раз, когда я изменяю данные NSMutableString * на жестко закодированные строковые константы @"" на уровне посредника, проблема с памятью отсутствует. Разве это не должно быть проблемой с тем, как я обрабатываю свои строки здесь?

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


person David    schedule 07.07.2011    source источник
comment
Где этот NSMutableArray, о котором вы упоминаете? И почему вы храните объекты в массиве в структуре, а не просто используете NSArray?   -  person Chuck    schedule 08.07.2011
comment
Какая память перезаписывается?   -  person Firoze Lafeer    schedule 08.07.2011
comment
Должны ли эти строки быть изменяемыми в первую очередь?   -  person Georg Fritzsche    schedule 08.07.2011
comment
Чак, хороший улов - комментарий Array был опечаткой. Я отредактировал исходный вопрос, чтобы отразить. Здесь только струны. Большая часть функционального кода выполнена на C++, чтобы быть независимой от платформы, поэтому я стараюсь максимально избегать классов Objective-C. Тем не менее, я должен использовать NSStrings (предпочтительнее Mutables, так как я делаю некоторые незначительные изменения здесь или там). Перезаписываемая память находится в нескольких местах, но в данном случае это координаты текстуры, которые хранятся в той же структуре, что и строка, которую мы копируем ДО (а не из).   -  person David    schedule 08.07.2011


Ответы (1)


Я не знаю, почему вы получаете эту ошибку (у меня ее никогда не было), но в вашем примере кода есть некоторые фрагменты, которые выглядят странно (может быть, это просто отсутствие у меня знаний C/C++ :-)

message->text[i++] = [[NSMutableString alloc] 
                        initWithString:[[text attributeForName:@"text"] stringValue]];

Я не могу найти ссылку на метод stringValue в SDK. Но помимо этого, почему бы просто не сохранить ссылку на создаваемую NSMutableString? Я также не уверен, что такое text, но предполагая, что `[text attributeForName:@"text"]' возвращает NSString, я не думаю, что вам все равно нужно получать stringValue.

m_msgText->string = [[NSMutableString alloc] 
                        initWithString:[m_message->text[m_currentText] mutableCopy]];

Я не уверен, почему вы делаете бит [m_message->text[m_currentText] mutableCopy]. Почему бы просто не сделать

 m_msgText->string = [[NSMutableString alloc] 
                        initWithString:[m_message->text[m_currentText]]];

потому что он создаст новую NSMutableString, скопировав текст из [m_message->text[m_currentText]].

Не стесняйтесь говорить мне, что я говорю чепуху, потому что вы, вероятно, знаете больше о смешивании C/C++ и Objective C, чем я :-)

person drekka    schedule 08.07.2011
comment
Вы можете сократить последний бит до m_msgText->string = [m_message->text[m_currentText] mutableCopy];. -stringValue, вероятно, вернет неизменяемую строку, поэтому здесь применимо то же самое. - person Georg Fritzsche; 08.07.2011
comment
Дерек и Георг, держу пари, вы оба правы... Я не знал о поведении там с копированием NSMutableString, так что, я думаю, это сработает. Позвольте мне еще немного покопаться, я опубликую, какие результаты у меня есть в ближайшее время. - person David; 08.07.2011
comment
Дерек и Георг, я переписал свой вопрос... Надеюсь, это лучше объясняет, чего я пытаюсь достичь. Я много возился с ним весь день, и мне все еще не везет. Любые мысли будут очень признательны! - person David; 09.07.2011
comment
Этот ответ хороший, поэтому я принимаю его. Как оказалось, я довольно хорошо справлялся со строками NSString, всего несколько незначительных проблем здесь и там, которые решает решение Дерека. Перезапись памяти была (барабанная дробь!) совершенно не связанной с этим проблемой, но очистка моей строковой памяти стоила потраченного времени. Еще раз спасибо! - person David; 12.07.2011