Время жизни временных объектов
От: 10000.monkeys Россия  
Дата: 07.04.21 08:18
Оценка:
Код ниже продуцирует ошибку доступа в дебаге.

#include <string>
#include <iostream>

struct test
{
    test(const std::string& s) : s(s) {}
    const std::string& s;
};
std::unique_ptr<test> construct(const char* s)
{
    return std::make_unique<test>(s);
}
void print(std::unique_ptr<test> t)
{
    std::cout << t->s.c_str();
}
int main(int argc, char* argv[])
{
    print(construct("TEST"));
    return 0; 
}


Поправьте если не прав.
Из временной строки конструируется временный std::string, ссылка на который передается в конструктор. По ходу дела ссылка в объекте становится невалидной из-за разрушения временного std::string, и мы имеем ошибку доступа.

Если все так вопросы следующие. Где заканчивается полное выражение для временной строки? В этом случае не работает расширение жизни объекта на который ссылается константная ссылка (работает но ссылка умирает по дороге)? Где доходчиво можно прочитать про временные объекты и их время жизни?
временный объект время жизни у объекта lifetime
Re: Время жизни временных объектов
От: Muxa  
Дата: 07.04.21 09:23
Оценка: -1
1M>std::unique_ptr<test> construct(const char* s)
1M>{
1M>    return std::make_unique<test>(s);
1M>}
1M>


1M>Если все так вопросы следующие. Где заканчивается полное выражение для временной строки? В этом случае не работает расширение жизни объекта на который ссылается константная ссылка (работает но ссылка умирает по дороге)? Где доходчиво можно прочитать про временные объекты и их время жизни?


возвращаемый объект этой функции не константный, видимо умирает именно он, а не указатель на строку.
попробуй так
#include <string>
#include <iostream>
#include <memory>

struct test
{
    test(const std::string& s) : s(s) {}
    const std::string& s;
};
const std::unique_ptr<test> construct(const char* s)
{
    return std::make_unique<test>(s);
}
void print(const std::unique_ptr<test> &t)
{
    std::cout << t->s.c_str();
}
int main(int argc, char* argv[])
{
    print(construct("TEST"));
    return 0; 
}
Re: Время жизни временных объектов
От: Videoman Россия https://hts.tv/
Дата: 07.04.21 09:31
Оценка: +3
Здравствуйте, 10000.monkeys, Вы писали:

1M>Поправьте если не прав.

Не прав. Вот тут:
return std::make_unique<test>(s);

из s создается временный std::string который благополучно умирает при возврате std::unique_ptr<test>.

Замени const std::string& s на std::string s
struct test
{
    test(const std::string& s) : s(s) {}
    std::string s;
};

P.S.

Если ты где-то прочитал что const ссылка продлевает время жизни объекта, то это совсем не тот случай. const ссылка будет оставаться валидной только при возврате объекта из функции по значению.
Отредактировано 07.04.2021 11:33 Videoman . Предыдущая версия . Еще …
Отредактировано 07.04.2021 9:33 Videoman . Предыдущая версия .
Отредактировано 07.04.2021 9:33 Videoman . Предыдущая версия .
Re: Время жизни временных объектов
От: σ  
Дата: 07.04.21 09:59
Оценка:
1M> Где доходчиво можно прочитать про временные объекты и их время жизни?

https://timsong-cpp.github.io/cppwp/n4861/class.temporary
Re: Время жизни временных объектов
От: Sm0ke Россия ksi
Дата: 07.04.21 12:33
Оценка:
Здравствуйте, 10000.monkeys, Вы писали:

1M>Код ниже продуцирует ошибку доступа в дебаге.


1M>
1M>#include <string>
1M>#include <iostream>

1M>struct test
1M>{
1M>    test(const std::string& s) : s(s) {}
1M>    const std::string& s;
1M>};
1M>std::unique_ptr<test> construct(const char* s)
1M>{
1M>    return std::make_unique<test>(s);
1M>}
1M>void print(std::unique_ptr<test> t)
1M>{
1M>    std::cout << t->s.c_str();
1M>}
1M>int main(int argc, char* argv[])
1M>{
1M>    print(construct("TEST"));
1M>    return 0; 
1M>}
1M>


1M>Поправьте если не прав.

1M>Из временной строки конструируется временный std::string, ссылка на который передается в конструктор. По ходу дела ссылка в объекте становится невалидной из-за разрушения временного std::string, и мы имеем ошибку доступа.

1M>Если все так вопросы следующие. Где заканчивается полное выражение для временной строки? В этом случае не работает расширение жизни объекта на который ссылается константная ссылка (работает но ссылка умирает по дороге)? Где доходчиво можно прочитать про временные объекты и их время жизни?


У вас ошибка в структуре test. Конструктор принимает временный объект в аргумент, время жизни которого продлевается до конца жизни аргумента, и при выходе из конструктора поле s ссылается на уже разрушенный объект. Константная ссылка не продлевает время жизни другой константной ссылки.
Re: Время жизни временных объектов
От: ArtDenis Россия  
Дата: 07.04.21 14:33
Оценка: 11 (1) +1
Здравствуйте, 10000.monkeys, Вы писали:

1M>Код ниже продуцирует ошибку доступа в дебаге.


А самое прикольное, что asan не ловит эту ошибку. Чтобы он начал её ловить, надо длину увеличить строки (поставить например "TEST66666666666666666" вместо "TEST"). Похоже что такое поведение связано со small string optimization.

https://gcc.godbolt.org/z/qv3o771bY
[ 🎯 Дартс-лига Уфы | 🌙 Программа для сложения астрофото ]
Отредактировано 07.04.2021 14:35 ArtDenis . Предыдущая версия .
Re: Время жизни временных объектов
От: TailWind  
Дата: 07.04.21 16:49
Оценка:
Что-то ты намудрил
Можно проще эту ошибку словить:

struct test
{
    test(const std::string& s) : s(s) {}
    const std::string& s;
};

int main()
{   
    test *t = new test("123");
    //
    printf("%s\n", t->s.c_str());
}
Re: Время жизни временных объектов
От: rg45 СССР  
Дата: 07.04.21 20:46
Оценка:
Здравствуйте, 10000.monkeys, Вы писали:

1M>
1M>#include <string>
1M>#include <iostream>

1M>struct test
1M>{
1M>    test(const std::string& s) : s(s) {}
1M>    const std::string& s;
1M>};
1M>std::unique_ptr<test> construct(const char* s)
1M>{
1M>    return std::make_unique<test>(s);
1M>}
1M>void print(std::unique_ptr<test> t)
1M>{
1M>    std::cout << t->s.c_str();
1M>}
1M>int main(int argc, char* argv[])
1M>{
1M>    print(construct("TEST"));
1M>    return 0; 
1M>}
1M>



1M> Где заканчивается полное выражение для временной строки?


Это выражение под оператором return в функции construct.

1M> В этом случае не работает расширение жизни объекта на который ссылается константная ссылка (работает но ссылка умирает по дороге)?


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

1M> Где доходчиво можно прочитать про временные объекты и их время жизни?


https://en.cppreference.com/w/cpp/language/lifetime#Temporary_object_lifetime
https://en.cppreference.com/w/cpp/language/reference_initialization#Lifetime_of_a_temporary

И по последней ссылке есть полезные примеры:
https://coliru.stacked-crooked.com/view?id=9869da7c84b2a746
--
Не можешь достичь желаемого — пожелай достигнутого.
Отредактировано 07.04.2021 21:12 rg45 . Предыдущая версия . Еще …
Отредактировано 07.04.2021 21:08 rg45 . Предыдущая версия .
Отредактировано 07.04.2021 21:02 rg45 . Предыдущая версия .
Отредактировано 07.04.2021 21:01 rg45 . Предыдущая версия .
Отредактировано 07.04.2021 20:51 rg45 . Предыдущая версия .
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.