Инструменты пользователя

Инструменты сайта


bug_ref_fn

Это старая версия документа!


Эта страница посвящена поиску бага связанного с вызовом функции init в произвольном модуле из другого модуля, в котором используются ссылки на функции.

https://github.com/inferno-os/inferno-os/issues/31

Описание

В коде приведённом ниже есть есть функции empty и init. В init производится попытка вызова функции init из модуля echo (как это происходит в шелле). В случае если раскоментирован блок

#fp:= empty;

или любой из if (0) включен, вызов не срабатывает:

link typecheck Echo->empty() 0/9cd71c5e
echo: link typecheck Echo->empty() 0/9cd71c5e

Очевидно, что вместо init вызывается empty, которого в модуле echo нет.

implement Sh93;

include "sys.m";
  sys: Sys;

include "draw.m";

Sh93: module
{
  init: fn(ctxt: ref Draw->Context, argv: list of string);
};

SomeT: adt {
  f: ref fn();
};

empty() {
  sys->print("empty\n");
}

init(ctxt: ref Draw->Context, argv: list of string)
{
  sys = load Sys Sys->PATH;

  #fp:= empty;

  if (0)
  {
    st:= ref SomeT;
    st.f = empty;
    st.f();
  }

  file := "echo.dis";

  args : list of string;
  args = "\"test\"" :: args;
  args = "echo" :: args;
  
  c := load Sh93 file;
  if(c == nil) {
    err := sys->sprint("%r");
    if(err != "permission denied" && err != "access permission denied" && file[0]!='/' && file[0:2]!="./"){
      c = load Sh93 "/dis/"+file;
      if(c == nil) {
        err = sys->sprint("%r");
      }
    }
    if(c == nil) {
      sys->print("%s: %s\n", "echo", err);
      return;
    }
  }
  
  c->init(ctxt, args);

  if (0)
  {
    st:= ref SomeT;
    st.f = empty;
    st.f();
  }
}

Workaround

Объявление функции в блоке «модуль» помогает решить проблему:

Добавляем empty в декларацию модуля:

Sh93: module
{
  init: fn(ctxt: ref Draw->Context, argv: list of string);
  empty: fn();
};

Lets check libinterp/link.c. The error manifests itself in linkm proc (thats where «link typecheck» message comes from), for some reason

empty

is in

m->ext

array (interp.h / struct Module comment calls

m->ext

: «External dynamic links») and this loop: [ for(l = m→ext; l→name; l++)](https://github.com/inferno-os/inferno-os/blob/d7b29f497205f48247d2bab33340bd7ace64de4d/libinterp/link.c#L41) iterates over

init<code/> and <code>empty

.

When you add

empty

to module definition explicitly, then this loop only makes single iteration with

init

.

Limbo does not have anonymous functions (lambdas) as far as I know, so this issue just leads to inconvenience of declaration of functions you normally would prefer not to declare.

bug_ref_fn.1765798052.txt.gz · Последнее изменение: snegovick