access violation inside ADODB recordset Close
.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty{ height:90px;width:728px;box-sizing:border-box;
}
Still trying to figure out what is happening with ADODB's connections and why a certain crash is occuring.
The problem was that we had a memory leak in our code:
void getDetailConfig()
{
m_displayConf = new TestDetailDisplayCfg();
}
This function is called often so a basic memory leak.
Fixed it with a unique pointer
void getDetailConfig()
{
m_displayConf = std::make_unique<TestDetailDisplayCfg>();
}
Yay party, but now an acces violation started to happen inside ADODB's Recordset15::Close.
inline HRESULT Recordset15::Close ( ) {
HRESULT _hr = raw_Close();
if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));
return _hr;
}
Unhandled exception at 0x679E653F (msado15.dll) in LaneControl.exe:
0xC000041D: An unhandled exception was encountered during a user
callback.
So calling all destructors the right way caused a new issue, there are recordset's opened and closed somewhere.
After debugging it turns out that getDetailConfig is called from two different threads.
Thread1
void updateIconStatus()
{
getDetailConfig();
}
Thread ID 5bA8
Thread2
void CVTSDetailDisplay::setCurrentTestIconStatus(int status)
{
m_CurrentDialog->getDetailConfig();
}
Thread ID 6A4C
So these 2 threads call getDetailConfig where a recordset is closed which was opened on another thread and COM objects are Released and what not.
Is that a problem that you can't close ADO recordsets on another thread? Is it more a race condition?
What is going wrong here at ADODB's level?
c++ com ado
add a comment |
Still trying to figure out what is happening with ADODB's connections and why a certain crash is occuring.
The problem was that we had a memory leak in our code:
void getDetailConfig()
{
m_displayConf = new TestDetailDisplayCfg();
}
This function is called often so a basic memory leak.
Fixed it with a unique pointer
void getDetailConfig()
{
m_displayConf = std::make_unique<TestDetailDisplayCfg>();
}
Yay party, but now an acces violation started to happen inside ADODB's Recordset15::Close.
inline HRESULT Recordset15::Close ( ) {
HRESULT _hr = raw_Close();
if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));
return _hr;
}
Unhandled exception at 0x679E653F (msado15.dll) in LaneControl.exe:
0xC000041D: An unhandled exception was encountered during a user
callback.
So calling all destructors the right way caused a new issue, there are recordset's opened and closed somewhere.
After debugging it turns out that getDetailConfig is called from two different threads.
Thread1
void updateIconStatus()
{
getDetailConfig();
}
Thread ID 5bA8
Thread2
void CVTSDetailDisplay::setCurrentTestIconStatus(int status)
{
m_CurrentDialog->getDetailConfig();
}
Thread ID 6A4C
So these 2 threads call getDetailConfig where a recordset is closed which was opened on another thread and COM objects are Released and what not.
Is that a problem that you can't close ADO recordsets on another thread? Is it more a race condition?
What is going wrong here at ADODB's level?
c++ com ado
0xC000041D does not actually have that much to do with ADODB. It can occur in a 32-bit app that runs on a 64-bit version of Windows. There was another exception before this one that got thrown in a windows message handler (aka WndProc, aka "user callback"). Such an exception is quite difficult to handle correctly since the callback started in the 64-bit window manager and it can't unwind the stack properly through these layers. Focus on seeing that first mishap, that's where it started to fall apart. Force the debugger to stop on the "first chance exception"
– Hans Passant
Nov 23 '18 at 14:20
Fwiw, ADODB is not thread-safe. You have to marshal the interface pointer, typically most easily done this way.
– Hans Passant
Nov 23 '18 at 14:22
I would basically think that the object has been tried to be released twice (for the reason described in my answer), AKA "double-delete", so the second release indeed failed as the object was already no longer valid. And indeed, possible non-thread-safety of ADODB (which I don't know much about) can only add another injury to that.
– axalis
Nov 23 '18 at 14:23
add a comment |
Still trying to figure out what is happening with ADODB's connections and why a certain crash is occuring.
The problem was that we had a memory leak in our code:
void getDetailConfig()
{
m_displayConf = new TestDetailDisplayCfg();
}
This function is called often so a basic memory leak.
Fixed it with a unique pointer
void getDetailConfig()
{
m_displayConf = std::make_unique<TestDetailDisplayCfg>();
}
Yay party, but now an acces violation started to happen inside ADODB's Recordset15::Close.
inline HRESULT Recordset15::Close ( ) {
HRESULT _hr = raw_Close();
if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));
return _hr;
}
Unhandled exception at 0x679E653F (msado15.dll) in LaneControl.exe:
0xC000041D: An unhandled exception was encountered during a user
callback.
So calling all destructors the right way caused a new issue, there are recordset's opened and closed somewhere.
After debugging it turns out that getDetailConfig is called from two different threads.
Thread1
void updateIconStatus()
{
getDetailConfig();
}
Thread ID 5bA8
Thread2
void CVTSDetailDisplay::setCurrentTestIconStatus(int status)
{
m_CurrentDialog->getDetailConfig();
}
Thread ID 6A4C
So these 2 threads call getDetailConfig where a recordset is closed which was opened on another thread and COM objects are Released and what not.
Is that a problem that you can't close ADO recordsets on another thread? Is it more a race condition?
What is going wrong here at ADODB's level?
c++ com ado
Still trying to figure out what is happening with ADODB's connections and why a certain crash is occuring.
The problem was that we had a memory leak in our code:
void getDetailConfig()
{
m_displayConf = new TestDetailDisplayCfg();
}
This function is called often so a basic memory leak.
Fixed it with a unique pointer
void getDetailConfig()
{
m_displayConf = std::make_unique<TestDetailDisplayCfg>();
}
Yay party, but now an acces violation started to happen inside ADODB's Recordset15::Close.
inline HRESULT Recordset15::Close ( ) {
HRESULT _hr = raw_Close();
if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));
return _hr;
}
Unhandled exception at 0x679E653F (msado15.dll) in LaneControl.exe:
0xC000041D: An unhandled exception was encountered during a user
callback.
So calling all destructors the right way caused a new issue, there are recordset's opened and closed somewhere.
After debugging it turns out that getDetailConfig is called from two different threads.
Thread1
void updateIconStatus()
{
getDetailConfig();
}
Thread ID 5bA8
Thread2
void CVTSDetailDisplay::setCurrentTestIconStatus(int status)
{
m_CurrentDialog->getDetailConfig();
}
Thread ID 6A4C
So these 2 threads call getDetailConfig where a recordset is closed which was opened on another thread and COM objects are Released and what not.
Is that a problem that you can't close ADO recordsets on another thread? Is it more a race condition?
What is going wrong here at ADODB's level?
c++ com ado
c++ com ado
asked Nov 23 '18 at 13:47
Serve LaurijssenServe Laurijssen
5,57042354
5,57042354
0xC000041D does not actually have that much to do with ADODB. It can occur in a 32-bit app that runs on a 64-bit version of Windows. There was another exception before this one that got thrown in a windows message handler (aka WndProc, aka "user callback"). Such an exception is quite difficult to handle correctly since the callback started in the 64-bit window manager and it can't unwind the stack properly through these layers. Focus on seeing that first mishap, that's where it started to fall apart. Force the debugger to stop on the "first chance exception"
– Hans Passant
Nov 23 '18 at 14:20
Fwiw, ADODB is not thread-safe. You have to marshal the interface pointer, typically most easily done this way.
– Hans Passant
Nov 23 '18 at 14:22
I would basically think that the object has been tried to be released twice (for the reason described in my answer), AKA "double-delete", so the second release indeed failed as the object was already no longer valid. And indeed, possible non-thread-safety of ADODB (which I don't know much about) can only add another injury to that.
– axalis
Nov 23 '18 at 14:23
add a comment |
0xC000041D does not actually have that much to do with ADODB. It can occur in a 32-bit app that runs on a 64-bit version of Windows. There was another exception before this one that got thrown in a windows message handler (aka WndProc, aka "user callback"). Such an exception is quite difficult to handle correctly since the callback started in the 64-bit window manager and it can't unwind the stack properly through these layers. Focus on seeing that first mishap, that's where it started to fall apart. Force the debugger to stop on the "first chance exception"
– Hans Passant
Nov 23 '18 at 14:20
Fwiw, ADODB is not thread-safe. You have to marshal the interface pointer, typically most easily done this way.
– Hans Passant
Nov 23 '18 at 14:22
I would basically think that the object has been tried to be released twice (for the reason described in my answer), AKA "double-delete", so the second release indeed failed as the object was already no longer valid. And indeed, possible non-thread-safety of ADODB (which I don't know much about) can only add another injury to that.
– axalis
Nov 23 '18 at 14:23
0xC000041D does not actually have that much to do with ADODB. It can occur in a 32-bit app that runs on a 64-bit version of Windows. There was another exception before this one that got thrown in a windows message handler (aka WndProc, aka "user callback"). Such an exception is quite difficult to handle correctly since the callback started in the 64-bit window manager and it can't unwind the stack properly through these layers. Focus on seeing that first mishap, that's where it started to fall apart. Force the debugger to stop on the "first chance exception"
– Hans Passant
Nov 23 '18 at 14:20
0xC000041D does not actually have that much to do with ADODB. It can occur in a 32-bit app that runs on a 64-bit version of Windows. There was another exception before this one that got thrown in a windows message handler (aka WndProc, aka "user callback"). Such an exception is quite difficult to handle correctly since the callback started in the 64-bit window manager and it can't unwind the stack properly through these layers. Focus on seeing that first mishap, that's where it started to fall apart. Force the debugger to stop on the "first chance exception"
– Hans Passant
Nov 23 '18 at 14:20
Fwiw, ADODB is not thread-safe. You have to marshal the interface pointer, typically most easily done this way.
– Hans Passant
Nov 23 '18 at 14:22
Fwiw, ADODB is not thread-safe. You have to marshal the interface pointer, typically most easily done this way.
– Hans Passant
Nov 23 '18 at 14:22
I would basically think that the object has been tried to be released twice (for the reason described in my answer), AKA "double-delete", so the second release indeed failed as the object was already no longer valid. And indeed, possible non-thread-safety of ADODB (which I don't know much about) can only add another injury to that.
– axalis
Nov 23 '18 at 14:23
I would basically think that the object has been tried to be released twice (for the reason described in my answer), AKA "double-delete", so the second release indeed failed as the object was already no longer valid. And indeed, possible non-thread-safety of ADODB (which I don't know much about) can only add another injury to that.
– axalis
Nov 23 '18 at 14:23
add a comment |
1 Answer
1
active
oldest
votes
I'd think it is a race condition.
If the getDetailConfig()
function was already called before, and then both threads call the getDetailConfig()
, this can result in both threads calling the destructor (of the object which was there before) simultaneously (std::unique_ptr
is not inherently thread-safe AFAIK).
You'd then need to ensure critical section for the exchange of the pointers, for example adding std::mutex m_mutex;
as a member of your class (ideally to the first place in the members list so it remains valid longer than the m_displayConf
member) and then adding
void getDetailConfig()
{
std::unique_lock<std::mutex> lock(m_mutex);
m_displayConf = std::make_unique<TestDetailDisplayCfg>();
}
to make sure the exchange is locked between threads.
add a comment |
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
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53447900%2faccess-violation-inside-adodb-recordset-close%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
I'd think it is a race condition.
If the getDetailConfig()
function was already called before, and then both threads call the getDetailConfig()
, this can result in both threads calling the destructor (of the object which was there before) simultaneously (std::unique_ptr
is not inherently thread-safe AFAIK).
You'd then need to ensure critical section for the exchange of the pointers, for example adding std::mutex m_mutex;
as a member of your class (ideally to the first place in the members list so it remains valid longer than the m_displayConf
member) and then adding
void getDetailConfig()
{
std::unique_lock<std::mutex> lock(m_mutex);
m_displayConf = std::make_unique<TestDetailDisplayCfg>();
}
to make sure the exchange is locked between threads.
add a comment |
I'd think it is a race condition.
If the getDetailConfig()
function was already called before, and then both threads call the getDetailConfig()
, this can result in both threads calling the destructor (of the object which was there before) simultaneously (std::unique_ptr
is not inherently thread-safe AFAIK).
You'd then need to ensure critical section for the exchange of the pointers, for example adding std::mutex m_mutex;
as a member of your class (ideally to the first place in the members list so it remains valid longer than the m_displayConf
member) and then adding
void getDetailConfig()
{
std::unique_lock<std::mutex> lock(m_mutex);
m_displayConf = std::make_unique<TestDetailDisplayCfg>();
}
to make sure the exchange is locked between threads.
add a comment |
I'd think it is a race condition.
If the getDetailConfig()
function was already called before, and then both threads call the getDetailConfig()
, this can result in both threads calling the destructor (of the object which was there before) simultaneously (std::unique_ptr
is not inherently thread-safe AFAIK).
You'd then need to ensure critical section for the exchange of the pointers, for example adding std::mutex m_mutex;
as a member of your class (ideally to the first place in the members list so it remains valid longer than the m_displayConf
member) and then adding
void getDetailConfig()
{
std::unique_lock<std::mutex> lock(m_mutex);
m_displayConf = std::make_unique<TestDetailDisplayCfg>();
}
to make sure the exchange is locked between threads.
I'd think it is a race condition.
If the getDetailConfig()
function was already called before, and then both threads call the getDetailConfig()
, this can result in both threads calling the destructor (of the object which was there before) simultaneously (std::unique_ptr
is not inherently thread-safe AFAIK).
You'd then need to ensure critical section for the exchange of the pointers, for example adding std::mutex m_mutex;
as a member of your class (ideally to the first place in the members list so it remains valid longer than the m_displayConf
member) and then adding
void getDetailConfig()
{
std::unique_lock<std::mutex> lock(m_mutex);
m_displayConf = std::make_unique<TestDetailDisplayCfg>();
}
to make sure the exchange is locked between threads.
edited Nov 23 '18 at 14:15
answered Nov 23 '18 at 14:10
axalisaxalis
4,7751113
4,7751113
add a comment |
add a comment |
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.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53447900%2faccess-violation-inside-adodb-recordset-close%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
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
0xC000041D does not actually have that much to do with ADODB. It can occur in a 32-bit app that runs on a 64-bit version of Windows. There was another exception before this one that got thrown in a windows message handler (aka WndProc, aka "user callback"). Such an exception is quite difficult to handle correctly since the callback started in the 64-bit window manager and it can't unwind the stack properly through these layers. Focus on seeing that first mishap, that's where it started to fall apart. Force the debugger to stop on the "first chance exception"
– Hans Passant
Nov 23 '18 at 14:20
Fwiw, ADODB is not thread-safe. You have to marshal the interface pointer, typically most easily done this way.
– Hans Passant
Nov 23 '18 at 14:22
I would basically think that the object has been tried to be released twice (for the reason described in my answer), AKA "double-delete", so the second release indeed failed as the object was already no longer valid. And indeed, possible non-thread-safety of ADODB (which I don't know much about) can only add another injury to that.
– axalis
Nov 23 '18 at 14:23