Changing a static variable to non-static avoids an exception












1















I am trying to diagnose a crash when calling a VB6 method from C# using COM interop.



The key thing is that defining a static variable referring to the VB6 object causes the crash; but making it non-static avoids the problem. I don't understand this.



This error was sporadic - sometimes occurring, other times not, without any change in inputs, etc.



I have a vague suspicion that this could be related to the VB6 DLL threading model, but very little real evidence for that other than details below. I'm not even sure this is 100% related to COM interop, it just seems likely.





VB6 code for class Calc:



Function CalcSomething(ByVal input as Single)
CalcSomething = ... <some math using 'input'>
End Function

'other functions exist also...


A Calc object has no internal state; it is just a collection of functions.





C# code which would crash:



static class A
{
private static Calc calc1 = new Calc();

public GetCalc() => calc1;
}

...

A.GetCalc.CalcSomething(1234); // CRASH!




C# code which does not crash:



static class A
{
public GetCalc() => new Calc();
}

...

A.GetCalc.CalcSomething(1234); // NO CRASH.




Additional details:



Error:




  • Exception type: System.AccessViolationException

  • Message: "Attempted to read or write protected memory"

  • Source : Interop.CalcDLL (which is the autogenerated COM-callable wrapper)


VB6 DLL:




  • Compiled with the "Apartment Threaded" setting.


  • Class Calc in that DLL is set to GlobalMultiUse instancing.


  • DLL is registered and referenced by the C# project



So although I have a workaround I would really like to understand what the root cause of the problem was, so it can be avoided and/or maybe fixed in a better way.



Thanks for your input!










share|improve this question

























  • Your static version creates one instance of Calc and hands that back to whoever asks for it via GetCalc. The non-static version creates a new instance of Calc every time it's called.

    – Damien_The_Unbeliever
    Nov 21 '18 at 12:44











  • @Damien_The_Unbeliever yes, that is correct.

    – DaveInCaz
    Nov 21 '18 at 12:44











  • I'm working on a C# component that runs on top of a C++ application and all communication is done through COM. We ran into a lot of System.AccessViolationException exceptions when the C# code was running in a background thread and making COM calls. We got around this by using App.Current.Dispatcher.Invoke to do the calls on the main thread. Not sure if this is the same as your issue but thought I would throw it out there.

    – Marc
    Nov 21 '18 at 13:27











  • @Marc thanks... we aren't creating any threads manually but I do suspect that something the default (or maybe "unintentional") threading model is causing this.

    – DaveInCaz
    Dec 3 '18 at 13:16
















1















I am trying to diagnose a crash when calling a VB6 method from C# using COM interop.



The key thing is that defining a static variable referring to the VB6 object causes the crash; but making it non-static avoids the problem. I don't understand this.



This error was sporadic - sometimes occurring, other times not, without any change in inputs, etc.



I have a vague suspicion that this could be related to the VB6 DLL threading model, but very little real evidence for that other than details below. I'm not even sure this is 100% related to COM interop, it just seems likely.





VB6 code for class Calc:



Function CalcSomething(ByVal input as Single)
CalcSomething = ... <some math using 'input'>
End Function

'other functions exist also...


A Calc object has no internal state; it is just a collection of functions.





C# code which would crash:



static class A
{
private static Calc calc1 = new Calc();

public GetCalc() => calc1;
}

...

A.GetCalc.CalcSomething(1234); // CRASH!




C# code which does not crash:



static class A
{
public GetCalc() => new Calc();
}

...

A.GetCalc.CalcSomething(1234); // NO CRASH.




Additional details:



Error:




  • Exception type: System.AccessViolationException

  • Message: "Attempted to read or write protected memory"

  • Source : Interop.CalcDLL (which is the autogenerated COM-callable wrapper)


VB6 DLL:




  • Compiled with the "Apartment Threaded" setting.


  • Class Calc in that DLL is set to GlobalMultiUse instancing.


  • DLL is registered and referenced by the C# project



So although I have a workaround I would really like to understand what the root cause of the problem was, so it can be avoided and/or maybe fixed in a better way.



Thanks for your input!










share|improve this question

























  • Your static version creates one instance of Calc and hands that back to whoever asks for it via GetCalc. The non-static version creates a new instance of Calc every time it's called.

    – Damien_The_Unbeliever
    Nov 21 '18 at 12:44











  • @Damien_The_Unbeliever yes, that is correct.

    – DaveInCaz
    Nov 21 '18 at 12:44











  • I'm working on a C# component that runs on top of a C++ application and all communication is done through COM. We ran into a lot of System.AccessViolationException exceptions when the C# code was running in a background thread and making COM calls. We got around this by using App.Current.Dispatcher.Invoke to do the calls on the main thread. Not sure if this is the same as your issue but thought I would throw it out there.

    – Marc
    Nov 21 '18 at 13:27











  • @Marc thanks... we aren't creating any threads manually but I do suspect that something the default (or maybe "unintentional") threading model is causing this.

    – DaveInCaz
    Dec 3 '18 at 13:16














1












1








1








I am trying to diagnose a crash when calling a VB6 method from C# using COM interop.



The key thing is that defining a static variable referring to the VB6 object causes the crash; but making it non-static avoids the problem. I don't understand this.



This error was sporadic - sometimes occurring, other times not, without any change in inputs, etc.



I have a vague suspicion that this could be related to the VB6 DLL threading model, but very little real evidence for that other than details below. I'm not even sure this is 100% related to COM interop, it just seems likely.





VB6 code for class Calc:



Function CalcSomething(ByVal input as Single)
CalcSomething = ... <some math using 'input'>
End Function

'other functions exist also...


A Calc object has no internal state; it is just a collection of functions.





C# code which would crash:



static class A
{
private static Calc calc1 = new Calc();

public GetCalc() => calc1;
}

...

A.GetCalc.CalcSomething(1234); // CRASH!




C# code which does not crash:



static class A
{
public GetCalc() => new Calc();
}

...

A.GetCalc.CalcSomething(1234); // NO CRASH.




Additional details:



Error:




  • Exception type: System.AccessViolationException

  • Message: "Attempted to read or write protected memory"

  • Source : Interop.CalcDLL (which is the autogenerated COM-callable wrapper)


VB6 DLL:




  • Compiled with the "Apartment Threaded" setting.


  • Class Calc in that DLL is set to GlobalMultiUse instancing.


  • DLL is registered and referenced by the C# project



So although I have a workaround I would really like to understand what the root cause of the problem was, so it can be avoided and/or maybe fixed in a better way.



Thanks for your input!










share|improve this question
















I am trying to diagnose a crash when calling a VB6 method from C# using COM interop.



The key thing is that defining a static variable referring to the VB6 object causes the crash; but making it non-static avoids the problem. I don't understand this.



This error was sporadic - sometimes occurring, other times not, without any change in inputs, etc.



I have a vague suspicion that this could be related to the VB6 DLL threading model, but very little real evidence for that other than details below. I'm not even sure this is 100% related to COM interop, it just seems likely.





VB6 code for class Calc:



Function CalcSomething(ByVal input as Single)
CalcSomething = ... <some math using 'input'>
End Function

'other functions exist also...


A Calc object has no internal state; it is just a collection of functions.





C# code which would crash:



static class A
{
private static Calc calc1 = new Calc();

public GetCalc() => calc1;
}

...

A.GetCalc.CalcSomething(1234); // CRASH!




C# code which does not crash:



static class A
{
public GetCalc() => new Calc();
}

...

A.GetCalc.CalcSomething(1234); // NO CRASH.




Additional details:



Error:




  • Exception type: System.AccessViolationException

  • Message: "Attempted to read or write protected memory"

  • Source : Interop.CalcDLL (which is the autogenerated COM-callable wrapper)


VB6 DLL:




  • Compiled with the "Apartment Threaded" setting.


  • Class Calc in that DLL is set to GlobalMultiUse instancing.


  • DLL is registered and referenced by the C# project



So although I have a workaround I would really like to understand what the root cause of the problem was, so it can be avoided and/or maybe fixed in a better way.



Thanks for your input!







c# vb6 com-interop






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Nov 21 '18 at 12:36







DaveInCaz

















asked Nov 20 '18 at 18:29









DaveInCazDaveInCaz

3,17231837




3,17231837













  • Your static version creates one instance of Calc and hands that back to whoever asks for it via GetCalc. The non-static version creates a new instance of Calc every time it's called.

    – Damien_The_Unbeliever
    Nov 21 '18 at 12:44











  • @Damien_The_Unbeliever yes, that is correct.

    – DaveInCaz
    Nov 21 '18 at 12:44











  • I'm working on a C# component that runs on top of a C++ application and all communication is done through COM. We ran into a lot of System.AccessViolationException exceptions when the C# code was running in a background thread and making COM calls. We got around this by using App.Current.Dispatcher.Invoke to do the calls on the main thread. Not sure if this is the same as your issue but thought I would throw it out there.

    – Marc
    Nov 21 '18 at 13:27











  • @Marc thanks... we aren't creating any threads manually but I do suspect that something the default (or maybe "unintentional") threading model is causing this.

    – DaveInCaz
    Dec 3 '18 at 13:16



















  • Your static version creates one instance of Calc and hands that back to whoever asks for it via GetCalc. The non-static version creates a new instance of Calc every time it's called.

    – Damien_The_Unbeliever
    Nov 21 '18 at 12:44











  • @Damien_The_Unbeliever yes, that is correct.

    – DaveInCaz
    Nov 21 '18 at 12:44











  • I'm working on a C# component that runs on top of a C++ application and all communication is done through COM. We ran into a lot of System.AccessViolationException exceptions when the C# code was running in a background thread and making COM calls. We got around this by using App.Current.Dispatcher.Invoke to do the calls on the main thread. Not sure if this is the same as your issue but thought I would throw it out there.

    – Marc
    Nov 21 '18 at 13:27











  • @Marc thanks... we aren't creating any threads manually but I do suspect that something the default (or maybe "unintentional") threading model is causing this.

    – DaveInCaz
    Dec 3 '18 at 13:16

















Your static version creates one instance of Calc and hands that back to whoever asks for it via GetCalc. The non-static version creates a new instance of Calc every time it's called.

– Damien_The_Unbeliever
Nov 21 '18 at 12:44





Your static version creates one instance of Calc and hands that back to whoever asks for it via GetCalc. The non-static version creates a new instance of Calc every time it's called.

– Damien_The_Unbeliever
Nov 21 '18 at 12:44













@Damien_The_Unbeliever yes, that is correct.

– DaveInCaz
Nov 21 '18 at 12:44





@Damien_The_Unbeliever yes, that is correct.

– DaveInCaz
Nov 21 '18 at 12:44













I'm working on a C# component that runs on top of a C++ application and all communication is done through COM. We ran into a lot of System.AccessViolationException exceptions when the C# code was running in a background thread and making COM calls. We got around this by using App.Current.Dispatcher.Invoke to do the calls on the main thread. Not sure if this is the same as your issue but thought I would throw it out there.

– Marc
Nov 21 '18 at 13:27





I'm working on a C# component that runs on top of a C++ application and all communication is done through COM. We ran into a lot of System.AccessViolationException exceptions when the C# code was running in a background thread and making COM calls. We got around this by using App.Current.Dispatcher.Invoke to do the calls on the main thread. Not sure if this is the same as your issue but thought I would throw it out there.

– Marc
Nov 21 '18 at 13:27













@Marc thanks... we aren't creating any threads manually but I do suspect that something the default (or maybe "unintentional") threading model is causing this.

– DaveInCaz
Dec 3 '18 at 13:16





@Marc thanks... we aren't creating any threads manually but I do suspect that something the default (or maybe "unintentional") threading model is causing this.

– DaveInCaz
Dec 3 '18 at 13:16












0






active

oldest

votes











Your Answer






StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");

StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});

function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});


}
});














draft saved

draft discarded


















StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53399315%2fchanging-a-static-variable-to-non-static-avoids-an-exception%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown

























0






active

oldest

votes








0






active

oldest

votes









active

oldest

votes






active

oldest

votes
















draft saved

draft discarded




















































Thanks for contributing an answer to Stack Overflow!


  • Please be sure to answer the question. Provide details and share your research!

But avoid



  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.


To learn more, see our tips on writing great answers.




draft saved


draft discarded














StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53399315%2fchanging-a-static-variable-to-non-static-avoids-an-exception%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown





















































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown

































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown







Popular posts from this blog

"Incorrect syntax near the keyword 'ON'. (on update cascade, on delete cascade,)

Alcedinidae

Origin of the phrase “under your belt”?