ESP8266 malloc/calloc-related crashes ("segfaults") This is sort of the continuation of this problem. After getting hints that the problem I had were related to bad memory, I checked all of my heap-allocating code again and found a malloc that didn't allocate enough memory for an array. After fixing that and fiddling around with calloc, which may be safer for array-related stuff, I think I exposed the actual programming errors themselves. The crash message I get now is:
No poison after block at: 0x3fff0fb8, actual data: 0x84 0xf 0xff 0x3f

User exception (panic/abort/assert)
Panic umm_malloc.cpp:422 umm_malloc_core

which sounds to me like some sort of ESP segfault. The code where this happens according to the stack trace is the following:
Menu* createMenuStructure(ace_time::TimeZone* mainTZ) {
  // create an array of all clock faces, i.e. a pointer to an array of function pointers
  void (**allClockFaces)(T_DISPLAY*, ace_time::ZonedDateTime*);
  // funkiest malloc in the world; undefined behavior? I hope not.
  allClockFaces = (void (**)(T_DISPLAY*, ace_time::ZonedDateTime*)) calloc(DESIGN_MENU_SIZE, sizeof(*allClockFaces));
  // initialize array
  allClockFaces[0] = &amp;basicDigitalCF;
  allClockFaces[1] = &amp;digitalWithSecondsCF;
  allClockFaces[2] = &amp;basicAnalogCF;
  allClockFaces[3] = &amp;binaryCF;
  allClockFaces[4] = &amp;fullDayBinaryCF;
  ClockFaceSelectMenu* cfMenu = (ClockFaceSelectMenu*) malloc(sizeof(ClockFaceSelectMenu));
  cfMenu = new ClockFaceSelectMenu((char**)design_menu, (size_t)DESIGN_MENU_SIZE, allClockFaces);

  // time zone select menu
  TimeZoneSelectMenu* tzMenu = (TimeZoneSelectMenu*) malloc(sizeof(TimeZoneSelectMenu));
  tzMenu = new TimeZoneSelectMenu();

  Menu** allMenus = (Menu**) calloc(3, sizeof(*allMenus));
  // initialize first layer of sub menus
  allMenus[0] = cfMenu;
  allMenus[3] = tzMenu;
  
  OptionsMenu* mainMenu = (OptionsMenu*) malloc(sizeof(OptionsMenu));
  mainMenu = new OptionsMenu((char**)main_menu, (size_t)MAIN_MENU_SIZE, allMenus);
  
  // for now, manually set the sub menu's parent to the main menu. When all menus are finished, the main menu will do this automatically
  allMenus[0]-&gt;parent = mainMenu;
  allMenus[3]-&gt;parent = mainMenu;
  
  ClockMenu* clk = (ClockMenu*) malloc(sizeof(ClockMenu));
  // timeClient is a global NTPClient variable
  clk = new ClockMenu(&amp;timeClient, mainTZ, (Menu*)mainMenu);
  
  return clk;
}

All names containing Menu are classes derived from that base class, and the top couple of lines allocate an array of function pointers. And just to be clear: This code was working perfectly fine for the last several days of development until I made some changes to the SD card functionality that caused the constant crashes.
I am not very used to working in manual memory management. Is this way of allocating appropriate, and if so, correct? What am I doing wrong, or does the error lie somewhere else in the (~1500sloc) project?
Edit: Although the issue is already solved, thanks to the approved answer, I wanted to clarify that the constants used in the array allocation are all correct and correspond to the string array's length. E.g. main_menu is a string array of length 5 and MAIN_MENU_SIZE is a constant defined right next to the array definition that is also defined to 5. This is of course necessary as C arrays have no way (that I know of) of finding the length of complex pointer arrays such as these.
You wrote:

// funkiest malloc in the world


Funky, indeed. ;-) I kind of like its twisted beauty, but not everyone
does. Some may urge you to typedef that function type.

allClockFaces[4] = &amp;fullDayBinaryCF;


Are you sure DESIGN_MENU_SIZE is strictly larger than 4? Maybe an
assert() would be good to use here.

ClockFaceSelectMenu* cfMenu = (ClockFaceSelectMenu*) malloc(...);
cfMenu = new ClockFaceSelectMenu(...);


You are assigning a value to cfMenu twice in a row, which means the
value assigned first is lost. This is a memory leak. You do not need
malloc() here, as new takes care of the memory allocation prior to
initializing the object. This error is repeated several times in this
function.

allMenus[3] = tzMenu;


allMenus has length 3: valid indices range from 0 to 2. This is an
out-of-bounds array access, and the likely cause of the errors you see.