A maioria das shells não usa a API getenv() / setenv() / putenv() .
Ao iniciar, eles criam variáveis de shell para cada variável de ambiente. Eles serão armazenados em estruturas internas que precisam carregar outras informações, como se a variável fosse exportada, somente leitura ... Eles não podem usar o environ da libc para isso.
Da mesma forma, e por esse motivo, eles não usarão execlp() , execvp() para executar comandos, mas chamarão a chamada de sistema execve() diretamente, computando a matriz envp[] com base na lista de suas variáveis exportadas.
Portanto, em seu gdb , você precisaria adicionar uma entrada a essa tabela interna de variáveis shells, ou possivelmente chamar a função correta que faria com que ela interpretasse um código export VAR=value para atualizar a tabela por si só .
Por que você vê uma diferença entre bash e zsh quando chama setenv() in gdb , suspeito que seja porque você está chamando setenv() antes do shell inicializar, por exemplo, ao digitar main() .
Você perceberá que bash main() é int main(int argc, char* argv[], char* envp[]) (e bash mapeia as variáveis dessas env vars em envp[] ), enquanto zsh é int main(int argc, char* argv[]) e zsh obtém as variáveis de environ em vez disso. setenv() modifica environ , mas não pode modificar envp[] no local (somente leitura em vários sistemas, bem como as cadeias apontadas por esses ponteiros).
Em qualquer caso, após o shell ter lido environ na inicialização, usar setenv() seria ineficaz, pois o shell não usa mais environ (ou getenv() ) posteriormente.