How to use a static environment

Giuseppe Modugno giuseppe.modugno.loqed@gmail.com
Thu Apr 5 15:46:00 GMT 2018


Il 05/04/2018 17:32, Bob Dunlop ha scritto:
> Hi,
>
> I don't know the newlib specifics but have played with this in other
> library environments before.
>
> The answer to your first question "Should unsetenv() free?" the
> answer is No because unsetenv() doesn't know where the original string
> came from.  You could be freeing something that was never malloc'd.
setenv() calls malloc to copy and save the new variable/value pair in a 
single string. So I was thinking the behaviour of unsetenv() should be 
symmetrical, i.e. unsetenv() should have free. Otherwise:

   setenv("TZ", "whatever", 1);
   unsetenv("TZ");

and you will have a memory leak... right?

> I'd also expect if it did free the memory you'd find a lot of use after
> free bugs pop out of the wooodwork.
>
>
> On Thu, Apr 05 at 04:49, Giuseppe Modugno wrote:
>> I need to use environment functionality in newlib to have a correct
>> result from localtime() with the western european timezone (I need TZ
>> environment variable). I? also need to convert UTC struct tm to time_t
>> with mktime(), so I should delete TZ variable before calling mktime().
>>
>> I know I can call setenv()/unsetenv(), but I would like to avoid using
>> dynamic allocation (that those functions use). So I'm thinking to have
>> two static const environments, such as:
>>
>>   ? static const char *const env_with_tz[] = {
>> "TZ=CET-1CEST,M3.5.0,M10.5.0/3", NULL };
>>   ? static const char *const env_empty[] = { NULL };
>>
>> and change the environment on-the-fly in the following way:
>>
>>   ? extern char **environ;
>>   ? environ = env_with_tz;??? ??? // or environ = env_empty;
>>
>> Is it safe?
> I doubt it very much.
>
> putenv() should be you friend rather than setenv() since it installs
> a string that you are then allowed to manipulate.
putenv() calls sentenv() in newlib.

>    static char tzbuf[ 50 ];
>
>    /* Install your buffer */
>    /* Your string may only be installed if the slot is empty */
>    unsetenv("TZ");
>    strcpy(tzbuf, "TZ=CET-1CEST,M3.5.0,M10.5.0/3");
>    putenv(tzbuf);
>    /* No need to call putenv() any more */
>
>    /* From now on you just need to manipulate the value in tzbuf */
>    strcpy(tzbuf + 3, "CET-1CEST,M3.5.0,M10.5.0/3");
>    Action using TZ
>    strcpy(tzbuf + 3, "UTC0")
>    Action using TZ...
>
I will try, but if I understand the source code of newlib, it doesn't 
work in this way.

Have a look at sentenv() code:

   if (!((*p_environ)[offset] =    /* name + `=' + value */
     _malloc_r (reent_ptr, (size_t) ((int) (C - name) + l_value + 2))))
     {
       ENV_UNLOCK;
       return -1;
     }
   for (C = (*p_environ)[offset]; (*C = *name++) && *C != '='; ++C);
   for (*C++ = '='; (*C++ = *value++) != 0;);

Here the pointer to the variable (*p_environ)[offset] is the result of a 
malloc() and the variable name and value (and equal sign) are copied to 
this allocated buffer. The string passed as arguments to setenv() aren't 
considered anymore by newlib functions.
Because putenv() calls senenv(), the behaviour of these two functions is 
the same.



More information about the Newlib mailing list