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

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


bug_ref_fn

Различия

Показаны различия между двумя версиями страницы.

Ссылка на это сравнение

Предыдущая версия справа и слеваПредыдущая версия
Следующая версия
Предыдущая версия
bug_ref_fn [2025/12/14 03:29] snegovickbug_ref_fn [2025/12/15 11:29] (текущий) – [Workaround] snegovick
Строка 1: Строка 1:
-Эта страница посвящена поиску бага связанного с вызовом функции init в произвольном модуле из модуля, в котором используются ссылки на функции.+Эта страница посвящена поиску бага связанного с вызовом функции init в произвольном модуле из другого модуля, в котором используются ссылки на функции
 + 
 +[[https://github.com/inferno-os/inferno-os/issues/31]] 
 + 
 +====== Описание ====== 
 + 
 +В коде приведённом ниже есть есть функции empty и init. В init производится попытка вызова функции init из модуля echo (как это происходит в шелле). В случае если раскоментирован блок 
 +<code> 
 +#fp:= empty; 
 +</code> 
 + 
 +или любой из if (0) включен, вызов не срабатывает: 
 +<code> 
 +link typecheck Echo->empty() 0/9cd71c5e 
 +echo: link typecheck Echo->empty() 0/9cd71c5e 
 +</code> 
 + 
 +Очевидно, что вместо init вызывается empty, которого в модуле echo нет.
  
 <code> <code>
Строка 24: Строка 41:
 init(ctxt: ref Draw->Context, argv: list of string) init(ctxt: ref Draw->Context, argv: list of string)
 { {
- sys = load Sys Sys->PATH;+  sys = load Sys Sys->PATH
 + 
 +  #fp:= empty;
  
   if (0)   if (0)
Строка 33: Строка 52:
   }   }
  
- file := "echo.dis";+  file := "echo.dis";
  
   args : list of string;   args : list of string;
   args = "\"test\"" :: args;   args = "\"test\"" :: args;
   args = "echo" :: args;   args = "echo" :: args;
-  +   
- c := load Sh93 file; +  c := load Sh93 file; 
- if(c == nil) { +  if(c == nil) { 
- err := sys->sprint("%r"); +    err := sys->sprint("%r"); 
- if(err != "permission denied" && err != "access permission denied" && file[0]!='/' && file[0:2]!="./"){ +    if(err != "permission denied" && err != "access permission denied" && file[0]!='/' && file[0:2]!="./"){ 
- c = load Sh93 "/dis/"+file; +      c = load Sh93 "/dis/"+file; 
- if(c == nil) { +      if(c == nil) { 
- err = sys->sprint("%r");+        err = sys->sprint("%r");
       }       }
- } 
- if(c == nil) { 
- sys->print("%s: %s\n", "echo", err); 
- return; 
     }     }
- }+    if(c == nil) { 
 +      sys->print("%s: %s\n", "echo", err); 
 +      return; 
 +    } 
 +  }
      
- c->init(ctxt, args);+  c->init(ctxt, args);
  
   if (0)   if (0)
Строка 64: Строка 83:
 } }
 </code> </code>
 +
 +====== Workaround ======
 +
 +Добавление проблемной функции в объявление модуля помогает решить проблему:
 +
 +<code>
 +Sh93: module
 +{
 +  init: fn(ctxt: ref Draw->Context, argv: list of string);
 +  empty: fn();
 +};
 +</code>
 +
 +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 and 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.1765682970.txt.gz · Последнее изменение: snegovick