While checking #16661 I stumbled upon what seems to be a lifetime issue in `ReleaseWallet(CWallet* wallet)` (`wallet.cpp`).

https://github.com/bitcoin/bitcoin/blob/fa6431055abfacea4f72ef11d061c7c755de327a/src/wallet/wallet.cpp#L107-L111

After `delete wallet;` the pointer is invalid and shouldn't be used like in the call `g_unloading_wallet_set.erase(wallet)`.

The code was introduced in #14941 which was merged into `master` on January 15, 2019.

In addition to fixing this specific instance it might be worth thinking about how we can use static analysis to automatically catch this class of issues going forward :-)
if (nLoadWalletRet == DBErrors::CORRUPT) {
            chain.initError(strprintf(_("Error loading %s: Wallet corrupted").translated, walletFile));
            return nullptr;
        }
        else if (nLoadWalletRet == DBErrors::NONCRITICAL_ERROR)
        {
            chain.initWarning(strprintf(_("Error reading %s! All keys read correctly, but transaction data"
                                          " or address book entries might be missing or incorrect.").translated,
                walletFile));
        }
        else if (nLoadWalletRet == DBErrors::TOO_NEW) {
            chain.initError(strprintf(_("Error loading %s: Wallet requires newer version of %s").translated, walletFile, PACKAGE_NAME));
            return nullptr;
        }
        else if (nLoadWalletRet == DBErrors::NEED_REWRITE)
        {
            chain.initError(strprintf(_("Wallet needed to be rewritten: restart %s to complete").translated, PACKAGE_NAME));
            return nullptr;
        }
        else {
            chain.initError(strprintf(_("Error loading %s").translated, walletFile));
            return nullptr;
        }
    }
    int prev_version = walletInstance->GetVersion();
    if (gArgs.GetBoolArg("-upgradewallet", fFirstRun))
    {
        int nMaxVersion = gArgs.GetArg("-upgradewallet", 0);
        if (nMaxVersion == 0) 
        {