MetaTrader4 close (crash?) on deinit() + dll threading on WinXP Mode Virtual PC - c++

I have a native library built with Visual Studio 2012. Required project configuration properties:
General / Platform Toolset = Visual Studio 2012 - Windows XP (v110_xp)
C/C++ / Code Generation / Runtime Library = Multi-threaded (/MT)
ExpertSample.cpp:
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <mutex>
BOOL APIENTRY DllMain(HANDLE hModule,DWORD ul_reason_for_call,LPVOID lpReserved) {
return(TRUE);
}
#define MT4_EXPFUNC __declspec(dllexport)
static std::mutex mutex;
MT4_EXPFUNC void __stdcall libInit() {
std::lock_guard<std::mutex> guard(mutex);
OutputDebugStringA("libInit");
}
MT4_EXPFUNC void __stdcall libDeInit() {
std::lock_guard<std::mutex> guard(mutex);
OutputDebugStringA("libDeInit");
}
ExpertSampleTest.mq4:
#import "ExpertSample.dll"
void libInit();
void libDeInit();
#import
int init() {
libInit();
return(0);
}
int deinit() {
libDeInit();
return(0);
}
int start() {
// libDeInit();
return(0);
}
Testing it on Windows 7 (x64) with MetaTrader build 451 (also for build 438) works normally.
Testing it in the WinXP Mode Virtual PC (running inside the same Windows 7), when the EA is removed from the chart, the whole terminal is closed. There is no crash report dialog, or anything in the log files.
If I call libDeInit() from start() it works fine.
If I remove the lock guard from libDeInit(), it works fine.
The above code is just a subset of a larger project. In that project, when the library was built with all kind of debug information and a lot of outputs, the problem seemed to happen less often.
Does anybody know how to fix it, or whether it's a MetaTrader 4 or WinXP Mode Virtual PC issue?

The C++ code itself looks good. Possible issues I see:
If the DLL is loaded but the constructor for the mutex is not called, that would explain your problem. That would be a problem in the environment loading the DLL.
Check the calling convention. Is it stdcall or cdecl? Using the wrong one can cause all kinds of issues, maybe even no issues under some circumstances.
Try replacing the mutex with a function returning a reference to a mutex, which is placed as function-static instance inside that function. If that helps, I'd say that it proves that the constructor is not called.
You don't need DllMain(), I'd only use it to call DisableThreadLibraryCalls().

Related

How do is structure my files right, when I write code for linux and windows

I am currently not sure how I should seperate my code best. I currently programming a software which should run on Linux and Windows. So I decided to put all OS-secificstuff in thier own folder/files.
For example
This is the header file:
#ifdef __linux__
#include <unistd.h>
#elif _WIN64
#include <Windows.h>
#endif
#include <string>
#include <iostream>
#pragma once
class SystemTools
{
public:
// Delay in secounds until the programm continues
static void sleep(int delay);
private:
};
and the OS specific implementation is in the linux/windows folder
Linux:
#ifdef __linux__
#include "../SystemTools.h"
void SystemTools::sleep(int delay)
{
usleep(delay*1000000);
}
#endif
Windows:
#ifdef _WIN64
#include "../SystemTools.h"
void SystemTools::sleep(int delay)
{
Sleep(delay*1000);
}
#endif
This works and I have no problems so far, but when I now have methods which don´t need any OS specific code I created an additional folder "Generic" so I can write the code in there and don´t have to mantain the same code in the linux and windows file. For example like that:
Generic:
#include "../SystemTools.h"
void SystemTools::sleepMin(int delay)
{
sleep(delay*60);
}
#endif
That still workes on Linux but not on Windows (no error but does not compile, used codeblockes for that on windows). So how do I organize my code correct? Should I use only one file with ifdef even it that gets very fast ugly?
(compiler Linux: g++, Windows: should be MinGW)
Firstly I'd suggest you to use the most recent of C++ (C++20 or so) on your project. This way, we can abstract many OS related calls (like threading, synchronization, random numbers and etc).
That means, you won't really need to use too many of OS specific APIs. IE: C++11 and earlier already have a standard way to sleep:
https://en.cppreference.com/w/cpp/thread/sleep_for
In the end, if you really need to call OS specific things on windows and on linux, using a library could be interesting and pay attention that windows C++ compiler (visual studio) really like to use 'pre compiled headers' so, it's interesting to have a single header file where all windows specific headers can be included.
Basically that. You can have a standard Cmake or makefile for your linux build and use .sln Visual Studio project to build it to windows.
That's the way I would do that

App Crash for C++/CLI DLL and Exe of x64 bit

Just to showcase problem I have written a simple DLL x64 of "Hello world" changed its property to CLR and Calling its Function from an Exe which is also x64 and property Changed to CLR.
But My exe prints the Output "Hello World" and crashes every time and gives FAULT Module Name KERNELBASE.dll.
When I change Property of both to NO CLR it works perfectly fine. This happens only for x64 application not observed in x86 program.
I am using Visual Studio 2017 on Windows Server 2012.
It will be very helpful if someone can guide me to correct direction.
Details of App Crash
Problem Event Name: APPCRASH
Application Name: consuming_using_clr.exe
Application Version: 0.0.0.0
Application Timestamp: 5b42fff3
Fault Module Name: KERNELBASE.dll
Fault Module Version: 6.3.9600.17055
Fault Module Timestamp: 532954fb
Exception Code: c0020001
Exception Offset: 0000000000005bf8
OS Version: 6.3.9600.2.0.0.16.7
Locale ID: 1033
Additional Information 1: 8e72
Additional Information 2: 8e72455f15a8480830570fcb3c4abf60
Additional Information 3: f8d5
Additional Information 4: f8d519c5149c6c561af747d4db7e910a
DLL dot.h file
// The following ifdef block is the standard way of creating macros which make exporting
// from a DLL simpler. All files within this DLL are compiled with the DLLWINDOWSDESKTOPWIZARD_EXPORTS
// symbol defined on the command line. This symbol should not be defined on any project
// that uses this DLL. This way any other project whose source files include this file see
// DLLWINDOWSDESKTOPWIZARD_API functions as being imported from a DLL, whereas this DLL sees symbols
// defined with this macro as being exported.
#ifdef DLLWINDOWSDESKTOPWIZARD_EXPORTS
#define DLLWINDOWSDESKTOPWIZARD_API __declspec(dllexport)
#else
#define DLLWINDOWSDESKTOPWIZARD_API __declspec(dllimport)
#endif
#using<System.dll>
#include<iostream>
using namespace System;
using namespace std;
// This class is exported from the Dll_windows_desktop_wizard.dll
class DLLWINDOWSDESKTOPWIZARD_API CDllwindowsdesktopwizard
{
public:
CDllwindowsdesktopwizard(void);
~CDllwindowsdesktopwizard(void);
void helloworld();
};
*DLL DOT CPP File *
// Dll_windows_desktop_wizard.cpp : Defines the exported functions for the DLL application.
//
#include "stdafx.h"
#include "Dll_windows_desktop_wizard.h"
// This is the constructor of a class that has been exported.
// see Dll_windows_desktop_wizard.h for the class definition
CDllwindowsdesktopwizard::CDllwindowsdesktopwizard(void)
{
}
CDllwindowsdesktopwizard::~CDllwindowsdesktopwizard(void)
{
}
void CDllwindowsdesktopwizard::helloworld()
{
Console::WriteLine("Hello World");
}
EXE Calling DLL Function
#include<iostream>
#include "Dll_windows_desktop_wizard.h"
using namespace System;
int main()
{
CDllwindowsdesktopwizard lv_obj;
lv_obj.helloworld();
return 0;
}
dllMain.cpp
#include "stdafx.h"
BOOL APIENTRY DllMain( HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
Finally I got it.Came across this link https://msdn.microsoft.com/en-us/library/ccthbfk8.aspx as i was trying to remove the warning from my exe warning was
"warning:Calling managed 'DllMain': Managed code may not be run under loader lock,including the DLL entrypoint and calls reached from the DLL entrypoint"

How can I check #ifdef in a DLL project, when the #define is in the executable project using the dll?

I have a C++ Visual Studio 2015 project consisting of
1 Windows API executable, 1 windows console executable, and 1 dll shared by both executables.
I have a #define USEWINDOWS in the Windows API main.cpp file
I don't have this defined in the console app
In the DLL, I would like to do an #ifdef USEWINDOWS statement, but the scope of the #define seems to be only valid to the Win32 executable, not in the dll.
How can I extend this #define to the DLL without having it affect the undefined USEWINDOWS in the console app?
Thanks
The DLL is shared by both executables, hence there is only one implementation available and therefore you can't use implementation specific compilation flags.
You'll need a runtime flag, i.e. some API parameter which tells the DLL code that it is OK to use "windows stuff". E.g.
api.h
void someAPI(...., bool useWindows);
dll.c
#include "api.h"
void someAPI(...., bool useWindows) {
...
if (useWindows) {
// do "windows stuff" here
}
...
}
app.c
#include "api.h"
...
someAPI(...., true);
console.c
#include "api.h"
...
someAPI(...., false);
(not tested by compilation, but you should get the drift...)

DLL built by vc6 turn to error when using by exe built by vs2012

I have a exe built by vs2012, which can successfully run with linking to dll built by vs2012, while the following error appeared when linking to the same dll built by vc6.
(Expression:_CrtIsValidHeapPointer(pUserData))
the only difference between the dll projects of vc6 and vs2012 is that the vc6 one fail to #include "SDKDDKVer.h"
Here is the code for export function of the dll
extern "C" _declspec(dllexport) RobotAI_Interface* Export()
{
return (RobotAI_Interface*)new RobotAI();
}
extern "C" _declspec(dllexport) void FreeRobotAIPointer(RobotAI_Interface* p)
{
delete p;
}
The program breaks at this specific point when debuging (a system code):
extern "C" _CRTIMP int __cdecl _CrtIsValidHeapPointer(const void * pUserData)
{
if (!pUserData)
return FALSE;
if (!_CrtIsValidPointer(pHdr(pUserData), sizeof(_CrtMemBlockHeader), FALSE))
return FALSE;
return HeapValidate( _crtheap, 0, pHdr(pUserData) );
->}
The arrow is where it breaks.
The following is my code where it breaks:
void CArmorClientDlg::AddToList(CString file_path_name)
{
pAIManager->Add(file_path_name);
string dll_name=pAIManager->GetAI_RobotName(pAIManager->GetAINum()-1);
CListBox* pList=static_cast<CListBox*>(GetDlgItem(IDC_LIST_AI));
pList->AddString((CString)dll_name.c_str());
->}
The arrow is where it breaks. All the operations related to dll are done in "Add(file_path_name)"
I know little about the dll things... How to solve the problem?
Thank you!
TIP: the reason that I have to support vc6 dll is that the project is an AI competition, dll is the AI program that built by different contastents. The majority of the students in my school may only use vc6.
To be clear, you are mixing an EXE built with VS2012 with a DLL built with VC6? If so you are mixing C runtime library versions. While this is possible, you have to be careful to not mix heap allocations. For example, if the DLL allocates memory and returns a pointer, and the EXE tries to free the pointer, that could cause the error you see.
Either compile both the DLL and EXE with the same compiler, or write a function in the DLL that frees the pointer and use that function to pass the allocated pointer back to the DLL to be freed by the C runtime that allocated it.

Using MFC and ATL libraries without Visual Studio

My question is if I can use MFC and ATL libraries that come with PSDK Windows Server 2003 R2, without Visual Studio. I mean only at the command prompt with BCC32.exe or CL.exe?
I have found MFC and ATL libraries in the PSDK Windows Server 2003 R2 but I does not know if these libraries can be used without Visual Stuio IDE! What I need to do before using MFC and ATL at the command prompt?
Thanks!
If you have all the headers, and either the source code or compiled version of the rest, then yes it can be used without Visual Studio. Visual Studio is just an IDE that invokes the compiler etc. for you. With command line tools you do that job yourself.
Here's a minimal MFC program that you can try out:
#define WINVER 0x0500 // Windows 2000 and up.
#include <afxwin.h> // MFC core and standard components
typedef CFrameWnd MainWindow;
class App
: public CWinApp
{
private:
bool createTheMainWindow()
{
static char const title[] = "A general top level MFC window";
MainWindow* const pWnd =
new MainWindow;
if( !pWnd ) { return false; } // Pre-standard 'new' in MFC...
m_pMainWnd = pWnd;
pWnd->Create( NULL, title );
return true;
}
public:
virtual BOOL InitInstance()
{
CWinApp::InitInstance();
if( !createTheMainWindow() ) { return false; }
m_pMainWnd->ShowWindow( SW_SHOW );
m_pMainWnd->UpdateWindow();
return true;
}
};
App theApp;
Cheers & hth.,
No you can't, since some functionality relies on the Visual Studio compiler specific behavior. For example the way trampolines are used to map window handles to objects.
I'm assuming that you by "can be used without Visual Stuio IDE" you actually mean "with another compiler", since you mention the Borland compiler. Of course you can write C++ in a text editor and compile those files from the command line, not using the IDE, but what you want is using another compiler, right? (the IDE and the compiler are related but not the same).