Я тут рассматривал главу 14.2.1 "Производные исключение"
у Страустрапа и понял, что не понимаю одной базовой вещи.
Есть у нас, согласно книжке,
некий
class int_overflow{
const char *op;
public: int_overflow(cont char *p){op=p}
/*...*/
};
с которым мы поступаем вот так
int add()
{
/*...*/
if(/*...*/)
throw int_overflow("+");
/*...*/
}
Так вот, строка с плюсом отведена на стеке,
и когда мы попытаемся анализировать исключение,
мы обратимся к довольно странному куску стека,
который скорее свободен, чем занят.
Здравствуйте, ilejn, Вы писали:
I>Я тут рассматривал главу 14.2.1 "Производные исключение" I>у Страустрапа и понял, что не понимаю одной базовой вещи.
I>Есть у нас, согласно книжке, I>некий I>class int_overflow{ I>const char *op; I>public: int_overflow(cont char *p){op=p} I>/*...*/ I>}; I>с которым мы поступаем вот так I>int add() I>{ I> /*...*/
I> if(/*...*/) I> throw int_overflow("+");
I> /*...*/ I>}
I>Так вот, строка с плюсом отведена на стеке, I>и когда мы попытаемся анализировать исключение, I>мы обратимся к довольно странному куску стека, I>который скорее свободен, чем занят.
I>В каком месте своих рассуждений я ошибаюсь?
Это не цепэпэ, а простой си. Строка будет не на стеке, а в сегменте данных.
Здравствуйте, ilejn, Вы писали:
aik>>Это не цепэпэ, а простой си. Строка будет не на стеке, а в сегменте данных. I>Не совсем понял это утверждение. Объясните, пожалуйста. I>Ну хорошо, а если мы напишем I>if(/*...*/) I>{ I>std::string err("+"); I>throw int_overflow(err.c_str()); I>} I>то это что-то изменит?
Думаю, что изменит, но в данном контексте пофигу. Зависит от реализации string. Либо string будет держать в себе указатель на строку в DS (до первой попытки записи в строку), либо сразу откопирует куда то в свою память (которую выделит в динамическом хипе). В любом случае строка на стеке не окажется. Чтобы она была на стеке, ее надо либо явно там выделить конструкцией char s[32] = "+"; либо через strcpy((char*)_alloca(32), "+").
Здравствуйте, aik, Вы писали:
aik>Здравствуйте, ilejn, Вы писали:
aik>>>Это не цепэпэ, а простой си. Строка будет не на стеке, а в сегменте данных. I>>Не совсем понял это утверждение. Объясните, пожалуйста.
Уже понял
I>>Ну хорошо, а если мы напишем I>>if(/*...*/) I>>{ I>>std::string err("+"); I>>throw int_overflow(err.c_str()); I>>} I>>то это что-то изменит?
aik>Думаю, что изменит, но в данном контексте пофигу. Зависит от реализации string. Либо string будет держать в себе указатель на строку в DS (до первой попытки записи в строку), либо сразу откопирует куда то в свою память (которую выделит в динамическом хипе). В любом случае строка на стеке не окажется. Чтобы она была на стеке, ее надо либо явно там выделить конструкцией char s[32] = "+"; либо через strcpy((char*)_alloca(32), "+").
Согласен. Я привел неудачный пример, но к моменту анализа
исключения op все-таки имеет все шансы указывать на уже освобожденную память,
потому что err к этому моменту уже удалился.
Мне кажется, что иметь такие объекты-исключения как int_overflow
крайне нежелательно, потому что торчащий из них указатель (или, скажем, ссылка)
может указывать на что-нибудь, что освободилось при раскрутке стека.
Действительно ли это так?
Здравствуйте, aik, Вы писали:
aik>Это не цепэпэ, а простой си. Строка будет не на стеке, а в сегменте данных.
Простой С с исключениями, ага. Приехали, называется.
В том, что строка будет не на стеке, Вы правы. Но по другой причине. В соответствии с пунктом 2.13.4/1 стандарта С++, string literals имеют static storage duration. Так-что приведённый код безопасен, но на мой взгляд — сомнителен.
Здравствуйте, Николай Ганичев, Вы писали:
aik>>Это не цепэпэ, а простой си. Строка будет не на стеке, а в сегменте данных. НГ>Простой С с исключениями, ага. Приехали, называется.
имелось ввиду, что вопрос про размещение строк на стеке относится не к cpp, а к простому си.
Здравствуйте, aik, Вы писали:
aik>>>Это не цепэпэ, а простой си. Строка будет не на стеке, а в сегменте данных. НГ>>Простой С с исключениями, ага. Приехали, называется. aik>имелось ввиду, что вопрос про размещение строк на стеке относится не к cpp, а к простому си.
Размещение строковых литералов в С++ описывается стандартом С++. То, что оно совместимо с Си и в какой степени — вопрос десятый.
[]
> Думаю, что изменит, но в данном контексте пофигу. Зависит от реализации string. Либо string будет держать в себе указатель на строку в DS (до первой попытки записи в строку), либо сразу откопирует куда то в свою память (которую выделит в динамическом хипе). В любом случае строка на стеке не окажется. Чтобы она была на стеке, ее надо либо явно там выделить конструкцией char s[32] = "+"; либо через strcpy((char*)_alloca(32), "+").
STLPort и Dinkum применяют small string optimization — строки до определенного размера храняться в буфере в объекте строки, а не в динамической памяти.