В (по крайней мере) Linux argv
и envp
имеют один и тот же тип: они являются указателями на массив указателей с NULL-окончанием на строки, заканчивающиеся NUL, и их хранилище сохраняется в течение всего времени жизни процесса,без необходимости управлять этим.Строки envp
имеют форму "KEY = VALUE", поэтому getenv("KEY")
может перебирать строки envp
, сравнивать их начальные байты с "KEY", а затем возвращать указатель на строку, начинающуюся после'=', когда найден.
Итак, поиск может вообще не включать выделение памяти, но поиск выполняется медленнее, чем при хеш-таблице.
Когда вы получаете envp
, ОС гарантирует правильность типа, но ничего не говорит о том, насколько велик массив.
Я хотел бы написать getenv (), который работает с этимвведите так, как он действительно расположен в памяти, и я хотел бы вернуть указатели в его строки с минимальным выделением.
Я ожидал бы, что что-то подобное будет работать:
fun getenv_from(key: string, env: magic): [b:bool] option_vt(string, b) =
if string2ptr(ptr[0]) > the_null_pointer then (
case+ string_is_prefix(string_append(key, "="), env[0]) of
| true => Some_vt(string_make_suffix(env[0], string_length(key)+1))
| false => getenv_from(key, succ(env))
) else None_vt()
где magic
должно быть просто envp
ptr
плюс, я полагаю, некоторые praxi
проверочные утверждения, которые сообщают ATS, что я говорил вам об этом типе.
Я пришелс одним обходным путем, который должен делать вид, что envp
действительно имеет тип argv
:
#include "share/atspre_staload.hats"
extern fun fake_free{n:int}: argv(n) -> void = "mac#"
%{
void fake_free(void *arg) {}
%}
// print out the first environment variable, as an example
implement main{n:int}(argc, argv, envp) =
let
val env2 = $UNSAFE.castvwtp1{argv(n)}(envp)
in
if argc > 0 then
print_string(env2[0]);
print_newline();
fake_free(env2);
0
end
Это работает, но теперь вы также должны победить ложные ограничения, включающие argc
(что на самом деле не имеет ничего общего с envp
), а также иметь дело с линейной типизацией, которая не нужна.
Просмотр ATSбиблиотека, я думаю, parray_v
может быть полезна, но я не нашел ни одного примера использования parray_v
.
Примечание: с чисто практической точки зрения использование собственного getenv () в C легкодостаточно из кода ATS, как при использовании различных вызовов getenv_gc
, getenv_opt
, getenv_exn' in ATS's own libraries. So the problem is not "how can I get an environment variable in ATS program?", but really "how can I *properly implement getenv()* in ATS". I'm given a bare pointer. How do I tell ATS about its properties, so that I can work with it in a legal manner? I also don't want to write C-in-ATS with
$ UNSAFE.ptr_xxx`;Я не хочу отказываться от преимущества ОВД, связанного с безопасным доступом к памяти, даже с указателями.