The International Simutrans Forum

 

Author Topic: Virtual function call  (Read 2806 times)

0 Members and 1 Guest are viewing this topic.

Offline zook2

  • *
  • Posts: 321
Virtual function call
« on: August 13, 2014, 02:50:38 PM »
Not even a crash report popup...

The newest MSVC I seem to have is msvcr100.dll (10.00.40219.1)

Offline jamespetts gb

  • Simutrans-Extended project coordinator
  • Moderator
  • *
  • Posts: 18564
  • Cake baker
    • Bridgewater-Brunel
  • Languages: EN
Re: Virtual function call
« Reply #1 on: August 13, 2014, 09:55:02 PM »
Can you upload a saved game in which this can be reproduced?

Offline zook2

  • *
  • Posts: 321
Re: Virtual function call
« Reply #2 on: August 13, 2014, 10:27:45 PM »
Sorry, it's the first time I've seen it and it hasn't cropped up again. And I wasn't doing anything in the game at the moment; the game window had been in the background.

Offline jamespetts gb

  • Simutrans-Extended project coordinator
  • Moderator
  • *
  • Posts: 18564
  • Cake baker
    • Bridgewater-Brunel
  • Languages: EN
Re: Virtual function call
« Reply #3 on: August 13, 2014, 10:59:56 PM »
Hmm - odd. If you notice any pattern for this occurring or can reproduce it, please let me know; otherwise, I am afraid that I shall not be able to track down the cause of this.

Offline DrSuperGood

  • Dev Team
  • Devotee
  • *
  • Posts: 2639
  • Languages: EN
Re: Virtual function call
« Reply #4 on: August 13, 2014, 11:29:59 PM »
I recall coming across this error being highly specific. Something like it gets generated in 3 main cases.
1. Calling a virtual function in constructors. Some compilers may allow it at certain times such as for members of a parent but mostly it should be avoided as chances are it will not do anything like what you want.
2. Calling a virtual function in destructors. Due to how objects get broken down it is not safe to call virtual functions as what they operate on may no longer be defined as existing.
However these will usually throw compile time errors as it is easy for a compiler to see that the virtual table is not initialized for an object at that stage of construction. This unfortunately leaves the final cause...
3. Calling a virtual function on an object composing of garbage. This can be a result of a dangling reference/pointer where the memory once representing the object was freed and re-allocated to something else leaving garbage for the previous object's virtual function table.

The only really viable way to find the cause of 3 (outside of major time consuming testing of every aspect of the game) is to reproduce the error reliably and run with a debugger.

It may help to explain what you were doing when it crashed. As that would limit the scope where it could be (important for future investigations).

Offline zook2

  • *
  • Posts: 321
Re: Virtual function call
« Reply #5 on: August 14, 2014, 12:53:23 AM »
I had the game running in the background, reading the wikipedia.

Offline Junna

  • Devotee
  • *
  • Posts: 1081
Re: Virtual function call
« Reply #6 on: August 14, 2014, 02:14:26 AM »
What is the reason for the depot message, or was it left over from before you started reading?

Offline zook2

  • *
  • Posts: 321
Re: Virtual function call
« Reply #7 on: August 15, 2014, 05:10:16 AM »
The latter.

Offline prissi

  • Developer
  • Administrator
  • *
  • Posts: 9460
  • Languages: De,EN,JP
Re: Virtual function call
« Reply #8 on: August 19, 2014, 08:56:21 PM »
If you delete something incorrectly, you can have a virtual function.

But mostly likely it is from accessing a dead objects (number 3 above). A short explaination is that many stuff (like trees) are in simutrans' own memory management to have less overhead. Such "deleted" objects cannot cause a unvalid memory access, because that memory still belongs to Simutrans. However, they are most likely reused or partly overwritten and contain garbage.

Offline jamespetts gb

  • Simutrans-Extended project coordinator
  • Moderator
  • *
  • Posts: 18564
  • Cake baker
    • Bridgewater-Brunel
  • Languages: EN
Re: Virtual function call
« Reply #9 on: August 19, 2014, 10:49:06 PM »
If you delete something incorrectly, you can have a virtual function.

But mostly likely it is from accessing a dead objects (number 3 above). A short explaination is that many stuff (like trees) are in simutrans' own memory management to have less overhead. Such "deleted" objects cannot cause a unvalid memory access, because that memory still belongs to Simutrans. However, they are most likely reused or partly overwritten and contain garbage.

Thank you; this is helpful. I wonder whether it would be helpful to have a debugging preprocessor definition to disable the internal memory management system (and use actual new/delete calls) that can be invoked when looking for issues such as these?

Offline prissi

  • Developer
  • Administrator
  • *
  • Posts: 9460
  • Languages: De,EN,JP
Re: Virtual function call
« Reply #10 on: August 20, 2014, 11:37:17 PM »
There is a heap only debugger. But the OS can handle only pages of 4 kB, i.e. any object in Simutrans would use 4 kB. I tried this once but it seems Windows has less handles for those pages than Simutrans needs.

There is however a valgrind switch to compile which make valgrind aware of the freelist memory module. DrMemory hooks into the std memory allocation routines on windows, so it can be made aware too. You can easily change freelist to call malloc and free, but then do not complain when opening a map takes about 5-6 times longer ...

Offline jamespetts gb

  • Simutrans-Extended project coordinator
  • Moderator
  • *
  • Posts: 18564
  • Cake baker
    • Bridgewater-Brunel
  • Languages: EN
Re: Virtual function call
« Reply #11 on: August 20, 2014, 11:52:49 PM »
There is a heap only debugger. But the OS can handle only pages of 4 kB, i.e. any object in Simutrans would use 4 kB. I tried this once but it seems Windows has less handles for those pages than Simutrans needs.

There is however a valgrind switch to compile which make valgrind aware of the freelist memory module. DrMemory hooks into the std memory allocation routines on windows, so it can be made aware too. You can easily change freelist to call malloc and free, but then do not complain when opening a map takes about 5-6 times longer ...

Ahh, that Valgrind switch sounds helpful. How does one invoke it?

Offline zook2

  • *
  • Posts: 321
Re: Virtual function call
« Reply #12 on: August 21, 2014, 04:29:09 PM »
Just a wild and uninformed guess here: could the problem be connected to industries closing down ? Because it crashed while I hadn't done anything myself in the game for a while and a closure happens very rarely, while other objects get destroyed all the time.

Offline jamespetts gb

  • Simutrans-Extended project coordinator
  • Moderator
  • *
  • Posts: 18564
  • Cake baker
    • Bridgewater-Brunel
  • Languages: EN
Re: Virtual function call
« Reply #13 on: August 21, 2014, 08:17:00 PM »
That's certainly possible, Zoosk2: closing industries involves deleting objects, and this error can be associated with things going wrong when objects are deleted, so this may well be a useful clue: thank you.

Offline prissi

  • Developer
  • Administrator
  • *
  • Posts: 9460
  • Languages: De,EN,JP
Re: Virtual function call
« Reply #14 on: August 21, 2014, 10:11:03 PM »
To use malloc/free:

remove freelist.cc from the project

change freelest.h to
Code: [Select]
#ifndef freelist_t_h
#define freelist_t_h

/**
 * Helper class to organize small memory objects i.e. nodes for linked lists
 * and such.
 *
 * @author Hanjsj√∂rg Malthaner
 */
class freelist_t
{
public:
static void *gimme_node( size_t size ) { return calloc(size,1); }
static void putback_node( size_t, void *p ) { free(p); }

// clears all list memories
static void free_all_nodes() {}
};

#endif
should do the trick.

Offline jamespetts gb

  • Simutrans-Extended project coordinator
  • Moderator
  • *
  • Posts: 18564
  • Cake baker
    • Bridgewater-Brunel
  • Languages: EN
Re: Virtual function call
« Reply #15 on: August 21, 2014, 10:17:52 PM »
Splendid - thank you. That can easily be done with preprocessor directives, I think.