Calling to a pointer from a c++ thread - c++

I'm trying to call from a thread to a pointer.
Here is my code:
myDll.dll c++ :
long cbAddrAsync;
void _asyncer(void* data)
{
typedef void (__stdcall *FUNCPTR)();
FUNCPTR vbFunc;
vbFunc = (FUNCPTR)cbAddrAsync;
vbFunc();
}
extern "C" __declspec(dllexport) void async(long addr)
{
cbAddrAsync = addr;
HANDLE hHandle = (HANDLE)_beginthread(_asyncer,0,NULL);
}
calling to this extern with vb6:
In Module1:
Declare Sub async Lib "myDll.dll" (ByVal addr As Long)
Sub onAsync()
MsgBox "ASYNC"
End Sub
In Form1:
Private Sub Command_Click()
Call async(AddressOf Module1.onAsync)
End Sub
when i click at command button , The problem occurs in
dll:
Unhandled exception at 0x734f9232 in Project1.exe: 0xC0000005: Access violation reading location 0x00000076.
in vbFunc();
How can I fix it?
Thanks.

0x00000076 is an invalid memory address. All addresses under 0x0000ffff are invalid. This catches a whole class of errors (failed memory allocations or object creation) along the lines of 0x0 and 0x0 + 2 (or 0x0 + 0x76) etc. The errors are errors that programmers are supposed to check for but often don't.
My guess is you are accessing the 0x76th byte of a structure that wasn't initialised.
VB6 is designed to be a COM server not a dynamic load dll.
AddressOf has rules because you are actually calling VB6 runtime not your program.
You can also start in a debugger.
windbg or ntsd (ntsd is a console program and maybe installed). Both are also from Debugging Tools For Windows.
Download and install Debugging Tools for Windows
http://msdn.microsoft.com/en-us/windows/hardware/hh852363
Install the Windows SDK but just choose the debugging tools.
Create a folder called Symbols in C:\
Start Windbg. File menu - Symbol File Path and enter
srv*C:\symbols*http://msdl.microsoft.com/download/symbols
then
windbg -o -g -G c:\windows\system32\cmd.exe /k batfile.bat
You can press F12 to stop it and kb will show the call stack (g continues the program). If there's errors it will also stop and show them.
Type lm to list loaded modules, x *!* to list the symbols and bp symbolname to set a breakpoint
If programming in VB6 then this environmental variable link=/pdb:none stores the symbols in the dll rather than seperate files. Make sure you compile the program with No Optimisations and tick the box for Create Symbolic Debug Info. Both on the Compile tab in the Project's Properties.
Also CoClassSyms (microsoft.com/msj/0399/hood/hood0399.aspx) can make symbols from type libraries.

Related

C++ COM DLL built in debug cannot be registered when depending on another C++ COM DLL built in release and vice versa

I am attempting to register a Visual C++ COM DLL that I have built with a debug configuration.
This COM DLL depends on another Visual C++ COM DLL that was built with a release configuration.
Both DLLs are being registered with regsvr32 (the release DLL has already been successfully registered).
I am using the 32 bit version of regsvr32 (located in SysWOW64) to register both DLLs (since they are both targeting x86).
The DLLs are compiled with the Visual C++ 2010 compiler (with Service Pack 1 installed).
When I attempt to register the debug DLL, regsvr32 fails with this error message. The blacked out text is just the name of the debug DLL I attempted to register.
The image of the error message has the following text:
RegSvr32
The module "REDACTED" failed to load.
Make sure the binary is stored at the specified path or debug
it to check for problems with the binary or dependent .DLL
files.
A dynamic link library (DLL) initialization routine failed.
I then attempted to debug the code in the debug DLL that gets called by regsvr32 to register it. The debug DLL initializes itself and then attempts to create a COM object from the release DLL that it depends on and call a method on that object.
The method in the release DLL that gets called then immediately calls the method AfxGetApp() to get a pointer to the application. This function returns a null pointer.
The application then attempts to dereference this null pointer and throws an exception.
It is my understanding that this function should not be returning a null pointer in this case.
It doesn't return one when both DLLs are built with a debug configuration or when both are built with a release configuration. It only returns null when the DLLs are built with opposite configurations.
What regsvr32.exe calls into:
BOOL DebugDLLApp::InitInstance()
{
if (CWinApp::InitInstance() == FALSE)
{
return FALSE;
}
ReleaseDLLClass releaseClass;
HINSTANCE hInstDll = releaseClass.LoadResourceDLL();
...
}
What the debug DLL calls into:
BOOL ReleaseDLLClass::LoadResourceDLL()
{
CWinApp* winApp = AfxGetApp(); // Returns null.
LPCSTR exeName = winApp->m_pszExeName; // Null reference exception occurs here.
...
}
So, my question is this:
Is there something inherent in COM that disallows registering DLLs with dependencies that were made with different build configurations?
If not, why would AfxGetApp() return a null pointer in these specific cases?
Thank you for any guidance you have.

Cygwin 64-bit cannot early-bind to DLL created by MSVC , giving __cxa_atexit error

Here is the C++ program compiled by up-to-date Cygwin64 (gcc/x86_84-pc-cygwin/9.3.0):
extern "C"
__declspec(dllimport) void foo(void);
int main(void)
{
foo();
return 0;
}
with commandline:
g++ -o mre.exe mre.cc /f/temp/simpledll/x64/Debug/simpledll.lib
For SimpleDLL I created a new Windows C++ DLL using VS Community 2019, switched to x64 target, disabled PCH, and added simpledll.cpp:
extern "C" __declspec(dllexport) void foo(void);
void foo(void)
{
MessageBoxA(NULL, "In simpledll foo", "Title", MB_OK);
}
leaving the rest of the DLL boilerplate unchanged.
The compilation in Cygwin64 runs successfully, but then running the executable under the Cygwin shell exits with no output. Running the executable in command prompt (and the cygwin1.dll and simpledll.dll in the same directory as the executable, to eliminate any path errors) produces a message box with the text:
The procedure entry point __cxa_atexit could not be located in the dynamic link library F:\temp\mre.exe
Via a debugger (WinDBG) and ProcMon64 I can see that during startup, simpledll.dll is opened correctly and read; and then this error appears (with a C0000139 error code visible in WinDBG when the __cxa_atexit messagebox appears). This happens even if the main() function never calls the function (e.g. I change it to if (argc > 1) foo(); and provide no commandline arguments).
However the following work correctly, showing the messagebox from foo:
The exact same procedure under a mingw-w64 standalone (either from MSYS2 shell, or command prompt).
The exact same procedure under MSYS2 (x86_64-pc-msys2).
Under Cygwin or MSYS2, loading the same DLL via LoadLibrary and GetProcAddress, instead of linking to the .lib file. That is, late binding works fine whereas early binding crashes.
I've been unable to figure out what is happening differently in the Cygwin targets versus any of the above bullet points. Using -fuse-cxa-atexit makes no difference (I think this is on by default anyway), and strings mre.exe shows __cxa_atexit and __imp___cxa_atexit existing. Furthermore, in the standalone mingw-w64 builds, strings does not find any cxa at all, and yet the code runs correctly.
My question is: what is going wrong and how do I fix it (i.e. how can I call a function in the MSVC-created x64 DLL from a Cygwin64-target build).

how to debug a c++ excel plugin's exception during excel exiting

I have an excel xll plug-in built in c++ (and with the help of xlw), which, runs pretty well except, when excel exits, exception happens occasionally.
My headache is that though it looks like some destructor issue, I can't see where it went wrong.
Excel window just closes then a Windows system error message pops out.
Even if I run it in Visual Studio debug mode, when the exception happened, it's already in the STL c++ code, also I can't see which part of my code, such as a destructor, is the root cause of the failure.
To be precise, Call Stack shows
[External Code] -> Excel.Exe -> [External Code] -> MSO.DLL ... repeat... OART.DLL... repeat ... ntdll.cll -> [External Code] -> _cexit() -> common_exit -> __acrt_lock_and_call -> ...
The first step with source visible is exit.cpp in C:\Program Files (x86)\Windows Kits\10\Source\10.0.16299.0\ucrt\startup\exit.cpp,
extern "C" void __cdecl _cexit()
{
common_exit(0, _crt_exit_full_cleanup, _crt_exit_return_to_caller);
}
Have you tried setting a conditional breakpoint in Visual Studio settings to break on any exception (or the specific exception you are getting)? You can enable this just before you exit Excel. This might help track down the problem and give you the call stack in the call stack window when the breakpoint hits.
Also make sure to check if your symbol files (.pdb) are getting loaded for your code and any third party dependencies. Another thing that can help is to specify the Microsoft public symbol servers so that the Microsoft system pdb’s are loaded as well as mentioned in this article.

Access violation on static library call

As an extension of question MSVC unresolved external symbol linking executables. A contains and a class P with two member functions F and G, and also contains a global P MyP. I'm attempting to call functions MyP.F, from Executable T. I finally got past the linking part, but now it fails at runtime with the exception.
A.cpp
struct P {
void F();
void G();
} MyP;
P::F() {
}
P::G() {
}
int main() {
MyP.F();
MyP.G();
}
T.cpp
struct P {
void F();
void G();
} MyP;
int main() {
MyP.F();
MyP.G();
}
I can put a breakpoint in T at the line where it calls F in Visual Studio 2008, but when I press the button to step in, or to step over, I get an exception First-chance exception at 0xfe5ca589 in A.exe: 0xC0000005: Access reading location 0xfe5ca589. When I look at the call stack, it shows
fe5ca589()
A.exe!G() + 0x60a6 bytes
[Frames below may be incorrect and/or missing, no symbols loaded for A.exe]
Both projects are part of the same Visual Studio solution, and A is properly set as a dependancy for T, and seems to be linking correctly, but I can't step into it. Does anyone have insights how to make Visual Studio load the symbols for A so I can step into it and find the error? (Or if something is linked funny causing the error?)
Executables don't have the metadata allowing them to be loaded at an alternate address, and A.EXE can't load into T.EXE at its desired address, because T.EXE's code is already there.
You might be able to work around this by changing the default load address of A.EXE (when building it, it's a linker option), but the correct solution is to use a DLL. (Confirmed, no you can't)
Exports from .EXE files are provided to allow plugin DLLs to call functions in the main application. They aren't meant to allow loading the .EXE like it was a DLL.

Loading an EXE as a DLL, local vftable

I have an exe named test.exe which is usually used as a stand-alone application. I want to use this exe as a module (a dll) inside another application, app.exe.
The code in test.exe does something really simple like:
void doTest()
{
MyClass *inst = new MyClass();
inst->someMethod();
}
Where someMethod() is virtual and MyClass has a virtual d'tor.
doTest() is exported from test.exe and thus a lib called test.lib is created
app.exe is linked with this lib to statically load test.exe when it starts.
When I'm running test.exe stand-alone it runs just fine but when I'm running it loaded from within app.exe it crashes.
Stepping into the code with the debugger revealed that the crash is in the call to the virtual method. It turns out that the vftable somehow goes bad.
After some investigations it turns out that when the code inside the constructor of MyClass is running , the vftable is one thing but when the call to new returns it is replace with something else called a "local vftable". I found this obscure discussion about why this is.
After about a day of debugging it occurred to me that the pointers in this "local vftable" are the same in both cases, when test.exe is stand alone and whenit is loaded as a module. This can't be right because test.exe is loaded into a different address...
To test this theory I changed the loading address in the linker options to the one where test.exe is loaded when it is in app.exe and now, lo and behold, everything works.
Obviously, this is not a permanent solution because next time this randomly selected address may be occupied and the same problem will occur again.
So my question: Why is this "local vftable" tied to the static loading address of the exe? is loading an exe as a module a bad thing? why does the exe assume it is loaded to its static address?
Just for context: this is all done with MSVC 2008, Windows XP x64.
VC++ strips out reloc info from .exes by default because normally they don't need to be relocatable.
You can force it to retain the reloc info with /fixed:no. See: http://msdn.microsoft.com/en-us/library/w368ysh2.aspx
The workaround I ended up using is to simply add a compile configuration and compile the exe as a real dll instead of forcing it to act like one.
using /fixed:no didn't solve the problem for some reason.
Another difference I between exes and DLLs is that the entry point is different. a DLL's entry point is DllMain where as an exe has its entry point in the CRT which eventually calls main() or WinMain().