Skip to content

Odd dependency cycle in CalculatorEngine #563

@janisozaur

Description

@janisozaur

There is an odd dependency in CalcEngine.

CalculatorManager inherits ICalcDisplay and implements a set of virtual calls it exposes, in particular SetPrimaryDisplay.

virtual void SetPrimaryDisplay(const std::wstring& pszText, bool isError) = 0;

When setting a mode in CalculatorManager, e.g.

make_unique<CCalcEngine>(true /* Respect Order of Operations */, true /* Set to Integer Mode */, m_resourceProvider, this, nullptr);

this (here: an instance of CalculatorManager) gets passed as an argument to the newly created CCalcEngine as ICalcDisplay pointer and the engine is stored as unique_ptr member field of CalculatorManager.

In the destructor of CalculatorManager, a single function is called, MemorizedNumberClearAll which then invokes ProcessCommand(IDC_MCLEAR) on current engine, gets passed on to CCalcEngine::ProcessCommandWorker, to DisplayNum, to CCalcEngine::SetPrimaryDisplay and finally to m_pCalcDisplay->SetPrimaryDisplay, but here m_pCalcDisplay was the instance of CalculatorManager that just got its destructor called.

this->MemorizedNumberClearAll();

m_currentCalculatorEngine->ProcessCommand(IDC_MCLEAR);

ProcessCommandWorker(wParam);

DisplayNum(); // Causes 3.000 to shrink to 3. on first op.

SetPrimaryDisplay(GroupDigitsPerRadix(m_numberString, m_radix));

m_pCalcDisplay->SetPrimaryDisplay(szText, isError);

It will likely differ by implementation on how exactly, but the standard suggests that will invoke the pure virtual ICalcDisplay::SetPrimaryDisplay. In case of GCC I believe the vtable is already destroyed by the time you enter dtor's body.

My question is: why is it necessary to call MemorizedNumberClearAll in CalculatorManager::~CalculatorManager()? The calc manager and all its engines are going down anyway, maybe it's ok to just drop that and it should fix the described problem.

Device and Application Information

  • OS Build: 5.0.13.1
Get-AppxPackage : The term 'Get-AppxPackage' is not recognized as the name of a cmdlet, function, script file, or operable program.
Check the spelling of the name, or if a path was included, verify that the path is correct and try again.
At line:1 char:22
+ " - Architecture: $((Get-AppxPackage -Name Microsoft.WindowsCalculato ...
+                      ~~~~~~~~~~~~~~~
+ CategoryInfo          : ObjectNotFound: (Get-AppxPackage:String) [], CommandNotFoundException
+ FullyQualifiedErrorId : CommandNotFoundException
  • Architecture:
Get-AppxPackage : The term 'Get-AppxPackage' is not recognized as the name of a cmdlet, function, script file, or operable program.
Check the spelling of the name, or if a path was included, verify that the path is correct and try again.
At line:1 char:29
+ " - Application Version: $((Get-AppxPackage -Name Microsoft.WindowsCa ...
+                             ~~~~~~~~~~~~~~~
+ CategoryInfo          : ObjectNotFound: (Get-AppxPackage:String) [], CommandNotFoundException
+ FullyQualifiedErrorId : CommandNotFoundException
  • Application Version:
  • Region: pl-PL
Get-AppxPackage : The term 'Get-AppxPackage' is not recognized as the name of a cmdlet, function, script file, or operable program.
Check the spelling of the name, or if a path was included, verify that the path is correct and try again.
At line:1 char:41
+ " - Dev Version Installed: $($null -ne (Get-AppxPackage -Name Microso ...
+                                         ~~~~~~~~~~~~~~~
+ CategoryInfo          : ObjectNotFound: (Get-AppxPackage:String) [], CommandNotFoundException
+ FullyQualifiedErrorId : CommandNotFoundException
  • Dev Version Installed:

Metadata

Metadata

Assignees

No one assigned

    Labels

    approvedcodebase qualityIssues that are not bugs, but still might be worth improving (eg, code hygiene or maintainability)

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions