Вход на сайт
C++ Frage zur Speicherverwaltung
634
NEW 17.12.08 14:30
Moin allerseits,
ich habe folgende Frage zur folgender Situation:
void Options::setActionField(std::string addr)
{
std::string *str = new std::string(addr);
m_action_field = (axis2_char_t *)str->c_str();
}
Der Zeiger *str ist lokal und wird gelöscht sobald die Funktion zu Ende ausgeführt wurde.
Besteht die Möglichkeit die Freigabe über m_action_field durhchzuführen?
etwa
free(m_action_field);
Danke für die Tipps
ich habe folgende Frage zur folgender Situation:
void Options::setActionField(std::string addr)
{
std::string *str = new std::string(addr);
m_action_field = (axis2_char_t *)str->c_str();
}
Der Zeiger *str ist lokal und wird gelöscht sobald die Funktion zu Ende ausgeführt wurde.
Besteht die Möglichkeit die Freigabe über m_action_field durhchzuführen?
etwa
free(m_action_field);
Danke für die Tipps
NEW 17.12.08 14:58
С чего это ты взял? :)
Вообще, как я погляжу, легких путей ты не ищешь :)
Такой странный вопрос: почему m_action_field ты объявил как LPCTSTR, а не как std::string?
в ответ evgher 17.12.08 14:30
В ответ на:
Der Zeiger *str ist lokal und wird gelöscht sobald die Funktion zu Ende ausgeführt wurde.
Der Zeiger *str ist lokal und wird gelöscht sobald die Funktion zu Ende ausgeführt wurde.
С чего это ты взял? :)
Вообще, как я погляжу, легких путей ты не ищешь :)
Такой странный вопрос: почему m_action_field ты объявил как LPCTSTR, а не как std::string?
NEW 17.12.08 15:08
Лёгкий путь я уже нашёл :)
Меня просто именно эта ситуация волновала.
Как ты уже сам намикнул
Мембер-переменная типа Стринг
ну а дальше всё просто:
при выдачи использую Геттер-Метод, который
сразу всё за меня делает
const axis2_char_t *Options::getActionField()
{
return (axis2_char_t *)ms_address_field->c_str();
}
In Antwort auf:
Вообще, как я погляжу, легких путей ты не ищешь :)
Вообще, как я погляжу, легких путей ты не ищешь :)
Лёгкий путь я уже нашёл :)
Меня просто именно эта ситуация волновала.
In Antwort auf:
Такой странный вопрос: почему m_action_field ты объявил как LPCTSTR, а не как std::string?
Такой странный вопрос: почему m_action_field ты объявил как LPCTSTR, а не как std::string?
Как ты уже сам намикнул
Мембер-переменная типа Стринг
ну а дальше всё просто:
при выдачи использую Геттер-Метод, который
сразу всё за меня делает
const axis2_char_t *Options::getActionField()
{
return (axis2_char_t *)ms_address_field->c_str();
}
NEW 17.12.08 16:55
Это локальная переменная str будет при выходе из функции уничтожена, а вот резервированный на куче std::string будет болтаться в памяти до конца жизни программы. Утечка памяти налицо.
Законно освободить память по m_action_field ты не можешь. У нас вообще нет гарантий, что str->c_str() показывает на отдельно резервированный кусок памяти. Это может быть просто пуффер внутри std::string (так называемая small string optimization). Так что ты либо будешь пытаться освободить невелидный кусок кучи, либо (если бы у нас все же была возможность освободить память занимаемую str) ты получишь двойную попытку освобождения одного и того же участка кучи.
Для дупликации сишных стрингов используй функцию strdup. Но ещё лучше использовать поля типа std::string. Если же ты используешь поля типа char*, то тебе надо так же правильно имплементировать деструктор, копирующий конструктор и оператор присваивания. Я сомневаюсь, что твоя квалификация позволит тебе это сделать. Поэтому используй std::string, пока не будешь знать язык настолько хорошо, что будешь чётко понимать, когда от него можно отказаться.
Кроме того, не передавай std::string по значению. Это вызывает ненужное копирование параметра. Правильно было бы так: void Options::setActionField(std::string const& addr);
в ответ evgher 17.12.08 14:30
В ответ на:
Der Zeiger *str ist lokal und wird gelöscht sobald die Funktion zu Ende ausgeführt wurde.
Besteht die Möglichkeit die Freigabe über m_action_field durhchzuführen?
Der Zeiger *str ist lokal und wird gelöscht sobald die Funktion zu Ende ausgeführt wurde.
Besteht die Möglichkeit die Freigabe über m_action_field durhchzuführen?
Это локальная переменная str будет при выходе из функции уничтожена, а вот резервированный на куче std::string будет болтаться в памяти до конца жизни программы. Утечка памяти налицо.
Законно освободить память по m_action_field ты не можешь. У нас вообще нет гарантий, что str->c_str() показывает на отдельно резервированный кусок памяти. Это может быть просто пуффер внутри std::string (так называемая small string optimization). Так что ты либо будешь пытаться освободить невелидный кусок кучи, либо (если бы у нас все же была возможность освободить память занимаемую str) ты получишь двойную попытку освобождения одного и того же участка кучи.
Для дупликации сишных стрингов используй функцию strdup. Но ещё лучше использовать поля типа std::string. Если же ты используешь поля типа char*, то тебе надо так же правильно имплементировать деструктор, копирующий конструктор и оператор присваивания. Я сомневаюсь, что твоя квалификация позволит тебе это сделать. Поэтому используй std::string, пока не будешь знать язык настолько хорошо, что будешь чётко понимать, когда от него можно отказаться.
Кроме того, не передавай std::string по значению. Это вызывает ненужное копирование параметра. Правильно было бы так: void Options::setActionField(std::string const& addr);
17.12.08 17:04
А вот такого лучше не делать. Если getter отдаёт сишный стринг, то это вызывает неопределённость в вопросе владения оным. Клиент может засомневаться: надо ли мне его уничтожать, или не надо? В итоге кто-нибудь, когда-нибудь его освободит, и вы получите красивенький такой баг. Лучше было бы отдать константную ссылку: std::string const& Options::getActionField();
в ответ evgher 17.12.08 15:08
В ответ на:
const axis2_char_t *Options::getActionField()
{
return (axis2_char_t *)ms_address_field->c_str();
}
А вот такого лучше не делать. Если getter отдаёт сишный стринг, то это вызывает неопределённость в вопросе владения оным. Клиент может засомневаться: надо ли мне его уничтожать, или не надо? В итоге кто-нибудь, когда-нибудь его освободит, и вы получите красивенький такой баг. Лучше было бы отдать константную ссылку: std::string const& Options::getActionField();
NEW 17.12.08 19:14
Остаётся только добавить , что приведения типов в стиле "С" не кошерны , воспользуйся static_cast<> .
Но в этом случае я бы не рекомендовал возвращать указатель , хоть на константное что-то .
axis2_char_t Options::getActionField()
{
return axis2_char_t (ms_address_field);
}
Конечно должен быть констр . axis2_char_t(const std::string&)
В ответ на:
const axis2_char_t *Options::getActionField()
{
return (axis2_char_t *)ms_address_field->c_str();
}
const axis2_char_t *Options::getActionField()
{
return (axis2_char_t *)ms_address_field->c_str();
}
Остаётся только добавить , что приведения типов в стиле "С" не кошерны , воспользуйся static_cast<> .
Но в этом случае я бы не рекомендовал возвращать указатель , хоть на константное что-то .
axis2_char_t Options::getActionField()
{
return axis2_char_t (ms_address_field);
}
Конечно должен быть констр . axis2_char_t(const std::string&)
NEW 18.12.08 16:26
Я думаю, что здесь вы не совсем правы.
ms_address_field является мембер-переменной - указателем.
Уничтожение оной будет предпринято только при вызове деструктора - до этого ничего
и не должно освобождаться. Константная ссылка имеет смысл если речь шла о
ссылке, которую - как вы уже правильно приметили - клиент в контексте программы мог бы (он не может (из-за приват)) внезапно освободить.
In Antwort auf:
А вот такого лучше не делать. Если getter отдаёт сишный стринг, то это вызывает неопределённость в вопросе владения оным. Клиент может засомневаться: надо ли мне его уничтожать, или не надо? В итоге кто-нибудь, когда-нибудь его освободит, и вы получите красивенький такой баг. Лучше было бы отдать константную ссылку: std::string const& Options::getActionField();
А вот такого лучше не делать. Если getter отдаёт сишный стринг, то это вызывает неопределённость в вопросе владения оным. Клиент может засомневаться: надо ли мне его уничтожать, или не надо? В итоге кто-нибудь, когда-нибудь его освободит, и вы получите красивенький такой баг. Лучше было бы отдать константную ссылку: std::string const& Options::getActionField();
Я думаю, что здесь вы не совсем правы.
ms_address_field является мембер-переменной - указателем.
Уничтожение оной будет предпринято только при вызове деструктора - до этого ничего
и не должно освобождаться. Константная ссылка имеет смысл если речь шла о
ссылке, которую - как вы уже правильно приметили - клиент в контексте программы мог бы (он не может (из-за приват)) внезапно освободить.
NEW 18.12.08 16:38
Квалификация у меня хватает
Последний год програмировал в Яве и фортране.
Теперь приходиться перестраиваться. В СИ програмировал тоже не мало, а
в СИ++ навыков ещё не очень.
Да и код генерируется автоматически - интерфейсы менять нет смысла.
Какие сигнатуры генерируются - такие и использую, чтобы добавить
нужной функциональности.
Иначи всё сложнее будет.
в ответ femidav 17.12.08 16:55
In Antwort auf:
Я сомневаюсь, что твоя квалификация позволит тебе это сделать.
Я сомневаюсь, что твоя квалификация позволит тебе это сделать.
Квалификация у меня хватает

Последний год програмировал в Яве и фортране.
Теперь приходиться перестраиваться. В СИ програмировал тоже не мало, а
в СИ++ навыков ещё не очень.
Да и код генерируется автоматически - интерфейсы менять нет смысла.
Какие сигнатуры генерируются - такие и использую, чтобы добавить
нужной функциональности.
Иначи всё сложнее будет.
NEW 18.12.08 17:02
в ответ evgher 18.12.08 16:38
В плюсах своя специфика, и, исходя из представленного кода, я не вижу её понимания.
Какой код генерируется автоматически? Можно посмотреть на декларацию класса и реализацию перечисленных мною функций?
Разумееется я прав. Во-первых, почему вообще ms_address_field хранится в классе как указатель? Почему не по значению? Во-вторых, функция возвращает указатель на внутренности поля. Это плохо. Ещё того хуже, что эти внутренности возвращаются в виду указателя. Почему это плохо? Потому имея функцию вида const axis2_char_t *Options::getActionField(), мы не можем по её виду сказать имплементирована ли она так:
Речь идёт не о том, как это может быть в идеальном случае. А о вот таком случае:
Какой код генерируется автоматически? Можно посмотреть на декларацию класса и реализацию перечисленных мною функций?
В ответ на:
Я думаю, что здесь вы не совсем правы. ms_address_field является мембер-переменной - указателем.
Я думаю, что здесь вы не совсем правы. ms_address_field является мембер-переменной - указателем.
Разумееется я прав. Во-первых, почему вообще ms_address_field хранится в классе как указатель? Почему не по значению? Во-вторых, функция возвращает указатель на внутренности поля. Это плохо. Ещё того хуже, что эти внутренности возвращаются в виду указателя. Почему это плохо? Потому имея функцию вида const axis2_char_t *Options::getActionField(), мы не можем по её виду сказать имплементирована ли она так:
const axis2_char_t *Options::getActionField()
{
return (axis2_char_t *)ms_address_field->c_str();
}
или так:
const axis2_char_t *Options::getActionField()
{
return (axis2_char_t *) strdup( ms_address_field->c_str() );
}
Соотвественно мы не знаем, что мы должны делать с данным указателем, то ли потереть его с помощью free, то ли с помощью delete[], то ли оставить всё как есть. Вообще, raw pointer - в большинстве случае есть зло. Есть ссылки, есть значения, есть умные указатели. Обычно этого достаточно. В-третьих, здесь убирается const-qualifier с помощью сишного каста, что не только плохо, но и совершенно излишне.
В ответ на:
Уничтожение оной будет предпринято только при вызове деструктора - до этого ничего
Уничтожение оной будет предпринято только при вызове деструктора - до этого ничего
Речь идёт не о том, как это может быть в идеальном случае. А о вот таком случае:
{
Options o;
axis2_char_t const * address = o.getActionField();
delete [] address;
} // приехали...
NEW 18.12.08 18:38
в ответ femidav 18.12.08 17:02
функция возвращает указатель на внутренности поля.
ms_address_field как указатель на стринг можно конечно заменить и на сам стринг - и вместо
const axis2_char_t *Options::getActionField(){ return (axis2_char_t *)ms_address_field->c_str();}
вернуть
const axis2_char_t *Options::getActionField(){ return (axis2_char_t *)ms_address_field.c_str();}
Банальный вопрос - а почему это плохо?
В чем вообще разница между указателем и референц?
В обоях случаях передаётся адресация поля.
Falls ich davon ausgehe, dass mir die flache Kopie völlig ausreicht, dann erfüllt es
ihren Zweck.
Насчёт существования этой версии
const axis2_char_t *Options::getActionField(){ return (axis2_char_t *) strdup( ms_address_field->c_str() );}
я очень сомневаюсь.
Думаю что знаем. Аллокация произошла с new std::string значит delete[].
Конечно плохо то что потом указатель указывает на поле которого позже может и не быть.
Конечно это только мои доводы. С этим языком я не настолько знаком ...
ms_address_field как указатель на стринг можно конечно заменить и на сам стринг - и вместо
const axis2_char_t *Options::getActionField(){ return (axis2_char_t *)ms_address_field->c_str();}
вернуть
const axis2_char_t *Options::getActionField(){ return (axis2_char_t *)ms_address_field.c_str();}
In Antwort auf:
Это плохо. Ещё того хуже, что эти внутренности возвращаются в виду указателя.
Это плохо. Ещё того хуже, что эти внутренности возвращаются в виду указателя.
Банальный вопрос - а почему это плохо?
В чем вообще разница между указателем и референц?
В обоях случаях передаётся адресация поля.
Falls ich davon ausgehe, dass mir die flache Kopie völlig ausreicht, dann erfüllt es
ihren Zweck.
In Antwort auf:
const axis2_char_t *Options::getActionField(){ return (axis2_char_t *)ms_address_field->c_str();}
или так:
const axis2_char_t *Options::getActionField(){ return (axis2_char_t *) strdup( ms_address_field->c_str() );}
const axis2_char_t *Options::getActionField(){ return (axis2_char_t *)ms_address_field->c_str();}
или так:
const axis2_char_t *Options::getActionField(){ return (axis2_char_t *) strdup( ms_address_field->c_str() );}
Насчёт существования этой версии
const axis2_char_t *Options::getActionField(){ return (axis2_char_t *) strdup( ms_address_field->c_str() );}
я очень сомневаюсь.
In Antwort auf:
Соотвественно мы не знаем, что мы должны делать с данным указателем, то ли потереть его с помощью free, то ли с помощью delete[]
Соотвественно мы не знаем, что мы должны делать с данным указателем, то ли потереть его с помощью free, то ли с помощью delete[]
Думаю что знаем. Аллокация произошла с new std::string значит delete[].
Конечно плохо то что потом указатель указывает на поле которого позже может и не быть.
Конечно это только мои доводы. С этим языком я не настолько знаком ...
NEW 18.12.08 18:53
Да, разумеется сейчас, пока пишем, мы это знаем. А через несколько месяцев мы будем это знать? А другой программист использующий данный интерфейс будет это знать?
Указатели плохи, потому что оставляют неясным вопрос владения, если мы передаём ссылку, то всем ясно - этот объект нам не принадлежит. В случае raw pointer никакой ясности нет. Если действительно нужен указатель, то следует использовать умные указатели - shared_ptr и т.п.
Что же касается открытия внутренностей поля - читать теорию OOP (инкапсуляция).
в ответ evgher 18.12.08 18:38
В ответ на:
Думаю что знаем. Аллокация произошла с new std::string значит delete[].
Конечно плохо то что потом указатель указывает на поле которого позже может и не быть.
Думаю что знаем. Аллокация произошла с new std::string значит delete[].
Конечно плохо то что потом указатель указывает на поле которого позже может и не быть.
Да, разумеется сейчас, пока пишем, мы это знаем. А через несколько месяцев мы будем это знать? А другой программист использующий данный интерфейс будет это знать?
В ответ на:
Это плохо. Ещё того хуже, что эти внутренности возвращаются в виду указателя. Банальный вопрос - а почему это плохо? В чем вообще разница между указателем и референц?
Это плохо. Ещё того хуже, что эти внутренности возвращаются в виду указателя. Банальный вопрос - а почему это плохо? В чем вообще разница между указателем и референц?
Указатели плохи, потому что оставляют неясным вопрос владения, если мы передаём ссылку, то всем ясно - этот объект нам не принадлежит. В случае raw pointer никакой ясности нет. Если действительно нужен указатель, то следует использовать умные указатели - shared_ptr и т.п.
Что же касается открытия внутренностей поля - читать теорию OOP (инкапсуляция).
NEW 25.12.08 23:37
Над указателем (над его значением, содержимым) можно выполнять операции, а над ссылкой нельзя.
Поэтому указатель обычно используется, если надо сделать что-то типа:
int c = *(my_ptr + 5);
Ну а ссылка используется как учит ООП исключительно для доступа к одному объекту без какой либо возможности получить другие ссылки на другие объекты.
Конечно их функции и роль во многом пересекаются, но это вполне в духе С++.
в ответ evgher 18.12.08 18:38
В ответ на:
В чем вообще разница между указателем и референц?
В чем вообще разница между указателем и референц?
Над указателем (над его значением, содержимым) можно выполнять операции, а над ссылкой нельзя.
Поэтому указатель обычно используется, если надо сделать что-то типа:
int c = *(my_ptr + 5);
Ну а ссылка используется как учит ООП исключительно для доступа к одному объекту без какой либо возможности получить другие ссылки на другие объекты.
Конечно их функции и роль во многом пересекаются, но это вполне в духе С++.