2016-08-19 4 views
0

Я пытаюсь получить доступ к переменной среды из программы на C++. Так что я сделал тестовую программу, которая работает отлично:Невозможно получить доступ к переменной среды из программы C/C++

#include <stdio.h> 
#include <stdlib.h> 

int main() 
{ 
    printf("MANIFOLD : %s\n", getenv("MANIFOLD_DIRECTORY")); 
    return(0); 
} 

Выход: MANIFOLD : /home/n1603031f/Desktop/manifold-0.12.1/kitfox_configuration/input.config

Примечание: Подпись GetEnv является:

char *getenv(const char *name); 

Но когда я использую это как часть более более крупная программа с большим количеством связанных файлов:

energy_introspector->configure (getenv("MANIFOLD_DIRECTORY")); 

Выше не работает.

char *a = new char [1000]; 
a = getenv("MANIFOLD_DIRECTORY"); 
energy_introspector->configure (a); 

Выше также не работает.

Примечание: Подпись функции конфигурирования: сообщения

void configure(const char *ConfigFile); 

Ошибка:

Number of LPs = 1 
[Ubuntu10:18455] *** Process received signal *** 
[Ubuntu10:18455] Signal: Segmentation fault (11) 
[Ubuntu10:18455] Signal code: Address not mapped (1) 
[Ubuntu10:18455] Failing at address: (nil) 
[Ubuntu10:18455] [ 0] /lib/x86_64-linux-gnu/libpthread.so.0(+0x10330) [0x7f9a38149330] 
[Ubuntu10:18455] [ 1] /lib/x86_64-linux-gnu/libc.so.6(strlen+0x2a) [0x7f9a37dfc9da] 
[Ubuntu10:18455] [ 2] /home/n1603031f/Desktop/manifold-0.12.1/simulator/smp/QsimLib/smp_llp() [0x5bf8c4] 
[Ubuntu10:18455] [ 3] /home/n1603031f/Desktop/manifold-0.12.1/simulator/smp/QsimLib/smp_llp() [0x5a4ac6] 
[Ubuntu10:18455] [ 4] /home/n1603031f/Desktop/manifold-0.12.1/simulator/smp/QsimLib/smp_llp() [0x5a4df8] 
[Ubuntu10:18455] [ 5] /home/n1603031f/Desktop/manifold-0.12.1/simulator/smp/QsimLib/smp_llp() [0x4283b6] 
[Ubuntu10:18455] [ 6] /home/n1603031f/Desktop/manifold-0.12.1/simulator/smp/QsimLib/smp_llp() [0x41e197] 
[Ubuntu10:18455] [ 7] /home/n1603031f/Desktop/manifold-0.12.1/simulator/smp/QsimLib/smp_llp() [0x41de7a] 
[Ubuntu10:18455] [ 8] /home/n1603031f/Desktop/manifold-0.12.1/simulator/smp/QsimLib/smp_llp() [0x41d906] 
[Ubuntu10:18455] [ 9] /home/n1603031f/Desktop/manifold-0.12.1/simulator/smp/QsimLib/smp_llp() [0x41710b] 
[Ubuntu10:18455] [10] /lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xf5) [0x7f9a37d95f45] 
[Ubuntu10:18455] [11] /home/n1603031f/Desktop/manifold-0.12.1/simulator/smp/QsimLib/smp_llp() [0x41697f] 
[Ubuntu10:18455] *** End of error message *** 
-------------------------------------------------------------------------- 
mpirun noticed that process rank 0 with PID 18455 on node Ubuntu10 exited on signal 11 (Segmentation fault). 
-------------------------------------------------------------------------- 

Но это работает:

energy_introspector->configure ("/home/n1603031f/Desktop/manifold-0.12.1/kitfox_configuration/input.config"); 
+0

Могут ли быть другие вызовы 'getenv' внутри' configure'? Каждый раз, когда вызывается 'getenv', он может аннулировать результат последнего вызова. –

+0

@ TheDark No. Нет вызова 'getenv()' from 'configure' – PRP

+0

Практически нет оправдания для' new char [1000] 'в C++. Либо 'std :: string',' std :: vector ', либо' std :: array 'будет лучшим выбором. В этом случае: 'std :: string a = getenv();' – MSalters

ответ

3

getenv возвращает указатель на библиотечную память, которая не принадлежит вашей программе. Ваш

a = new char [1000] 

линия показывает, что вы не узнали об этом и, похоже, предположили, что вам нужно предоставить память. Это неверно, особенно у вас может никогда освободить память, возвращенную getenv.

(Даже если это было бы правильным, простое присваивание указателя

a = getenv... 

все равно будет не так, как вы просто поменяв указатель, а не копирования памяти. Эта линия является утечка памяти, как вы потеряйте указатель на выделенные 1000 символов)

Если вы хотите, чтобы ваша программа владела этой памятью, чтобы позже вы могли ее скопировать в наше личное пространство.

a = new char [1000]; 
e = getenv (<whatever>); 
strcpy (a, e); 

К сожалению, я не могу видеть, что вы делаете с указателем позже в других ваших примерах, особенно если вы пытаетесь free или delete его. Оба приведут к ошибке.

+0

Каково ваше решение? Есть ли ? – PRP

+0

btw .... 'a = новый символ [1000]; (); strcpy (a, e); 'не работает – PRP

+1

@PRP И * что именно *" не работает "? – tofro

1

Первая явная ошибка в вашем коде - распределение массива символов, а затем присвоение результата getenv. Это приводит к утечке памяти.В вашем случае использования:

std::string a = getenv("MANIFOLD_DIRECTORY"); 

Это сохраняет результат в переменной a и делает ваш код невосприимчивым к незаходимого переменных окружения.

Если getenv возвращает NULL, тогда переменная с указанным именем не находится в среде, переданной вашему приложению. Попробуйте перечислить все доступные переменные среды с кодом, как показано ниже.

extern char** environ; 

for (int i = 0; environ[i] != NULL; ++i) { 
    std::cout << environ[i] << std::endl; 
} 

Если ваша переменная отсутствует в списке, то, скорее всего, это проблема, как вы называете свое приложение. Другой вариант заключается в том, что ваша среда не установлена.

Смежные вопросы