Access violation on static library call - c++

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.

Related

Visual Studio Incremental Linking Full Relinks With Templates

I have an issue with incremental linking in that when I change some code it sometimes does a full link. I have narrowed the code down to a specific piece and was wondering if anyone knows why.
I am using Visual Studio 2012 (it exhibits the same behavior in 2015).
I have created a blank solution with 2 projects in it (a lib and an exe). I have setup incremental linking to work properly (importing library outputs as well).
The exe simply has main call into 'UpdateFrame' which is listed below.
This is all the code from the library project itself.
struct TypeId
{
unsigned char myTypeId;
// Comment out this line and it links incrementally
TypeId() : myTypeId(0) {}
};
template<class Type>
struct TypeRegistrationHelper
{
static TypeId ourTypeId;
};
template<class Type> TypeId TypeRegistrationHelper<Type>::ourTypeId;
// Uncomment this line and it links incrementally
//template struct TypeRegistrationHelper<float>;
void UpdateFrame()
{
// Commenting/uncommenting this line causes a full link to happen
// unless you have changed 1 of the 2 lines listed above. Then it links
// incrementally as expected when changing this line.
TypeRegistrationHelper<float>::ourTypeId;
}
The problem comes up that if I comment out the line in UpdateFrame, it causes a full link to happen (unless I have modified one of the two lines that are commented in code -- then everything works fine)
I've enabled verbose output for incremental linking and this is the reason it lists as performing a full relink:
LINK : directives changed; performing full link
This is the MSDN page regarding this particular error (note it says its for VC 6.0)
Linker Tools Warning LNK6019
And this is the only information it contains
A directive was added or deleted since the last incremental linking session. A full link was required in order to recreate the incremental status (.ILK) file.
Here is my main function (in the application project obviously)
#include "Updater.h"
int main()
{
UpdateFrame();
return 0;
}

Writing into stream passed to a DLL

I have an issue writing into a stream, passed as a FILE* to a function which is contained in a DLL. Compiler: Visual C++, all versions 2005 to 2015. The precise errors vary; the VS 2015 version is given below. The problem is identical for Win32 and x64 targets.
Trying to boil down the problem, consider this function:
#include <stdio.h>
void TestPrintf(FILE *TestFile)
{
fprintf(TestFile, "Hello World");
}
Now, another function will be calling the above function in the following way:
#include <stdio.h>
void TestPrintf(FILE *TestFile);
void AnyFunction( void )
{
FILE *TestFile;
fopen_s( &TestFile, "PrintTest.txt", "wt");
TestPrintf(TestFile);
}
The first function is part of a DLL. Depending on the settings in
Properties / C/C++ / Code Generation during compilation of both the DLL and the program containing the caller, I get the following error messages:
Caller compiled for Multithread Debug (static):
DLL compiled for either Multithread Debug (static) or Multithread Debug DLL:
Debug assertion failed
File: minkernel\crts\ucrt\src\appcrt\heap\debug_heap.cpp
Line: 980
Expression: __acrt_first_block == header
DLL compiled for Multithread (static):
Debug assertion failed in the same file as before, but now
Line: 892
Expression: is_block_type_valid(header->block_use)
DLL compiled for Multithread DLL:
Again another variant of the same. Now it is:
Line: 888
Expression: _CrtlsValidHeapPointer(block)
Caller compiled for Multithread Debug DLL:
DLL compiled for either Multithread (static) or Multithread Debug (static):
same messages as above
DLL compiled for Multithread DLL:
Yet another variant of the same. Now it is:
HEAP[FilePrintTest.exe]: Invalid address specified to RtlValidateHeap(
01060000, 0107B7A0 )
DLL compiled for Multithread Debug DLL:
This is error-free.
Caller compiled for Release (either Multithread or Multithread DLL):
all four versions of the DLL go error-free.
The difference between VS versions seems to be that VS 2015 first writes the output as intended and crashes afterwards, whereas VS 2005 crashes already while writing the output.
If the function TestPrintf is not in a DLL, but in a static library, there is no such problem (of course, there will be linker messages about library collisions, but the test program works nonetheless). However, unfortunately, I do need the writing function inside the DLL, and I must be able to call it from anywhere.
All of the above applies also to the case that the caller is in a console programme and the stream is stdout.
So my question is: Is there a stupid mistake on my side? If not, is there a way to work around this problem?
I would be grateful for suggestions!
Martin
Please review the fopen_s syntax. You are passing a FILE * * by using the & in front of the pointer.
Try removing the & symbol:
fopen_s(TestFile, /*...*/);
Your TestFile is already a pointer:
FILE * TestFile;
Your usage doesn't match the syntax presented by cppreference.com

Calling to a pointer from a c++ thread

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.

Persistent undefined reference

I am having a persistent undefined symbol error in Eclipse on MAC OS X. I can't figure
out the source of the error.
The error occurs according to the compiler when I try to use GA_Operations and gaAlgorithm->run_algorithm..... below:
int Application::execute_Algorithm()
{
if (this->GA_On)
{
GA_Operations *gaAlgorithm = new GA_Operations();
gaAlgorithm->run_algorithm(blocksSequence, bins);
}
else
{
packingAlgorithm->run_algorithm(blocksSequence, bins); return 0;
} //
return 0;
}
The error showing is:
Undefined symbols for architecture x86_64:
"binproject::GA_Operations::run_algorithm(binproject::Blocks_Sequence&, binproject::BinContainer&)", referenced from:
binproject::Application::execute_Algorithm() in Application.o
"binproject::GA_Operations::GA_Operations()", referenced from:
binproject::Application::execute_Algorithm() in Application.o
And the declaration is:
class GA_Operations {
public:
GA_Operations();
~GA_Operations();
//call from main application to execute algorithm
void run_algorithm(Blocks_Sequence &b_seq, BinContainer &container);
...
};
It also throws a similar error anytime I try to define a declared function in the
implementation (CPP) file.
Any ideas? This only seems to happen with this class.
Also, I apologize if there is a problem with the code indenting, I'm
The error you are showing is a linker error. This means that the compiler thinks something exists, but the linker can't find where you've defined (not declared) it. Somewhere you need something like this:
GA_Operations::GA_Operations()
{
// construct
}
void GA_Operations::run_algorithm(Blocks_Sequence &b_seq, BinContainer &container)
{
// stuff
}
Do you have that anywhere? If so, is it in the same file that Application::execute_Algorithm is in?
If it isn't, where is it? How are you compiling your whole program together so the stuff in these different files ends up in the same executable?
I'm not at all sure how to make Eclipse do what you need. I know it's possible, but I'm for familiar with pure command-line tools. You need to tell Eclipse that the .cpp file that contains the above definitions is part of your project and should be compiled and linked into the executable you're created.
Turns out this was an issue with linker settings. I turned on generating makefiles automatically and the problem resolved itself.

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().