Время жизни указателя, указывающего на функцию c_str в std::string

Во-первых, код, указанный ниже.

#include<string>
#include<stdio.h>

int main(){

    const char *cs;
    {
        std::string s("123456");
        cs = s.c_str();
        printf("cs = %s\n",cs);
    }
    printf("cs = %s\n",cs);
    return 0;
}

запустите его и получите следующий результат. (линукс gcc)

cs = 123456
cs = 123456

Итак, я не знаю, почему указатель cs действителен после уничтожения s. другими словами, время жизни указателя, указывающего на функцию c_str в std::string.


person Andy Cong    schedule 04.05.2020    source источник
comment
УБ есть УБ, вроде работает возможен выход.   -  person Jarod42    schedule 04.05.2020
comment
Невозможно определить, что указатель действителен, в том числе использовать его, чтобы увидеть, что происходит. Как говорится в старой поговорке, неопределенное поведение не определено.   -  person molbdnilo    schedule 04.05.2020
comment
Возможность распечатать содержимое указателя не доказывает, что указатель действителен.   -  person john    schedule 04.05.2020


Ответы (3)


Код имеет неопределенное поведение.

Во втором printf() указатель cs по-прежнему указывает на освобожденную память. Тот факт, что вы получаете один и тот же вывод, просто означает, что содержимое этой памяти еще не было перезаписано. Но по-прежнему невозможно получить доступ к освобожденной памяти.

person Remy Lebeau    schedule 04.05.2020

Это типичная проблема использования после освобождения, часть памяти, на которую указывает cs, освобождается, но, к счастью, она еще не возвращена ядру или повторно не использована вашей программой. Поведение use-after-free не определено, и вам не следует этого делать. Это одна из самых сложных проблем для решения. Google предоставил инструмент с открытым исходным кодом, который поможет вам определить использование после освобождения в вашем коде: https://github.com/google/sanitizers/wiki/AddressSanitizer

person Benquan Yu    schedule 04.05.2020
comment
но, к счастью, работает и является наихудшим признаком неопределенного поведения. Громко проигрывать гораздо предпочтительнее - person Caleth; 04.05.2020

Только предположение, но:

  • Ваша операционная система допускает более слабую политику, когда речь идет о выделении памяти. Это случалось со мной, когда я иногда работал в Windows, код, который заканчивался бы на sigsegv в linux, хорошо работал на win.
  • Кроме того, это может зависеть от вашего компилятора, версии c++ и так далее. Он может потреблять только ссылку и копировать по требованию. См. здесь Will std:: string.assign(const char*) или op= (с const char *) создать копию char*?
person Ondřej Navrátil    schedule 04.05.2020
comment
С++ управляется не так, как С#, поэтому дело не в операционной системе. Указатель просто указывает на место, которое не было изменено за это время, поэтому он печатает правильную строку. Если вы делали что-то между прицелом и 2-м отпечатком, вы, вероятно, видите мусор... - person Lior; 04.05.2020