VC6 to VS2013 MFC Runtime Error - c++

I am trying to upgrade a legacy product from VC6 to VS2013 using toolset 12_xp. I can get the project to compile just fine however I am getting a runtime ASSERT and it seems related to CSingleLock lock() call.
CSingleLock slock(&CV7CmnSS::m_cs); // Wait for access
slock.Lock(m_dwTimeout); // <- this is the line that does it.
CV7CmnSS::m_cs is declared as a static object in a different class in another dll refrenced by this project.
the exe's header file has this CCriticalSection CV7CmnSS::m_cs;
as declared in CV7CmnSS header file static CCriticalSection m_cs;
I try to step through the MFC code (I know, i know...)
this is about all the further I can get...
mfc120d.dll!CCriticalSection::Lock(unsigned long dwTimeout) Line 118 C++ //<-- from the call stack window
_AFXMT_INLINE BOOL (::CCriticalSection::Lock(DWORD dwTimeout))
{
ASSERT(dwTimeout == INFINITE);
(void)dwTimeout;
return Lock();
}
the assert I box i get:
fairly generic..
Both the dll project are targeting the same toolset, 12_xp, both use MBCS, both are using MFC as a shared dll. Both are using Multithreaded debug dll setting.
I suspect a cross threading issue? But I am not sure how to proceed.
If there is anymore info I can provide please let me know.
EDIT:
I forgot to add this little gem, if I run the program in release without debugging I am able to get a little further with the app, however this strange message pops up....

The code you showed reveals the problem: there's an assert that requires the dwTimeout parameter to be INFINITE. As you can see from the code, and as mentioned in the CCriticalSection::Lock documentation, that parameter is ignored, so you can just change the code to pass INFINITE as the parameter, or just call the overload that takes no parameters (which does the same thing).
As for why the error doesn't happen in release mode, it's because asserts are only compiled in debug mode, so the assert never happens. Whatever is causing that message box is completely unrelated to the assert.

Related

Visual Studio C++ Console Application Won't Run

What can be done when a C++ console application builds and launches but won't run any code, at least not any that the debugger can see? I have a program with a main function:
int main (int argc, char *argv[])
{
short retval = 0;
retval = samain ( (short) argc, argv);
return ((int) retval);
}
I put a breakpoint on the first line (retval=0) and the line after it just to be safe, and run. It shows a console window and hangs until I stop the debugger. The debug output shows a number of DLLs being loaded but nothing else. It ends with this line that looks very similar to the dozens before it:
'fcmtsysmd.exe' (Win32): Loaded 'C:\Windows\SysWOW64\RpcRtRemote.dll'. Cannot find or open the PDB file.
This is a program I know runs and functions in a "normal" environment because hundreds of people are using it and I haven't changed the code. The things different in my environment (because I'm in the process of rewriting our installation process) are:
I might not have all the dependencies installed properly.
One of the DLL dependencies that was causing an error earlier has been replaced by a newly built version with an Isolated COM reference instead of its usual COM reference because the COM object it was trying to access is not registered. (I'm trying to implement isolated COM in our new installation.)
So my question is, if an error is occurring before the first line of code executed, how can I track down the source of the problem?
I can't get a sensible call stack because even if I single step (F10 key) to start the program, it's hung right away. If I break at that point, I see the following call stack:
ntdll.dll!7743fdd1() Unknown
[Frames below may be incorrect and/or missing, no symbols loaded for ntdll.dll]
ntdll.dll!7743fdd1() Unknown
ntdll.dll!77475f86() Unknown
ntdll.dll!77459809() Unknown
When I remove the isolated COM settings from the dependent DLL, I can get a access violation exception and stop on some code in the debugger. It's stopped on a function being called during the initialization of a static variable in another DLL. The strange thing is, when I add the isolated COM settings to the first DLL, and put a breakpoint on the other DLL, the breakpoint doesn't even get hit.
It turns out that the application was hanging during a call to CoCreateInstance triggered by some static initialization logic in one of the dependent DLLs. I guess the trick is trying to identify static initialization logic in dependent DLLs and putting breakpoints there. Unfortunately there doesn't appear to be any debug output to help identify which DLL's static initialization is executing when, so it's impossible to tell which DLL is the problem.
I will ask about how to identify the source of a hanging CoCreateInstance call in a separate question if there isn't already a question covering it: Application hung during CoCreateInstance when using Isolated COM
The final answer ended up being at https://stackoverflow.com/a/34076433/78162 (which I had to create myself).

CEF crashes when calling functions in a particular DLL

I have an MSVC project, this project consists of multiple DLLs called from an executable. One of these DLLs initializes CEF (Chromium Embedded Framework) and another provides some other general functionality, We'll call them cefDLL and generalDLL. The calls go like this:
All the calls are done from the executable.
I call functions in the cefDLL to initialize CEF.
I call functions the second generalDLL.
Some thread internally in CEF crashes with a Windows error popup reporting "The application was unable to start correct (0xc0000124). Click OK to close the application.".
A Windows popup appears declaring Application.exe has stopped working.
The main thread continues running even if I close the program on the "has stopped working" popup.
If I try to run the debugger on the crashed program I get a blank Visual Studio, no call stack, no locals, nothing, not even the name of a failed DLL.
If I call a function from another DLL, a function from the executable itself or none at all, the code reaches my infinite loop just fine (I'm using an infinite loop to stop the rest of the program from running).
If I let it keep running into the rest of the program and don't stop it with an infinite loop two more threads in CEF crash for a total of three crashed threads. These produce exactly the same errors as the first thread. I'm not sure what causes this precisely as I haven't had the time to look into this yet.
Even if the functions called in generalDLL do absolutely nothing this still occurs. I am certain it is the act of calling them that causes this, if my code is
initializeCEF();
while (true)
{
}
it works, if the code is
initializeCEF();
someBlankFunctionInGeneralDLL();
while (true)
{
}
the thread crashes.
The initialization of CEF consists of this:
//Initialize
CefMainArgs mainArgs;
//Launch Threads
CefExecuteProcess(mainArgs, nullptr, nullptr);
//Settings
CefSettings settings;
settings.pack_loading_disabled = true;
settings.windowless_rendering_enabled = true;
settings.multi_threaded_message_loop = false;
settings.no_sandbox = true;
//Sandbox Info
void *sandboxInfo = nullptr;
//Launch System
CefInitialize(mainArgs, settings, nullptr, sandboxInfo);
Does anyone have the faintest idea what this could be caused by? It's easily among the strangest bugs I've ever encountered.
The project is giant at 50,000 lines or so and there aren't really any other relevant parts so I can't really provide any examples I'm afraid. Let me know if there's some code you think it would help to see though.
You know CEF is multi-process, right? Is it possible that your main application that is initializing CEF is not able to start multiple instances correctly, or is not passing the required command-line arguments to your CEF-containing DLL at startup? See this documentation about the structure of CEF applications: https://bitbucket.org/chromiumembedded/cef/wiki/Architecture#markdown-header-cef3
You can try starting CEF with the "--single-process" argument to force it to run single process (though shipping with this is very much not recommended because they don't test Chromium in this configuration - it is just for debugging). If you are not passing command line arguments to CEF that is probably the start of your problems. To do this, you can add a handler for OnBeforeCommandLineProcessing() in you CefApp derived class, as recommended by the creator of CEF here: http://www.magpcss.org/ceforum/viewtopic.php?f=6&t=12928&p=25732&hilit=main_args#p25717 . The override would end up looking something like this:
void ServiceCenterApp::OnBeforeCommandLineProcessing(const CefString& process_type,
CefRefPtr<CefCommandLine> command_line) {
if(!command_line->HasSwitch("single-process")) {
command_line->AppendSwitch("single-process");
}
}
But I don't see you defining a CefApp derived class, that would be an argument to CefInitialize(). For example, the cefclient sample has this in their wWinMain():
// SimpleApp implements application-level callbacks. It will create the first
// browser instance in OnContextInitialized() after CEF has initialized.
CefRefPtr<SimpleApp> app(new SimpleApp);
followed by
// Initialize CEF.
CefInitialize(main_args, settings, app.get(), sandbox_info);
Where you tell CEF to use the derived App, where you would override whatever handlers you need to. You might want to start with the simple_app sample for a very basic override.
For the debugging issue, try attaching to all processes launched, assuming I'm incorrect and the multiple processes are launching correctly.

Heisenbug issue with using a dll. What do I do next?

I am working on a system that uses a Voltage Controlled Oscillator chip (VCO) to help process a signal. The makers of the chip (Analog Devices) provide a program to load setup files onto the VCO but I want to be able to setup the chip from within the overarching signal processing control system. Fortunately Analog Devices also provides a DLL to interface with their chip and load setup files myself. I am programming in Visual C++ 6.0 (old I know) and my program is a dialog application.
I got the system to work perfectly writing setup files to the card and reading its status. I then decided that I needed to handle the case where there are multiple cards attached and one must be selected. The DLL provides GetDeviceCount() which returns an integer. For some reason every time the executable runs it returns 15663105 (garbage I assume). Whenever I debug my code however the function returns the correct number of cards. Here is my call to GetDeviceCount().
typedef int (__stdcall *GetDeviceCount)();
int AD9516_Setup()
{
int NumDevices;
GetDeviceCount _GetDeviceCount;
HINSTANCE hInstLibrary = LoadLibrary("AD9516Interface.dll");
_GetDeviceCount = (GetDeviceCount)GetProcAddress(hInstLibrary,"GetDeviceCount");
NumDevices = _GetDeviceCount();
return NumDevices;
}
Just to be clear: every other function from the DLL I have used is called exactly like this and works perfectly in the executable and debugger. I did some research and found out that a common cause of Heisenbugs is threading. I know that there is some threading behind the scenes in the dialogs I am using so I deleted all my calls to the function except one. I also discovered that the debugger code executes slower than executable code and I thought the chip may not have enough time to finish processing each command. First I tried taking up time between each chip function call by inserting an empty for loop and when that did not work I commented out all other calls to the DLL.
I do not have access to the source code used to build the DLL and I have no idea why its function would be returning garbage in the executable and not debugger. What other differences are there between running in debugger and executing that could cause an error? What are some other things I can do to search for this error?
Some compilers/IDEs add extra padding to variables in debug builds or initialize them to 0 - this might explain the differences you're encountering between debugging and "normal" execution.
Some things that might be worth checking:
- are you using the correct calling convention?
- do you get the same return value if no devices are connected?
- are you using the correct return type (uint vs int vs long vs ..)?
Try setting _GetDeviceCount to 0 before calling the function; that could be what the debugger is doing for you.

How to test if a DLL can be loaded without an error

I have a native C++ application (no fancy .Net stuff just C++). However it uses some optional .Net assemblies through mixed mode wrapper dll files. These dlls are loaded using delay load. Thing with mixed mode wrappers is they need to be fully trusted in order to load. So when the application try to use the dll if it is not there or if it is not trusted entire thing crashes with a nasty error message.
But i my case as long as my main application is concerned it can live without these dll files. So I need a way to check if these dlls can be loaded (files are there and trusted). In order to do this I tried to put a dummy call to one of the dll functions within a try catch block hoping the catch the exception but it still crash with 'module not found' exception.
we also tried replacing unhanded exception filter with a custom one but still no luck.
we also tried to use LoadLibrary method to first load the dll and check the return value.
But that function load the Dll even if it is not trusted but crash when we try to do a method call.
I dont think that this is an unsolved problem. How hard can it be to check if a dll can be used without actually trying to load it and end up crashing? Any ideas?
If all methods fail, try running a separate process (i.e. simple command-line app) that will try to load the library, then analyze its return code.
But, did you try structured exceptions handling - i.e. __try/__catch, not try/catch? See here.
I had the idea of using a separate process to test the dll first and see if it runs in to any errors. I don't want to use that in my app cos it was not really a clan solution. but the __try, __except approach worked with delay load dll calls. I didn't even have to use LoadLibrary. Thanks.

"CoInitialize failed" when one function (from a lib) is included in VC++ MFC project

I know this is kind of vague, I'm just shooting for general possibilities here to get me on the right track.
I include two libs and their .h's in my MFC Dialog program and compile it, no problem. When I call a function from one of the libs though, it shoots up a dialog box that says "Com Error" "CoInitialize Failed". That's not when I actually CALL the function, that's as soon as the program starts running. My assumption is that when it sees the function, it actually calls in the lib and when it does, possibly a CoInit is being called before the one in my MFC program, thus creating a conflict?
Stepping through the code, it seems to throw this at CDialog::DoModal
I can always add in more details, I was just hoping to get steered in the right direction. Thanks a lot in advance for any help!
EDIT:
The thing is, I don't know where the DLL is calling CoInitialize. I really can't post code, because there's simply too much, even for a simple program. I'll try dependency walker and check out my InitInstance... Any other suggestions? Thanks so much guys
Try adding in your own call to CoInitializeEx, and make sure you're using STA (SingleThreadedApartment) threading in your main thread.
Chances are something is setting up your main thread to be MTA, but your library expects and requires STA, so it's CoInitialize call is failing.
A good direction will be to add more details, specially if you have them, like which is the HRESULT returned by CoInitialize?
My guess is that such lib have a static initialization, if none of the functions from the dll are called they are discarded by the linker, but if at least one function is called then the static initializers are linked.
You should call CoInitialize in your App InitInstance(). Then it should execute before the call to DoModal().
It might be that this error message isn't indicating that the lib tried to call CoInitialize itself but rather tried some other COM call and from the error it received there it deduced that CoInitialize hadn't been called by you.
You can find out who is calling CoInitialize by putting a break point on the same.
This is the way you do it using Debugging Tools for Windows.
You first enable start with debugger option using gflags.exe for your exe.
For that
run gflags.exe
In the image file options give the name of your exe say xyz.exe.
Press tab to enable image level options.
In the debugger option type Full Path to windbg -g
This will result in your exe being started with debugger attached everytime you start xyz.exe.
Now to set a breakpoint on CoInitialize call, break the execution in Windbg.
In the command pane type
bp Ole32!CoInitialize
stop debugging, save the workspace when it prompts and restart xyz.exe
This time the application will break into the debugger when anyone calls CoInitialize.
Hope it helps you
A common error is if a referenced DLL is missing so when the CoInitialize is called it tries to load the DLL and fails with good old E_FAIL. Try using dependency walker and check for any DLL's you may have missed.