Hi,

I just ran across this post, so I'm not sure if you managed to resolve your 
problem or not, but just in case it is helpful to others:

The problem as described is extremely puzzling...  The only relevant thing 
that createUserCheckinAsync() seems to do is pass in a 
std::shared_ptr<Business>, which really shouldn't affect otherwise valid 
invocations of Business::shared_from_this().  A few ideas:

   - Per cppreference.com 
   
<http://en.cppreference.com/w/cpp/memory/enable_shared_from_this/shared_from_this#Notes>,
 
   wherever Business::shared_from_this() is called, you must ensure that 
   the instance of Business has first been stored in a std::shared_ptr.  
   This includes all instances held in class members and locally scoped 
   variables.  Less obviously, this also includes any code run from the 
   Business constructor.  A good rule of thumb is: If you are using 
   ClassName::shared_from_this(), then no variables or parameters of type "
   ClassName" should appear in your code; they should all be some variation 
   of "std::shared_ptr<ClassName>".  When you say "- createdBusiness: 
   Business", it's not obvious that this is the case -- it really should be "- 
   createdBusiness: std::shared_ptr<Business>".


   - One non-obvious way to create Business instances that are not stored 
   in std::shared_ptrs is to bind the raw constructor in embind, using the "
   .constructor()" method.  If you do this, then invocations of "new 
   Business()" in JavaScript will return JS objects representing raw 
   pointers, not smart pointers.  If you want "new Business()" in 
   JavaScript to instead return objects representing a smart pointer, you 
   should prefer the".smart_ptr_constructor()" method instead.  See this 
   discussion for an example: 
   https://groups.google.com/forum/#!topic/emscripten-discuss/FM-wIqAVc3s


   - Likewise, without seeing the actual content of your classes and how 
   they are bound, I can't rule out the possibility that some method or field 
   access is also returning a raw pointer instead of a smart pointer.  This 
   generally shouldn't happen if you are following the "
   std::shared_ptr<ClassName> everywhere" rule above, though.


   - I am surprised that invoking a method that does nothing can affect 
   subsequent invocations of shared_from_this().  I'd assume that the only 
   way this could happen is if the destruction of the parameter value is 
   destroying the object -- which should only happen if the parameter value is 
   the only std::shared_ptr pointing at the object.  Per your comment, 
   though, I'd assume this would run the destructor, in which you say you have 
   a printf() which is not being hit.  I haven't examined the printf() used 
   by emscripten, but many printf() implementations buffer their output, 
   making it possible to miss output if a crash happens before the buffer gets 
   flushed.  I've therefore gotten in the habit of throwing a "
   fflush(stdout);" at the end of all by printf() debugging lines, which 
   has saved me a lot of trouble.  You might try this to ensure that the 
   printf() output is not simply being lost.  Another technique (which I 
   haven't tried, myself) is to run the JavaScript "debugger;" statement in 
   inline JavaScript ("EM_ASM") in the destructor -- that should pop you 
   into the browser's debugger if it is hit, and may be a little easier than 
   digging through the compiled JavaScript to set a manual breakpoint.


   - If the creation and destruction of the std::shared_ptr parameter is 
   causing the problem, one variation you might try is instead passing the 
   parameter as "const std::shared_ptr<Business>&" .  This also has the 
   benefit of reducing incref/decref traffic, if performance is a concern.


   - It's possible that some memory corruption may be going on somewhere, 
   especially if std::shared_ptr is inadvertently being misused.  Building 
   a small C++-only executable (as you say you have done) is a good step to 
   improve confidence, although actual behavior will vary across 
   compilers/environments.  In particular, the behavior of throwing 
   std::bad_weak_ptr on a bad shared_from_this() invocation is a new 
   requirement of C++17, which clang seems to have picked up early; prior to 
   that, it was simply undefined behavior.  I wouldn't necessarily trust this 
   to be implemented yet in other compilers, or when compiling with exceptions 
   turned off and/or NDEBUG defined.  That said, when tracking down memory 
   bugs, I've found it enormously effective to run small test apps under 
   Valgrind.  It reliably finds out-of-bounds accesses, use-after-frees, 
   uninitialized memory use, and leaks, all at the point they occur -- as 
   opposed to maybe crashing at some point later, if you're lucky.  *Highly* 
   recommended.  Clang also has tools that cover different sets of conditions 
   (asan, tsan, ubsan, etc.); presumably MSVC does, too.


   - As a side note, in your JavaScript snippet it looks like you are not 
   freeing the returned C++ objects.  Again, without seeing your bindings, I 
   can't say for sure, but I'd expect to see a lot more ".delete()"s and/or 
   ".deleteLater()"s if you don't want to leak the returned references.

Hope this helps some,
-- Joe

-- 
You received this message because you are subscribed to the Google Groups 
"emscripten-discuss" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to emscripten-discuss+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to