Why does Emscripten throw errors for some number added to an allocated Float32Array?

183 views Asked by At

Update:

This has been resolved ↓, but I couldn't accept my own answer immediately.


I am learning how to pass TypeArrays between JavaScript and "C++" compiled using Emscripten. In this process I ran into an error I don't know what to make of.

This is the basically what I'm doing:

let bufferLength = 32
let ptr = Module._malloc(bufferLength)
let buf = new Float32Array(Module.HEAPF32.buffer, ptr, bufferLength)

for (let i = 0; i < bufferLength; i++) {
  // The multiplier (here 1.234) sometimes causes an error,
  // and sometimes it doesn't
  buf[i] = i * 1.234
}

// Here is where the error is thrown and Module._abort()
// is invoked
Module._free(ptr)

I have set up a repo where this is reproducable: https://github.com/alexanderwallin/emcc-f32-buffer-error. The repo tests the multipliers [1.1, 1.2, 1.3, 1.4], where 1.1 and 1.4 causes errors.

Module in this case is an empty C file compiled using emcc -o empty.js empty.c.

This is the console output:

- - - - - - - 

f32-ptr-tests.js:24 testing multiplier: 1.1
f32-ptr-tests.js:34 ... did fill array
f32-ptr-tests.js:41 oh nose!
f32-ptr-tests.js:42 abort() at Error
    at jsStackTrace (file:///path/to/emcc-f32-ptr-error/empty.js:1173:13)
    at stackTrace (file:///path/to/emcc-f32-ptr-error/empty.js:1190:22)
    at Object.abort (file:///path/to/emcc-f32-ptr-error/empty.js:9814:44)
    at _abort (file:///path/to/emcc-f32-ptr-error/empty.js:1796:22)
    at _free (file:///path/to/emcc-f32-ptr-error/empty.js:8998:3)
    at Object.asm._free (file:///path/to/emcc-f32-ptr-error/empty.js:9602:19)
    at file:///path/to/emcc-f32-ptr-error/f32-ptr-tests.js:36:12
(anonymous) @ f32-ptr-tests.js:42
f32-ptr-tests.js:45 


f32-ptr-tests.js:23 - - - - - - - 

f32-ptr-tests.js:24 testing multiplier: 1.2
f32-ptr-tests.js:34 ... did fill array
f32-ptr-tests.js:38 all good
f32-ptr-tests.js:45 


f32-ptr-tests.js:23 - - - - - - - 

f32-ptr-tests.js:24 testing multiplier: 1.3
f32-ptr-tests.js:34 ... did fill array
f32-ptr-tests.js:38 all good
f32-ptr-tests.js:45 


f32-ptr-tests.js:23 - - - - - - - 

f32-ptr-tests.js:24 testing multiplier: 1.4
f32-ptr-tests.js:34 ... did fill array
f32-ptr-tests.js:41 oh nose!
f32-ptr-tests.js:42 abort() at Error
    at jsStackTrace (file:///path/to/emcc-f32-ptr-error/empty.js:1173:13)
    at stackTrace (file:///path/to/emcc-f32-ptr-error/empty.js:1190:22)
    at Object.abort (file:///path/to/emcc-f32-ptr-error/empty.js:9814:44)
    at _abort (file:///path/to/emcc-f32-ptr-error/empty.js:1796:22)
    at _free (file:///path/to/emcc-f32-ptr-error/empty.js:8998:3)
    at Object.asm._free (file:///path/to/emcc-f32-ptr-error/empty.js:9602:19)
    at file:///path/to/emcc-f32-ptr-error/f32-ptr-tests.js:36:12

What is happening here?

1

There are 1 answers

0
Alexander Wallin On BEST ANSWER

This was a nice 101 memory management lesson.

I am allocating 32 bytes, but since a Float32Array contain 32-bit (4 byte) numbers, I only allocate 25% of the memory I need. This means that when I write numbers to the last 3 quarters of the array, I overwrite memory somewhere else in the application, which sometimes causes an error and sometimes not.

So, changing

let ptr = Module._malloc(bufferLength)

to

let ptr = Module._malloc(bufferLength * Float32Array.BYTES_PER_ELEMENT)

does the trick.