Ich habe versucht, Hello World (+ α) in C-Sprache aus JavaScript [Web Assembly] zu verschieben.

Was bedeutet es, C-Code in einem Browser auszuführen? WebAssembly war eine der Technologien, an denen ich interessiert war, weil ich mich in meinem vorherigen Job mit C befasst hatte. In diesem Artikel habe ich zusätzlich zu HelloWorld die Ergebnisse eines kleinen Experiments zusammengefasst.


## Was ist Web Assembly? *WebAssembly (abbreviated Wasm) is a binary instruction format for a stack-based virtual machine.* (Zitiert aus [Official](https://webassembly.org/))
## Postscript (was ich getan habe) * Versuchen Sie, Hello World zu bewegen * Was passiert, wenn ich Code ausführe, der Speicher verliert? * Was passiert, wenn Sie Speicher verbrauchen? * Was passiert, wenn ich Code ausführe, der einen Laufzeitfehler verursacht?
## Versuchen Sie, Hello World zu bewegen Referenz: https://laboradian.com/tried-webassembly/ (Gleiches Verfahren wie [MDN](https://developer.mozilla.org/ja/docs/WebAssembly/C_to_wasm), jedoch mit zusätzlicher Erklärung leichter zu verstehen)

** Installieren Sie Emscripten (Compiler) **

#Die diesmal installierte Version
$ emcc -v
emcc (Emscripten gcc/clang-like replacement + linker emulating GNU ld) 1.39.16
clang version 11.0.0 (/b/s/w/ir/cache/git/chromium.googlesource.com-external-github.com-llvm-llvm--project 3774bcf9f84520a8c35bf765d9a528040d68a14b)
Target: x86_64-apple-darwin19.5.0
Thread model: posix
shared:INFO: (Emscripten: Running sanity checks)

** Erstelle hallo.c **

hello.c


#include <stdio.h>

int main(int argc, char *argv[]) {
  printf("Hello World\n");
  return 0;
}

kompilieren

#Vor dem Zusammenstellen
$ ls
hello.c

#kompilieren
$ emcc hello.c -s WASM=1 -o hello.html

# wasm, js,HTML wurde generiert
$ ls -l
total 496
-rw-r--r--  1 arene  staff      95  5 19 21:55 hello.c
-rw-r--r--  1 arene  staff  102675  5 21 21:50 hello.html
-rw-r--r--  1 arene  staff  115917  5 21 21:50 hello.js    #2600 Zeilen(!)
-rw-r--r--  1 arene  staff   21727  5 21 21:50 hello.wasm

Die nach der Kompilierung generierte js-Datei hat satte 2600 Zeilen. Sie können sehen, dass es eine schwierige Technologie ist. Natürlich konnte Code, der nicht als C kompiliert werden konnte, auch nicht in WASM kompiliert werden.

↓   ** Aktivieren Sie die experimentelle Web Assembly auf Chrome: // flags / **

↓   ** Richten Sie einen Webserver auf Ihrem lokalen PC ein **

#Emscripten bietet sogar einen einfachen Webserver
$ emrun --no_browser --port 8080 .
Web server root directory: /Users/arene/temporary/wasm
Now listening at http://0.0.0.0:8080/

↓   ** Öffnen Sie hello.html in Ihrem Browser **

1.png

Der Code, der beim Kompilieren von HelloWorld automatisch generiert wurde, sah folgendermaßen aus. (Da es nicht richtig analysiert wurde und es viele davon gibt, werden nur die Teile extrahiert, an denen die Atmosphäre leicht zu erfassen ist.)

hello.html


<!--Lassen Sie Logos, terminalähnliche Bildschirme und andere unnötige Elemente weg-->
<script async type="text/javascript" src="hello.js"></script>

hello.js


//Der tatsächliche Code ist 2600 Zeilen
//Um mir einen Überblick zu verschaffen, habe ich es so extrahiert
//Die Reihenfolge der Funktionsdefinition wurde ebenfalls geändert, damit sie von Anfang an gelesen werden kann.(Tatsächlich`run();`Ist am Ende der Datei)

var wasmBinaryFile = 'hello.wasm';
if (!isDataURI(wasmBinaryFile)) {
  wasmBinaryFile = locateFile(wasmBinaryFile);
}

run(); //Dieser Typ am Ende der Datei ist der Ausgangspunkt für alles

function run(args) {
  //Sehr verschiedene Auslassungen
  callMain(args)
}
function callMain(args) {
  //Sehr verschiedene Auslassungen
  var entryFunction = Module['_main']; // Module['xxx']Es gibt viele Dinge, einschließlich der Hauptfunktion.
  var ret = entryFunction(argc, argv);
  exit(ret, true);
}

//Modul C funktioniert so["asm"]Verbunden mit
var asm = createWasm();
Module["asm"] = asm;
var _main = Module["_main"] = function() {
  assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)');
  assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)');
  return Module["asm"]["main"].apply(null, arguments)
}; 
var _malloc = Module["_malloc"] = function() {
  assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)');
  assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)');
  return Module["asm"]["malloc"].apply(null, arguments)
}; 
var _free = Module["_free"] = function() {
  assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. waMBit for main() to be called)');
  assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)');
  return Module["asm"]["free"].apply(null, arguments)
};

## Was passiert, wenn ich Code ausführe, der Speicher verliert?

** Bereiten Sie Code vor, der für jede Sekunde 100 KB Speicher verliert **

memoryLeak.c


#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

void memoryLeak(void) {
  int shouldLoop = 1;
  int loopCount = 0;
  while(shouldLoop) {
    loopCount++;
    if (loopCount > 10) {
      shouldLoop = 0;
    }
    char* p = malloc(1024 * 100); //Speicher dynamisch zuordnen. Da es nicht freigegeben wird, tritt für jede Schleife ein Speicherverlust auf.
    printf("memory leak: leak 100KB!\n");
    usleep(1000 * 1000); // 1000msec
  }
  return;
}

int main(int argc, char *argv[]) {
  printf("memory leak: start\n");
  memoryLeak();
  printf("memory leak: end\n");
  return 0;
}

↓   ** Führen Sie es nach dem Kompilieren in einem Browser aus und messen Sie die Leistung mit devtool **

1.png

JS Heap hat nicht zugenommen und auf der Vorderseite wurde kein Speicherverlust festgestellt. ...Was meinst du? (Da in Liste der Vorschläge ein GC enthalten ist, scheint der GC nicht funktioniert zu haben.)


## Was passiert, wenn Sie Speicherplatz verbrauchen?

Ich dachte, dass der Grund, warum ich den Speicherverlust im vorherigen Abschnitt nicht bestätigen konnte, darin bestand, dass die Leckbreite klein und schwer zu verstehen war, also habe ich die Leckbreite erweitert. Ich habe es in einen Code umgeschrieben, der alle 100 ms 1 MB ausläuft, was insgesamt 100 MB entspricht, und als ich es auf die gleiche Weise überprüft habe, ist der folgende Fehler aufgetreten.

Es ist unklar, welche Schicht begrenzt ist, Browser, WASM, Betriebssystem, aber es scheint, dass der verfügbare Speicher begrenzt ist. (Natürlich, natürlich)

console.log


 Cannot enlarge memory arrays to size 17534976 bytes (OOM). Either (1) compile with  -s INITIAL_MEMORY=X  with X higher than the current value 16777216, (2) compile with  -s ALLOW_MEMORY_GROWTH=1  which allows increasing the size at runtime, or (3) if you want malloc to return NULL (0) instead of this abort, compile with  -s ABORTING_MALLOC=0 
 
 memoryLeak.html:1246 Cannot enlarge memory arrays to size 17534976 bytes (OOM). Either (1) compile with  -s INITIAL_MEMORY=X  with X higher than the current value 16777216, (2) compile with  -s ALLOW_MEMORY_GROWTH=1  which allows increasing the size at runtime, or (3) if you want malloc to return NULL (0) instead of this abort, compile with  -s ABORTING_MALLOC=0 
 
 memoryLeak.html:1246 exception thrown: RuntimeError: abort(Cannot enlarge memory arrays to size 17534976 bytes (OOM). Either (1) compile with  -s INITIAL_MEMORY=X  with X higher than the current value 16777216, (2) compile with  -s ALLOW_MEMORY_GROWTH=1  which allows increasing the size at runtime, or (3) if you want malloc to return NULL (0) instead of this abort, compile with  -s ABORTING_MALLOC=0 ) at Error
     at jsStackTrace (http://0.0.0.0:8080/memoryLeak.js:1978:17)
     at stackTrace (http://0.0.0.0:8080/memoryLeak.js:1995:16)
     at abort (http://0.0.0.0:8080/memoryLeak.js:1735:44)
     at abortOnCannotGrowMemory (http://0.0.0.0:8080/memoryLeak.js:2018:7)
     at _emscripten_resize_heap (http://0.0.0.0:8080/memoryLeak.js:2021:7)
     at wasm-function[13]:0x237a
     at wasm-function[11]:0xd36
     at wasm-function[8]:0x337
     at wasm-function[9]:0x407
     at Module._main (http://0.0.0.0:8080/memoryLeak.js:2212:32),RuntimeError: abort(Cannot enlarge memory arrays to size 17534976 bytes (OOM). Either (1) compile with  -s INITIAL_MEMORY=X  with X higher than the current value 16777216, (2) compile with  -s ALLOW_MEMORY_GROWTH=1  which allows increasing the size at runtime, or (3) if you want malloc to return NULL (0) instead of this abort, compile with  -s ABORTING_MALLOC=0 ) at Error
     at jsStackTrace (http://0.0.0.0:8080/memoryLeak.js:1978:17)
     at stackTrace (http://0.0.0.0:8080/memoryLeak.js:1995:16)
     at abort (http://0.0.0.0:8080/memoryLeak.js:1735:44)
     at abortOnCannotGrowMemory (http://0.0.0.0:8080/memoryLeak.js:2018:7)
     at _emscripten_resize_heap (http://0.0.0.0:8080/memoryLeak.js:2021:7)
     at wasm-function[13]:0x237a
     at wasm-function[11]:0xd36
     at wasm-function[8]:0x337
     at wasm-function[9]:0x407
     at Module._main (http://0.0.0.0:8080/memoryLeak.js:2212:32)
     at abort (http://0.0.0.0:8080/memoryLeak.js:1741:9)
     at abortOnCannotGrowMemory (http://0.0.0.0:8080/memoryLeak.js:2018:7)
     at _emscripten_resize_heap (http://0.0.0.0:8080/memoryLeak.js:2021:7)
     at wasm-function[13]:0x237a
     at wasm-function[11]:0xd36
     at wasm-function[8]:0x337
     at wasm-function[9]:0x407
     at Module._main (http://0.0.0.0:8080/memoryLeak.js:2212:32)
     at callMain (http://0.0.0.0:8080/memoryLeak.js:2500:15)
     at doRun (http://0.0.0.0:8080/memoryLeak.js:2562:23)
 
 memoryLeak.js:1741 Uncaught RuntimeError: abort(Cannot enlarge memory arrays to size 17534976 bytes (OOM). Either (1) compile with  -s INITIAL_MEMORY=X  with X higher than the current value 16777216, (2) compile with  -s ALLOW_MEMORY_GROWTH=1  which allows increasing the size at runtime, or (3) if you want malloc to return NULL (0) instead of this abort, compile with  -s ABORTING_MALLOC=0 ) at Error
     at jsStackTrace (http://0.0.0.0:8080/memoryLeak.js:1978:17)
     at stackTrace (http://0.0.0.0:8080/memoryLeak.js:1995:16)
     at abort (http://0.0.0.0:8080/memoryLeak.js:1735:44)
     at abortOnCannotGrowMemory (http://0.0.0.0:8080/memoryLeak.js:2018:7)
     at _emscripten_resize_heap (http://0.0.0.0:8080/memoryLeak.js:2021:7)
     at wasm-function[13]:0x237a
     at wasm-function[11]:0xd36
     at wasm-function[8]:0x337
     at wasm-function[9]:0x407
     at Module._main (http://0.0.0.0:8080/memoryLeak.js:2212:32)
     at abort (http://0.0.0.0:8080/memoryLeak.js:1741:9)
     at abortOnCannotGrowMemory (http://0.0.0.0:8080/memoryLeak.js:2018:7)
     at _emscripten_resize_heap (http://0.0.0.0:8080/memoryLeak.js:2021:7)
     at wasm-function[13]:0x237a
     at wasm-function[11]:0xd36
     at wasm-function[8]:0x337
     at wasm-function[9]:0x407
     at Module._main (http://0.0.0.0:8080/memoryLeak.js:2212:32)
     at callMain (http://0.0.0.0:8080/memoryLeak.js:2500:15)
     at doRun (http://0.0.0.0:8080/memoryLeak.js:2562:23)

## Was passiert, wenn ich Code ausführe, der mit einem Laufzeitfehler abstürzt?

Schließlich habe ich versucht, den Code auszuführen, der den Laufzeitfehler verursacht hat. Das Ergebnis war natürlich ein Laufzeitfehler im Browser. Der Code nach der Zeile, die den Laufzeitfehler verursacht hat, wurde jedoch ebenfalls ausgeführt. (Wenn Sie es normal als C ausführen, wird es an der Fehlerstelle gelöscht, sodass es geringfügig anders ist.

segfault.c


#include <stdio.h>

int main(void) {
  int i;
  char str[4];
  char* p;
  
  printf("Before Segmentation Fault\n");
  for(i = 0; i < 16; i++) {
    str[i] = 'a';
    *p = str[i];
  }
  printf("After Segmentation Fault\n");
  return 0;
}
#Beim normalen Kompilieren und Ausführen als C-Sprache schlägt dies im Fehlerteil fehl
$ gcc segfault.c
$ ./a.out
Before Segmentation Fault
[1]    22777 segmentation fault  ./a.out

Bei der Ausführung über den Browser wird die Verarbeitung auch nach dem Fehlerteil fortgesetzt 1.png

Fehler bei der Konsolenanmeldung

console.log


 segfault.html:1246 Runtime error: The application has corrupted its heap memory area (address zero)!
 segfault.js:1741 Uncaught RuntimeError: abort(Runtime error: The application has corrupted its heap memory area (address zero)!) at Error
     at jsStackTrace (http://0.0.0.0:8080/segfault.js:1978:17)
     at stackTrace (http://0.0.0.0:8080/segfault.js:1995:16)
     at abort (http://0.0.0.0:8080/segfault.js:1735:44)
     at checkStackCookie (http://0.0.0.0:8080/segfault.js:1446:46)
     at postRun (http://0.0.0.0:8080/segfault.js:1538:3)
     at doRun (http://0.0.0.0:8080/segfault.js:2545:5)
     at http://0.0.0.0:8080/segfault.js:2554:7
     at abort (http://0.0.0.0:8080/segfault.js:1741:9)
     at checkStackCookie (http://0.0.0.0:8080/segfault.js:1446:46)
     at postRun (http://0.0.0.0:8080/segfault.js:1538:3)
     at doRun (http://0.0.0.0:8080/segfault.js:2545:5)
     at http://0.0.0.0:8080/segfault.js:2554:7



## Schließlich Standardeingabe, Datei-E / A, Thread, Semaphor, gemeinsamer Speicher, Signal, js-Funktion von C aufrufen, mehrere Funktionen definieren, Dateisplit, rekursiver Aufruf, Geschwindigkeitsvergleich usw. Es gibt andere Problembereiche, aber vorerst werde ich das Experiment hier beenden.

Irgendwann wird alles im Browser erledigt und ich habe einen Traum.

Recommended Posts

Ich habe versucht, Hello World (+ α) in C-Sprache aus JavaScript [Web Assembly] zu verschieben.
Ich habe versucht, eine C-Sprachprogrammquelle aus cURL zu generieren
Ich habe versucht, innerhalb von 3 Monaten einen Antrag von unerfahren zu stellen
Ich habe versucht, C # (Indexer) zu kauen.
C # (Polymorphismus: Polymorphismus)
"Lehrer, ich möchte im Frühjahr eine Anmeldefunktion implementieren" ① Hallo Welt
Konvertieren Sie die C-Sprache mit Emscripten in JavaScript
Ich habe versucht, mit Web Assembly zu beginnen
Ich habe versucht, JavaScript Part.2 Objektorientiert zu berühren
Führen Sie in der nativen Xamarin.Forms Gawa-App die Anforderungsantwort von C # an die JavaScript-Aufgabe <T> aus
Ich habe versucht, polymorph in Nogizaka zu implementieren.
[Rails] Ich habe versucht, die Version von Rails von 5.0 auf 5.2 zu erhöhen
Ich habe versucht, die Sitzung in Rails zu organisieren
Ich habe auch Web Assembly mit Nim und C ausprobiert
C # (Grund der Kapselung)
Ich habe versucht, neunundneunzig in Java auszugeben
Ich habe versucht, eine Anwendung in 2 Sprachen zu entwickeln
Ich habe versucht, Alexa-Fähigkeiten mit Java zu erstellen
Ich habe versucht zu erklären, was Sie aus Anfängersicht in einer beliebten Sprache für die Webentwicklung tun können.
Tokoro habe ich in der Migration von Wicket 7 auf 8 umgeschrieben
Ich habe versucht, die Firebase-Push-Benachrichtigung in Java zu implementieren
# 2 [Anmerkung] Ich habe versucht, neunundneunzig mit Java zu berechnen.
Ich habe versucht, eine Clova-Fähigkeit in Java zu erstellen
Ich habe versucht, eine Anmeldefunktion mit Java zu erstellen
Ich habe versucht, die Methode der gegenseitigen Teilung von Eugrid in Java zu implementieren
~ Ich habe jetzt versucht, funktionale Programmierung mit Java zu lernen ~
Ich habe versucht, C # zu kauen (Dateien lesen und schreiben)
Ich habe versucht herauszufinden, was sich in Java 9 geändert hat