The invocation to the wallet call forward method failed with the error:
An error happened during the call: 5:
Wasm module of canister xxxxx-xxxxx-xxxxx-xxxxx-xxx is not valid:
Wasm module defined 220 globals which exceeds the maximum number allowed 200.
What do these globals refer to ?
I am trying to figure out where they come from, so I can fix my code.
I am using C++, and I linked in a 3rd party json library that triggered this error.
These arbitrary limits on the system on what should be internals of the canister can and probably should be adjusted. Different CDKs likely produce quite differently looking modules, and I assume the limit was chosen based on canisters in the wild, so mostly Rust and Motoko. If it turns out that C++ tends to use globals more heavily, then hopefully we can get the limit increased quickly.
(Or simply be lifted, as long as the cost of globals is adequately represented in the storage cost for a canister.)
Pinging @diegop , because this should probably trickle into the internal discussions.
One guess may be function pointers across units of compilation. LLVM represents entries in something called Global Offset Table using globals. But my memory is vague and it’s late, so it might be something else.
There is some information in the note at
If you have some form of link-time-optimization that you can enable that might help?
Are these globals mutable or immutable? Ideally the system doesn’t store and thus charge for immutable globals, but I didn’t check.
What I am trying to do is link in a json library. I found a way to use C++ with std::string, so my thinking was that I now can use JSON data by using Candid text → std::string → JSON → do stuff → JSON → std::string → Candid text.
I tried 3 different versions, which all are pretty small & standalone:
I think that I need to stick to lower level C libraries for now, and wrap them myself into Classes that somehow do not generate globals. I am still studying what is generating these globals, but it does seem to be caused by function pointers, traits, virtual things & such…
Im sure you are using WABT already, but if not there a lot of powerful tools for debugging these issues. Here is a wasm2wat online which can be useful: wasm2wat demo
As I know, cargo can not download precompiled packages and compile crates directly on machine.
Nevertheless, you can try using github actions cache between jobs and put cargo caches there. More info about installed crates location
Here is another useful link with a similar problem
(Reposting here from something I vaguely remember saying at the dev tools WG, at @Fulco’s request:)
The issue here is that the things other programs think of as translators from code to binary, like the linker, C++ thinks of as a direct build tool, as integral as rustc. Exported symbols are how other programs perform FFI; they’re how C++ works across files at all. This can result in some surprising behavior in environments that have requirements on things like the number of exported symbols. There is a SO post on the subject of controlling exports which you may find helpful to read - one of those strategies is likely to work in solving your problem.
I’d like to raise this issue again, because another user of C++ CDK recently ran into this limit.
See here, it is related to the ostream operator. They had to strip out a library.
My experience from integrating several libraries is that the ostream is used very, very often to make the library work on a variety of systems. I had to hack just that piece of code, and then it worked.
I haven’t yet seen the limit go above 750, and I wonder if raising it to 1,000 would be a possibility, so many more C++ libraries would just work for the IC
Today I learned about yet another C++ library that compiled fine to Webassembly running in a canister, except that the user had to work around the globals limit.
Would it be possible to start a discussion how this limit can be removed?