The OpenNET Project / Index page

[ новости /+++ | форум | wiki | теги | ]

форумы  помощь  поиск  регистрация  майллист  ВХОД  слежка  RSS
"Класс OSTRSTREAM странное поведение"
Вариант для распечатки Архивированная нить - только для чтения! 
Пред. тема | След. тема 
Форумы Программирование под UNIX (Public)
Изначальное сообщение [Проследить за развитием треда]

"Класс OSTRSTREAM странное поведение"
Сообщение от FrOdO emailИскать по авторуВ закладки on 10-Мрт-04, 13:31  (MSK)
Hi ALL.

Столкнулся с классом ostrstream, позволяющим писать в буфер.
В цикле у меня вызывется функция, в которой формируется буфер, с помощью данного класса. Причем буфер бывает разной длины, в зависимости от данных. У меня появляются концы старых, более длинных, строк. Хотя при выходе из функции объект класса должен уничтожаться, зн. и внутренний буфер со старыми данными, тоже должен исчезнуть.
Я вывожу сформированные данные на stdout, получив до этого замороженный буфер посредством метода str() (потом я удаляю этот буфер оператором delete[]). Свои изыскания я основывал на книге Тереса Чана "Системное программирование на С++ для Unix".
Если предположить, что внутри класса используется статический буфер, не уничтожающийся при выходе из функции, то все равно он должен выставлять корректный размер данных при входе в эту функцию снова.

Может кто сталкивался с подобным явлением. У меня стоит Fedore Core 1, gcc 3.3.3.

Благодарю за внимание.

  Рекомендовать в FAQ | Cообщить модератору | Наверх

 Оглавление

Индекс форумов | Темы | Пред. тема | След. тема
Сообщения по теме

1. "Класс OSTRSTREAM странное поведение"
Сообщение от solov Искать по авторуВ закладки on 10-Мрт-04, 17:16  (MSK)
Ты имееш ввиду класс ostringstream? Покажи код...
  Рекомендовать в FAQ | Cообщить модератору | Наверх

2. "Класс OSTRSTREAM странное поведение"
Сообщение от FrOdO emailИскать по авторуВ закладки on 10-Мрт-04, 17:49  (MSK)
>Ты имееш ввиду класс ostringstream? Покажи код...

Пример:

// cut here ------------

#include <strstream>
#include <iostream>
#include <string>
using namespace std;

string str[4] = {"str1", "str1str2", "str1str2str3", "sr"};
int i = 0;

char *Func()
{
  ostrstream s_out;
  s_out << "String " << str[i] << endl;
  return s_out.str();
}

int main()
{
  for(; i < 4; i++)
  {
    char *s = Func();
    cerr << s;
    delete[] s;
  }

  cerr << endl;
  return 0;
}

// cut here ------------

при работе выдает следующий результат:

String str1
String str1str2
String str1str2str3
String sr
1str2s

последней строки быть не должно !!!

  Рекомендовать в FAQ | Cообщить модератору | Наверх

3. "Класс OSTRSTREAM странное поведение"
Сообщение от solov Искать по авторуВ закладки on 10-Мрт-04, 19:33  (MSK)
#include <sstream>
#include <iostream>
#include <string>


std::string str[4] = {"str1", "str1str2", "str1str2str3", "sr"};
int i = 0;


char* Func()
{
   std::ostringstream s_out;
   s_out << "String " << str[i] << std::endl;
   return (s_out.str()).c_str();   // !!!!!
}

int main()
{
   for(; i < 4; i++) {

   char *s = Func();
   std::cout << s;
   //delete [] s;
   }

   std::cout << std::endl;

   return 0;
}

  Рекомендовать в FAQ | Cообщить модератору | Наверх

4. "Класс OSTRSTREAM странное поведение"
Сообщение от asso Искать по авторуВ закладки on 11-Мрт-04, 04:42  (MSK)
>char* Func()
>{
>   std::ostringstream s_out;
>   s_out << "String " << str[i] << std::endl;
>   return (s_out.str()).c_str();   // !!!!!
>}

Вот это то же не должно работать.  s_out размещается в стеке и уничтожается при выходе из функции, а вместе с ней и строка которая была записана.

Надо либо вообще все переделать либо сделать что-то вроде

#include <sstream>
#include <iostream>
#include <string>


std::string str[4] = {"str1", "str1str2", "str1str2str3", "sr"};
int i = 0;


std::string Func()
{
   std::ostringstream s_out;
   s_out << "String " << str[i] << std::endl;
   return s_out.str();
}

int main()
{
   for(; i < 4; i++) {

   std::string s(Func());
   std::cout << s;
   //delete [] s;
   }

   std::cout << std::endl;

   return 0;
}

  Рекомендовать в FAQ | Cообщить модератору | Наверх

5. "Класс OSTRSTREAM странное поведение"
Сообщение от solov Искать по авторуВ закладки on 11-Мрт-04, 13:51  (MSK)
>Вот это то же не должно работать.  s_out размещается в стеке
>и уничтожается при выходе из функции, а вместе с ней и
>строка которая была записана.


Память под char* выделяется статически !!!, поэтому после вызова функции не освобождается

  Рекомендовать в FAQ | Cообщить модератору | Наверх

7. "Класс OSTRSTREAM странное поведение"
Сообщение от asso Искать по авторуВ закладки on 12-Мрт-04, 05:59  (MSK)
>Память под char* выделяется статически !!!, поэтому после вызова функции не освобождается

Не понял что ты этим хотел сказать.

Посмотри исходный текст std::strsream:

typedef basic_string<char_type, _Traits, _Alloc> __string_type;

// Get and set:
/**
*  @brief  Copying out the string buffer.
*  @return  A copy of one of the underlying sequences.
*
*  "If the buffer is only created in input mode, the underlying
*  character sequence is equal to the input sequence; otherwise, it
*  is equal to the output sequence." [27.7.1.2]/1
*/
__string_type
str() const
{
if (_M_mode & ios_base::out)
  {
    // This is the deal: _M_string.size() is a value that
    // represents the size of the initial string that makes
    // _M_string, and may not be the correct size of the
    // current stringbuf internal buffer.
    __size_type __len = _M_string.size();
    if (_M_out_end > _M_out_beg)
      __len = max(__size_type(_M_out_end - _M_out_beg), __len);
    return __string_type(_M_out_beg, _M_out_beg + __len);
  }
else
  return _M_string;
}

Другими словами создается новый экземпляр __string_type.  В случае std::ostrstream тип __string_type эквивалентен std::string.  Метод c_str() у std::string не выделяет память а возвращает указатель на свой внутренний буфер (поэтому его не надо освобождать).

Другими словами, код

const char *foo() {
  std::string s("la-la-la");
  return s.c_str();
}

будет возвращать неправильный указатель потому что строка s будет уничтожена при возврате из функции.  Код

   return (s_out.str()).c_str();

не будет работать правильно по той же причине.  Более того, специально для таких случаев метод c_str() возвращает не просто char*, а const char*, поэтому этот код даже не откомпилируется.

На практике можно явно преобразовать const char* в char* и это, возможно, даже будет иногда работать в зависимости от состояния кучи и стека.  Но состояние кучи и стека не всегда будет оставаться благоприятным поэтому ошибка рано или поздно даст о себе знать.

  Рекомендовать в FAQ | Cообщить модератору | Наверх

8. "Класс OSTRSTREAM странное поведение"
Сообщение от solov Искать по авторуВ закладки on 12-Мрт-04, 13:33  (MSK)
>Вот это то же не должно работать.  s_out размещается в стеке и >уничтожается при выходе из функции, а вместе с ней и строка которая была >записана.

Почти все правильно кроме одного что мы получаем при помощи c_str() следующий тип char* и этот тип всегда будет static поэтому и остается в стеке. Но ты прав с константой. Да c_str() возращает тип const char*  поэтому пишим
const_cast<char*>((s_out.str()).c_str())
Но это уже извращение да и функция char* Func() не нужна.

  Рекомендовать в FAQ | Cообщить модератору | Наверх

9. "Класс OSTRSTREAM странное поведение"
Сообщение от asso Искать по авторуВ закладки on 13-Мрт-04, 08:35  (MSK)
>Почти все правильно кроме одного что мы получаем при помощи c_str() следующий
>тип char* и этот тип всегда будет static поэтому и остается
>в стеке.

Да, на счет этого я был не прав.  Действительно получается static, поэтому никаких проблем с памятью не будет.

  Рекомендовать в FAQ | Cообщить модератору | Наверх

10. "Класс OSTRSTREAM странное поведение"
Сообщение от sas emailИскать по авторуВ закладки on 13-Мрт-04, 12:58  (MSK)
>>Вот это то же не должно работать.  s_out размещается в стеке и >уничтожается при выходе из функции, а вместе с ней и строка которая была >записана.
>
>Почти все правильно кроме одного что мы получаем при помощи c_str() следующий
>тип char* и этот тип всегда будет static поэтому и остается
>в стеке. Но ты прав с константой. Да c_str() возращает тип
>const char*  поэтому пишим
>const_cast<char*>((s_out.str()).c_str())
>Но это уже извращение да и функция char* Func() не нужна.

Доброго времени суток,

Простите, но откуда здесь static?

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

Стандарт  четко говорит, что возвращаемый c_str const указатель верен ТОЛЬКО пока строка (объект класса) существует и пока не была вызвана хотя бы одна не константная функция.

Удачи
--- sas

  Рекомендовать в FAQ | Cообщить модератору | Наверх

11. "Класс OSTRSTREAM странное поведение"
Сообщение от solov Искать по авторуВ закладки on 13-Мрт-04, 13:23  (MSK)
>Доброго времени суток,
>
>Простите, но откуда здесь static?

Стандарт четко говорит что char* всегда будет static char*

>
>Ваше мнение к сожалению ложно. Как сказал предидущий оратор - это работать
>если и будет, то только случайно при определенных условиях.
>
>Стандарт  четко говорит, что возвращаемый c_str const указатель верен ТОЛЬКО пока
>строка (объект класса) существует и пока не была вызвана хотя бы
>одна не константная функция.
>
>Удачи
>--- sas


  Рекомендовать в FAQ | Cообщить модератору | Наверх

12. "Класс OSTRSTREAM странное поведение"
Сообщение от sas emailИскать по авторуВ закладки on 13-Мрт-04, 13:35  (MSK)
>>Доброго времени суток,
>>
>>Простите, но откуда здесь static?
>
>Стандарт четко говорит что char* всегда будет static char*
>
>>
>>Ваше мнение к сожалению ложно. Как сказал предидущий оратор - это работать
>>если и будет, то только случайно при определенных условиях.
>>
>>Стандарт  четко говорит, что возвращаемый c_str const указатель верен ТОЛЬКО пока
>>строка (объект класса) существует и пока не была вызвана хотя бы
>>одна не константная функция.
>>
>>Удачи
>>--- sas

Я прошу прощения и где он это говорит? Ссылочка или хотя-бы пункт помогли бы отцу русской демократии :)

Удачи
--- sas

  Рекомендовать в FAQ | Cообщить модератору | Наверх

13. "Класс OSTRSTREAM странное поведение"
Сообщение от solov Искать по авторуВ закладки on 13-Мрт-04, 16:24  (MSK)
Строковым литералом называется последовательность символов заключенная в двойные кавычки:
“Это строка”
.....

Память под строкавые литералы выделяется статически поэтому их свободно можно возращать в качестве значения функции. Например:
const char* error_message(int i)
{
// ...
retrun “Выход за пределы диапазона”;
}
Память содержащая строку “Выход за пределы диапазона” не будет освобождена после вызова error_message().

Стр. 130 Глава 5.2.2.  “Язык программирования С++ специальное издание” Bjarne Stroustrup


  Рекомендовать в FAQ | Cообщить модератору | Наверх

14. "Класс OSTRSTREAM странное поведение"
Сообщение от sas emailИскать по авторуВ закладки on 13-Мрт-04, 17:23  (MSK)
>Строковым литералом называется последовательность символов заключенная в двойные кавычки:
>?Это строка?
>.....
>
>Память под строкавые литералы выделяется статически поэтому их свободно можно возращать в
>качестве значения функции. Например:
> const char* error_message(int i)
> {
>  // ...
>  retrun ?Выход за пределы диапазона?;
> }
>Память содержащая строку ?Выход за пределы диапазона? не будет освобождена после вызова
>error_message().
>
>Стр. 130 Глава 5.2.2.  ?Язык программирования С++ специальное издание? Bjarne Stroustrup
>

Прекрасно!!! :)) Возразить НЕЧЕГО... И где же здесь аналогия с нашим случаем?

Удачи
--- sas

  Рекомендовать в FAQ | Cообщить модератору | Наверх

15. "Класс OSTRSTREAM странное поведение"
Сообщение от ed Искать по авторуВ закладки on 13-Мрт-04, 17:24  (MSK)
>Строковым литералом называется последовательность символов заключенная в двойные кавычки:
>?Это строка?
>.....
>

Ну и что ? Да "String " и "str1str2str3" - static const char*, но неужели ты думаеш что (std::string("String ") + "str1str2str3") все еще static !?

  Рекомендовать в FAQ | Cообщить модератору | Наверх

16. "Класс OSTRSTREAM странное поведение"
Сообщение от sas emailИскать по авторуВ закладки on 13-Мрт-04, 17:27  (MSK)
>Строковым литералом называется последовательность символов заключенная в двойные кавычки:
>?Это строка?
>.....
>
>Память под строкавые литералы выделяется статически поэтому их свободно можно возращать в
>качестве значения функции. Например:
> const char* error_message(int i)
> {
>  // ...
>  retrun ?Выход за пределы диапазона?;
> }
>Память содержащая строку ?Выход за пределы диапазона? не будет освобождена после вызова
>error_message().
>
>Стр. 130 Глава 5.2.2.  ?Язык программирования С++ специальное издание? Bjarne Stroustrup
>

Уважаемый  solov!

А вдогонку вопрос: А можно менять постоянные статические строки?

Удачи
--- sas

  Рекомендовать в FAQ | Cообщить модератору | Наверх

17. "Класс OSTRSTREAM странное поведение"
Сообщение от sas emailИскать по авторуВ закладки on 13-Мрт-04, 17:51  (MSK)
>Строковым литералом называется последовательность символов заключенная в двойные кавычки:
>?Это строка?
>.....
>
>Память под строкавые литералы выделяется статически поэтому их свободно можно возращать в
>качестве значения функции. Например:
> const char* error_message(int i)
> {
>  // ...
>  retrun ?Выход за пределы диапазона?;
> }
>Память содержащая строку ?Выход за пределы диапазона? не будет освобождена после вызова
>error_message().
>
>Стр. 130 Глава 5.2.2.  ?Язык программирования С++ специальное издание? Bjarne Stroustrup
>

Уважаемый Mr Solov,

И еще один вопрос: Меняется ли содержимое объекта (i|o)stringstream  в процессе его жизнидеятельности?

Удачи
--- sas

  Рекомендовать в FAQ | Cообщить модератору | Наверх

6. "Класс OSTRSTREAM странное поведение"
Сообщение от FrOdO emailИскать по авторуВ закладки on 11-Мрт-04, 14:46  (MSK)
Всем спасибо, разобрался.
Плохо, когда нет хорошего хелпа с возможностью поиска.
  Рекомендовать в FAQ | Cообщить модератору | Наверх

18. "Класс OSTRSTREAM странное поведение"
Сообщение от sas emailИскать по авторуВ закладки on 13-Мрт-04, 18:22  (MSK)
>Hi ALL.
>
>Столкнулся с классом ostrstream, позволяющим писать в буфер.
>В цикле у меня вызывется функция, в которой формируется буфер, с помощью
>данного класса. Причем буфер бывает разной длины, в зависимости от данных.
>У меня появляются концы старых, более длинных, строк. Хотя при выходе
>из функции объект класса должен уничтожаться, зн. и внутренний буфер со
>старыми данными, тоже должен исчезнуть.
>Я вывожу сформированные данные на stdout, получив до этого замороженный буфер посредством
>метода str() (потом я удаляю этот буфер оператором delete[]). Свои изыскания
>я основывал на книге Тереса Чана "Системное программирование на С++ для
>Unix".
>Если предположить, что внутри класса используется статический буфер, не уничтожающийся при выходе
>из функции, то все равно он должен выставлять корректный размер данных
>при входе в эту функцию снова.
>
>Может кто сталкивался с подобным явлением. У меня стоит Fedore Core 1,
>gcc 3.3.3.
>
>Благодарю за внимание.

Для полноты картины, хотя и несколько поздновато:

Объекты классов (i|o|)strstream являются устаревшими. По стандарту пользователь обязан сам "закрывать" строку  добавляя ends, если ему это нужно.
...
 ostrstream s_out;
 s_out << "String " << str[i] << "\n" << ends;
 return s_out.str();
...

Массив который Вы возвращаете выделен из динамической памяти

Как уже было указано  лучше использовать stringstream.

Удачи
--- sas

  Рекомендовать в FAQ | Cообщить модератору | Наверх

19. "Класс OSTRSTREAM странное поведение"
Сообщение от sas emailИскать по авторуВ закладки on 13-Мрт-04, 18:36  (MSK)
Гораздо более полное и понятное объяснение чем мое :)

http://docs.freebsd.org/info/iostream/iostream.info.Strings.html

Удачи
--- sas

>>Hi ALL.
>>
>>Столкнулся с классом ostrstream, позволяющим писать в буфер.
>>В цикле у меня вызывется функция, в которой формируется буфер, с помощью
>>данного класса. Причем буфер бывает разной длины, в зависимости от данных.
>>У меня появляются концы старых, более длинных, строк. Хотя при выходе
>>из функции объект класса должен уничтожаться, зн. и внутренний буфер со
>>старыми данными, тоже должен исчезнуть.
>>Я вывожу сформированные данные на stdout, получив до этого замороженный буфер посредством
>>метода str() (потом я удаляю этот буфер оператором delete[]). Свои изыскания
>>я основывал на книге Тереса Чана "Системное программирование на С++ для
>>Unix".
>>Если предположить, что внутри класса используется статический буфер, не уничтожающийся при выходе
>>из функции, то все равно он должен выставлять корректный размер данных
>>при входе в эту функцию снова.
>>
>>Может кто сталкивался с подобным явлением. У меня стоит Fedore Core 1,
>>gcc 3.3.3.
>>
>>Благодарю за внимание.
>
>Для полноты картины, хотя и несколько поздновато:
>
>Объекты классов (i|o|)strstream являются устаревшими. По стандарту пользователь обязан сам "закрывать" строку
> добавляя ends, если ему это нужно.
>...
> ostrstream s_out;
> s_out << "String " << str[i] << "\n" << ends;
> return s_out.str();
>...
>
>Массив который Вы возвращаете выделен из динамической памяти
>
>Как уже было указано  лучше использовать stringstream.
>
>Удачи
>--- sas

  Рекомендовать в FAQ | Cообщить модератору | Наверх


Удалить

Индекс форумов | Темы | Пред. тема | След. тема
Пожалуйста, прежде чем написать сообщение, ознакомьтесь с данными рекомендациями.




Партнёры:
PostgresPro
Inferno Solutions
Hosting by Hoster.ru
Хостинг:

Закладки на сайте
Проследить за страницей
Created 1996-2024 by Maxim Chirkov
Добавить, Поддержать, Вебмастеру