Модераторы: Daevaorn
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Возвращение const char*, Корректный код или параноя? 
V
    Опции темы
SaDFromSpb
Дата 20.7.2006, 15:05 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 263
Регистрация: 5.4.2006
Где: Санкт-Петербург

Репутация: 3
Всего: 3



Совершенно типичная задача: метод некоторого объекта возвращает строку описания кода ошибки:
Код

const char* SomeObject :: strerror(int errcode) {
   ostringstream oss;  // чтобы не париться с sprintf()
   switch (errcode) {
   case SO_WARN_SAVE_GRID : oss<<"Can't save grid for "<<spnum<<" shotpoint";    break;
   ...
   }
   return oss.str().c_str();
}

Здесь происходит не очень хорошая вещь: во "вне" выкидывается ссылка на объект области видимости функции strerror(), который может кануть в небытие в скором времени. Ведь так? Или же в данном случае, если полученная строка используется сразу же (до последующих вызовов функций по выделению памяти), то это не критично?
Но если писать полностью корректный код, то надо поступать по-честному. Заменить, например, строку
ostringstream oss; на ostringstream& oss = *(new ostringstream); (тогда получим висящий объект в куче) или сделать oss членом класса SomeObject... Тогда ситуация разрешится как с методом c_str() у string, который дает const-ссылку на внутренний буфер.

А может const - массивы все-равно остаются в стеке даже после выхода из области видимости и можно не париться (э... хотя вряд ли =) )? 


--------------------
"За исключением части, касающейся потоков, библиотека Loki написана на стандартном языке С++. Увы, это означает, что многие современные компиляторы не смогут работать с ней в полном объеме." (А. Александреску. Modern C++ design. 2001)
PM   Вверх
Fazil6
Дата 20.7.2006, 15:20 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1653
Регистрация: 3.5.2006
Где: Минск

Репутация: 35
Всего: 60



Цитата

Ведь так?

да.
обычно так.
Код

char* SomeObject :: strerror(int errcode, char * buf, int size) {
   ostringstream oss;  // чтобы не париться с sprintf()
   switch (errcode) {
   case SO_WARN_SAVE_GRID : oss<<"Can't save grid for "<<spnum<<" shotpoint";    break;
   ...
   }
   strncpy(buf, oss.str().c_str(), size - 1);
   buf[size - 1] = '\0';
   return buf;
}
  

Это сообщение отредактировал(а) Fazil6 - 20.7.2006, 15:22
PM MAIL   Вверх
SaDFromSpb
Дата 20.7.2006, 15:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 263
Регистрация: 5.4.2006
Где: Санкт-Петербург

Репутация: 3
Всего: 3



Fazil6, нда это конечно самый надежный вариант, просто хотелось сохранить семантику стандартного strerror() из <cstddef>
Только тогда уже лучше вот так:
Код
char* SomeObject :: strerror(int errcode, char** buff) {
   ostringstream oss;  // чтобы не париться с sprintf()
   switch (errcode) {
   case SO_WARN_SAVE_GRID : oss<<"Can't save grid for "<<spnum<<" shotpoint";    break;
   ...
   }
   const char* errmess = oss.str().c_str();
   *buff = new char[strlen(errmess) + 1];
   strcpy(*buff, errmess);
   return *buff;
}


Добавлено @ 15:32 
Кстати, strncpy() и так в buf допишет '\0'   

Это сообщение отредактировал(а) SaDFromSpb - 20.7.2006, 15:45


--------------------
"За исключением части, касающейся потоков, библиотека Loki написана на стандартном языке С++. Увы, это означает, что многие современные компиляторы не смогут работать с ней в полном объеме." (А. Александреску. Modern C++ design. 2001)
PM   Вверх
Fazil6
Дата 20.7.2006, 15:46 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1653
Регистрация: 3.5.2006
Где: Минск

Репутация: 35
Всего: 60



Цитата

Только тогда уже лучше вот так:

хм. Чем же это лучше?
Код

*buff = new char[strlen(errmess) + 1];

кто удалять это будет?
Цитата

Кстати, strncpy() и так в buf допишет '\0'  

если строка источника больше заданной для копирования, то не добавит

Добавлено @ 15:54 
Цитата

хотелось сохранить семантику стандартного strerror()


можно иметь какие-то константы вне функции и возвращать их 
PM MAIL   Вверх
SaDFromSpb
Дата 20.7.2006, 15:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 263
Регистрация: 5.4.2006
Где: Санкт-Петербург

Репутация: 3
Всего: 3



Fazil6,
Лучше тем, что не нужно производить мучительных раздумий, какой же длинны строку передавать в эту функцию. Нет ограничений на длинну строки, и лишняя память не используется.
Цитата(Fazil6 @  20.7.2006,  15:46 Найти цитируемый пост)
кто удалять это будет?

Так программер и будет.
Цитата(Fazil6 @  20.7.2006,  15:46 Найти цитируемый пост)
если строка источника больше заданной для копирования, то не добавит

ну да, вернее, если третий параметр больше длины строки назначения, то не добавит.

Что-то мы уже здесь немного оффтопим.

Добавлено @ 16:00 
Цитата(Fazil6 @  20.7.2006,  15:46 Найти цитируемый пост)
можно иметь какие-то константы вне функции и возвращать их

Ты имеешь ввиду строковые константы? Так у нас же строки формируются внутри функции.  

Это сообщение отредактировал(а) SaDFromSpb - 20.7.2006, 16:21


--------------------
"За исключением части, касающейся потоков, библиотека Loki написана на стандартном языке С++. Увы, это означает, что многие современные компиляторы не смогут работать с ней в полном объеме." (А. Александреску. Modern C++ design. 2001)
PM   Вверх
SaDFromSpb
Дата 20.7.2006, 16:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 263
Регистрация: 5.4.2006
Где: Санкт-Петербург

Репутация: 3
Всего: 3



Ладно, закрываю эту глупую тему =) . 


--------------------
"За исключением части, касающейся потоков, библиотека Loki написана на стандартном языке С++. Увы, это означает, что многие современные компиляторы не смогут работать с ней в полном объеме." (А. Александреску. Modern C++ design. 2001)
PM   Вверх
UnrealMan
Дата 20.7.2006, 17:25 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 722
Регистрация: 30.3.2006

Репутация: 27
Всего: 32



Цитата(SaDFromSpb @  20.7.2006,  15:05 Найти цитируемый пост)
ostringstream oss;

Сделай этот объект статическим – тогда до следующего обращения к функции SomeObject::strerror твоя строка будет в целости и сохранности. Только не забудь обнулять потоковую строку перед тем как туда что-то записывать (желательно это делать сразу после объявления static ostringstream oss; ). 
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++:Общие вопросы"
Earnest Daevaorn

Добро пожаловать!

  • Черновик стандарта C++ (за октябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика(4.4мб).
  • Черновик стандарта C (за сентябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика (3.4мб).
  • Прежде чем задать вопрос, прочтите это и/или это!
  • Здесь хранится весь мировой запас ссылок на документы, связанные с C++ :)
  • Не брезгуйте пользоваться тегами [code=cpp][/code].
  • Пожалуйста, не просите написать за вас программы в этом разделе - для этого существует "Центр Помощи".
  • C++ FAQ

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Earnest Daevaorn

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0477 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.