Переменная всегда пуста - PullRequest
1 голос
/ 19 июня 2020

У меня проблемы с инициализацией глобальной переменной. Мой C ++ немного заржавел, поэтому я не могу вспомнить причину, по которой мой код не работает.

файл. cpp

const char * write_path = &(std::string(getenv("FIFO_PATH")) + "/pythonread_fifo")[0];

int main(int argc, char**argv)
{
    std::cout << "printing a string: ";
    std::cout << (std::string(getenv("FIFO_PATH")) + "/pythonread_fifo\n");

    std::cout << "printing a const char*: ";
    std::cout << &(std::string(getenv("FIFO_PATH")) + "/pythonread_fifo")[0] << std::endl;

    std::cout << "printing write_path:";
    std::cout << write_path;
    std::cout << write_path << std::endl;

    std::cout << "printing FIFO_PATH:" << std::string(getenv("FIFO_PATH"));
}

Как Предпосылка: FIFO_PATH был правильно добавлен в bashr c, и он работает, однако, когда я запускаю эту программу, это результат:

printing a string: /home/Processes/FIFOs/pythonread_fifo
printing a const char*: /home/Processes/FIFOs/pythonread_fifo
printing write_path:
printing FIFO_PATH:/home/Processes/FIFOs

Как видите, write_path полностью пуст.

Что еще более странно для меня, так это то, что если я определю write_path как:

 const char * write_path = "/home/Processes/FIFOs/pythonread_fifo";

, то write_path больше не будет пустым, он будет правильно инициализирован и напечатан.

Как может Я это решаю? Или, по крайней мере, почему это происходит?

EDIT: проблема НЕ связана с глобальным значением write_path. Я поместил определение внутри основного, и когда я пытаюсь напечатать write_path, оно все еще пустое

Ответы [ 3 ]

6 голосов
/ 19 июня 2020

write_path инициализируется как указатель, указывающий на 1-й элемент временного std::string, который будет уничтожен сразу после полного выражения, оставив write_path висящим, разыменование на нем приводит к UB.

Вы можете использовать std::string напрямую или использовать именованный std::string, а затем получить от него указатель.

std::string s = std::string(getenv("FIFO_PATH")) + "/pythonread_fifo";
const char * write_path = &s[0]; // or s.c_str()

С другой стороны,

const char * write_path = "/home/mverrocc/dss_cp/dss-cp/Processes/FIFOs/pythonread_fifo";

работает нормально, строковый литерал в стиле c имеет stati c продолжительность хранения и существует в памяти в течение всего срока службы программы, тогда write_path является всегда действительный указатель.

3 голосов
/ 19 июня 2020
const char * write_path = &(std::string(getenv("FIFO_PATH")) + "/pythonread_fifo")[0];

создает временный std::string, принимает адрес его первого символа, затем отбрасывает строку, тем самым удаляя базовый массив char. Это UB.

Лучше просто std::string и c_str(), когда вам нужен const char*

2 голосов
/ 19 июня 2020

Вы создаете временный std::string объект и получаете указатель на его первый символ. Этот указатель станет недействительным, как только выражение &(std::string(getenv("FIFO_PATH")) + "/pythonread_fifo")[0] закончится, когда временный объект будет разрушен.

Используйте объект std::string также для write_path, определите его внутри функции main, и используйте функцию c_str строки, если вам нужна строка с завершающим нулем.

...