C ++ строки манипуляции - PullRequest
       29

C ++ строки манипуляции

6 голосов
/ 10 ноября 2008

Отсутствие у меня опыта работы с C ++, или, скорее, моего раннего изучения языков с сборкой мусора, в настоящий момент очень утомляет меня, и у меня возникают проблемы при работе со строками в C ++.

Чтобы было очень ясно, использование std :: string или equlivents не вариант - это полностью char *.

Итак: что мне нужно сделать, это очень просто и сводится к объединению строк. Во время выполнения у меня есть 2 класса.

Один класс содержит информацию «type» в форме базового имени файла.

в шапке:

char* mBaseName;

и позже, в .cpp загружается информация, переданная откуда-то еще.

mBaseName = attributes->BaseName;

2-й класс предоставляет информацию о версии в виде суффикса к базовому имени файла, это статический класс, который в настоящее время реализован так:

static const char* const suffixes[] = {"Version1", "Version", "Version3"}; //etc.

static char* GetSuffix()
{
    int i = 0;
    //perform checks on some data structures
    i = somevalue;
   return suffixes[i];
}

Затем во время выполнения базовый класс создает нужное имя файла:

void LoadStuff()
{
    char* suffix = GetSuffix();
    char* nameToUse = new char[50];
    sprintf(nameToUse, "%s%s",mBaseName,suffix);

    LoadAndSetupData(nameToUse);
}

И вы сразу видите проблему. nameToUse никогда не удаляется, утечка памяти.

Суффиксы представляют собой фиксированный список, но имена базовых файлов являются произвольными. Созданное имя должно сохраняться после окончания «LoadStuff ()», так как неясно, когда и как оно будет использовано впоследствии.

Возможно, я слишком беспокоюсь или слишком глуп, но код, аналогичный LoadStuff (), встречается и в других местах, поэтому его нужно решить. Это разочаровывает, так как я не знаю достаточно о том, как все работает, чтобы увидеть безопасное и «нехорошее» решение. В C # я бы просто написал:

LoadAndSetupData(mBaseName + GetSuffix());

и не нужно беспокоиться.

Любые комментарии, предложения или советы приветствуются.

Обновление

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

Я не контролирую этот код, поэтому не могу обновить его функцию.

Ответы [ 13 ]

0 голосов
/ 10 ноября 2008

Вам придется управлять временем жизни памяти, которую вы выделяете для nameToUse. Заключение в класс, такой как std :: string, делает вашу жизнь немного проще.

Я думаю, это незначительное возмущение, но, поскольку я не могу придумать лучшего решения вашей проблемы, я укажу еще одну потенциальную проблему. Вы должны быть очень осторожны, чтобы проверять размер буфера, в который вы пишете, при копировании или конкатенации строк. Такие функции, как strcat, strcpy и sprintf, могут легко перезаписывать конец своих целевых буферов, что приводит к ложным ошибкам во время выполнения и уязвимостям безопасности.

Извините, мой собственный опыт в основном на платформе Windows, где они представили "безопасные" версии этих функций, называемые strcat_s, strcpy_s и sprintf_s. То же самое касается всех их многих связанных функций.

0 голосов
/ 10 ноября 2008

Где именно nameToUse используется за пределами LoadStuff? Если кому-то это нужно после LoadStuff, оно должно передать его вместе с ответом за освобождение памяти

Если бы вы сделали это в c #, как вы предложили

LoadAndSetupData(mBaseName + GetSuffix()); 

тогда ничто не будет ссылаться на параметр LoadAndSetupData, поэтому вы можете смело изменить его на

char nameToUse[50];

как предложил Мартин.

0 голосов
/ 10 ноября 2008

Мне не совсем ясно, где определяется LoadAndSetupData, но похоже, что он хранит свою собственную копию строки. Итак, после вызова LoadAndSetupData вы должны удалить локально выделенную копию и позволить ей управлять своей собственной копией.

Или убедитесь, что LoadAndSetupData очищает выделенный символ [], который вы ему дали.

Я бы предпочел, чтобы другая функция оставила свою собственную копию и управляла ею, чтобы вы не выделяли объект для другого класса.

Редактировать: поскольку вы используете new с фиксированным размером [50], вы также можете сделать его локальным, как было предложено, и пусть LoadAndSetupData создаст свою собственную копию.

...