LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Programming (https://www.linuxquestions.org/questions/programming-9/)
-   -   getenv Returns different pointers every time it is called? (https://www.linuxquestions.org/questions/programming-9/getenv-returns-different-pointers-every-time-it-is-called-663025/)

worldgnat 08-15-2008 12:00 PM

getenv Returns different pointers every time it is called?
 
Sequel to my previous post here: http://www.linuxquestions.org/questi...u-8.04-662853/ I discovered a separate issue. I'm working with the same book, however now I'm trying to get the memory address of an environment variable. I googled around, and found this:

Quote:

There is not one single environment space. In fact, every program has their own unique environment space. By default, the environment from one program is copied into the next under it via fork and execs. A fork will make an (almost) exact copy of a program/process, environment and all. Most libc exec calls also will copy the current environment into the new program imagine. There are a few versions of the libc exec calls that allow you to pass in an envirment and it can be anything you want it to be (hopefully a list of X=Y pairs though).
from here: http://www.developerweb.net/forum/showthread.php?t=3291

What I have done is this:

export MYVAR='test'
echo $MYVAR

And of course it echos 'test'. Here is the C source I'm trying to run (without the includes).

Code:

int main(int argc, char *argv[]) {
    printf("%s is located at: %p\n", argv[1], getenv(argv[1]));
    printf("%s was found at the address.\n", ptr);
}

And the problem is that every time I run the program I get a different address. As per the above quote, I gather that the environment variables are copied each time the given program runs, and that they will be in a different address each time, so the results would make sense. However, the book I am reading, which has thus far proven itself to be credible, and has coding examples tested on Ubuntu 7.10, said to use the above C source to find the memory address of the environment variable and then enter it as the argument for another, precompiled binary using perl. I tried it and obviously it doesn't work.

I added the second printf so that I can verify that the given address does actually contain the information, and it does every time.

From what I've been reading, I gather that what I'm looking for is a thread safe version of getenv(), but I haven't found one thus far. I found this: https://www.securecoding.cert.org/co...ed+by+getenv() but either I don't understand it or it's not what I'm looking for.

I'd appreciate if someone could give me a hand with this, I'm a little stuck.

Thanks,
-Peter

raconteur 08-15-2008 01:47 PM

How are you invoking the perl executable?

Some invocation functions allow you to pass a pointer to the environment space (execlp() is a good example).

jim mcnamara 08-15-2008 01:51 PM

First off - environment variables (which argv[1] is not one of) are stored as part of the process memory - additions, ie., newly declared variables are inserted where there is free space. If there is no free space, then malloc is called to get more space. This means that the environment variables are stored in heap memory.

When you run a program it is the result of a fork()/exec() call. Meaning that you have a brand new process, with brand new variables, stored in memory in a new place. This means that every time you run a C program it can be loaded anywhere (almost) into memory, so the absolute addresses allocated in heap will be different.

Secondly, if you want the address of "MYVAR" you have to call getenv("MYVAR"). The returned pointer is the address in the current process heap memory where the variable value is stored.

Environment variables are stored as "SOMEVARIABLE=value". getenv returns the address of value, so you have to take what I said with a grain of salt - literally the part about addresses.

And. C somewhat unwillingly supports
Code:

int main(int argc, char ** rgv, char **envp)
You can loop thru the envp array until it returns NULL, and see what is in memory. This emulates the output of the shell command env or set.

Code:

#include <stdlib.h>

int main(int argc, char **argv, char **envp)
{
   
    for(envp; *envp!=NULL; envp++)
    {
            printf("%s\n", *envp);
    }
    return 0;
}


worldgnat 08-15-2008 09:58 PM

That's what I thought. Ok, so I abandoned all hope of finding the address and passing it via shell to the other program, and I wrote another program that uses getenv() to find the address and then use execle() to run my other binary so that the environment variable will still be there when it executes. It's not what the book says to do, but whatever, it works. Thanks for the help.


All times are GMT -5. The time now is 04:51 PM.