- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
假设我们有一个.exe和多个.dll,它们都使用不同的Visual Studio版本以C / C ++编写。
.exe和.dll可能具有大量的第三方静态库,并且很难升级整个项目(C ++或DLL)以使用较新的Visual Studio。
除了二进制兼容性可能会因Visual Studio切换而提高:
Visual studio 2015 run-time dependencies or how to get rid of Universal CRT?
可能还会有更多问题-如调试等:
https://randomascii.wordpress.com/2013/09/11/debugging-optimized-codenew-in-visual-studio-2012/
正如我在较旧的Visual Studio中所了解的那样,C ++函数名称改写也存在问题(从Visual Studio更改为Visual Studio)
移植解决方案会造成更多问题。
分配/免费问题
据我了解,在.exe上下文中执行p = malloc()(exe是用vs2010编译的),然后在.dll上下文中执行free(p)(dll是用vs2013编译的)会导致应用程序崩溃。
我猜想一种方法是根本不使用CRT分配功能(不使用malloc,免费,新建等),而是直接使用Windows api(LocalAlloc等),这样代码就可以在Visual Studio的不同版本中工作,但是用您自己的分配方案覆盖所有分配过程听起来像是繁琐的任务。
您知道使vs版本混合成为可能的其他方法吗?
我还测试了C ++函数处理的功能在Visual Studio 2010和2013之间兼容,但是现在它已成为标准-在下一个Visual Studio版本中是否会以不兼容的方式更改?
最佳答案
提出这样的问题有时真的很有用-从评论您的人那里可以获得真正有用的链接。
我想在此处复制粘贴该链接:
http://siomsystems.com/mixing-visual-studio-versions/
这是技术背景/问题的描述。
我自己试图为问题#1建立某种解决方案的原型。 (问题2对我来说仍然不清楚)
主要问题本身来自dll的MSVCR100.DLL / MSVCR120.DLL / ...趋向于使用自己的内存管理例程,而不是尝试具有一些共同点-例如依靠Windows API。据我所知,可能是vs2015中引入的通用CRT试图摆脱这个问题-但是-不确定-需要更深入的研究。
我自己想-“好吧,如果我们正在加载MSVCR120.DLL-为什么我们不能拦截malloc / realloc / free函数并路由到我们的CRT”。此解决方案适用于使用“单线程DLL”或“多线程DLL”运行时库的exe和dll。
我已经从这个网站上摘了Minhooks:
http://www.codeproject.com/Articles/44326/MinHook-The-Minimalistic-x-x-API-Hooking-Libra
并编写如下代码片段:
crtCompatibility.cpp:
#include <Windows.h>
#include "MinHook.h" //MH_Initialize
#include <map>
#include <vector>
#include <atlstr.h> //CStringW
#include <Psapi.h> //EnumProcessModules
using namespace std;
map<CStringW, bool> g_dlls; // dll file path (lowercased) for all loaded .dll's within process.
map<CStringW, vector<void*> > g_mapHooks; // dll file path to hooks accosiated with given dll.
map<CStringW, bool> g_myCrtDlls; // filenames only of all crt's which we enabled by default.
CRITICAL_SECTION g_dllCheck;
bool g_executingInCrt = false; // true if executing in dll's crt, don't reroute such mallocs then, otherwise crt gets angry to you.
DWORD g_monitorThread = (DWORD) -1;
#define CRTS_TO_HOOK 10 // Maximum CRT's to hook
bool hookIsFree[CRTS_TO_HOOK] = { true, true, true, true, true, true, true, true, true, true };
//-------------------------------------------
// malloc rerouter.
//-------------------------------------------
typedef void* (__cdecl *pFuncMalloc) (size_t size);
pFuncMalloc porigMalloc[CRTS_TO_HOOK] = { 0 };
map<CStringW, int> g_AllocationId;
template <int i>
void* __cdecl _thisCrtMalloc( size_t size )
{
if( !g_executingInCrt && g_monitorThread == GetCurrentThreadId() )
return malloc( size );
return porigMalloc[i]( size );
}
pFuncMalloc thisCrtMalloc[CRTS_TO_HOOK] =
{
_thisCrtMalloc<0>, _thisCrtMalloc<1>, _thisCrtMalloc<2>, _thisCrtMalloc<3>, _thisCrtMalloc<4>,
_thisCrtMalloc<5>, _thisCrtMalloc<6>, _thisCrtMalloc<7>, _thisCrtMalloc<8>, _thisCrtMalloc<9>
};
//-------------------------------------------
// realloc rerouter.
//-------------------------------------------
typedef void* (__cdecl *pFuncRealloc) (void* p, size_t size);
pFuncRealloc porigRealloc[CRTS_TO_HOOK] = { 0 };
template <int i>
void* __cdecl _thisCrtRealloc( void* p, size_t size )
{
if( !g_executingInCrt && g_monitorThread == GetCurrentThreadId() )
return realloc( p, size );
return porigRealloc[i]( p, size );
}
pFuncRealloc thisCrtRealloc[CRTS_TO_HOOK] =
{
_thisCrtRealloc<0>, _thisCrtRealloc<1>, _thisCrtRealloc<2>, _thisCrtRealloc<3>, _thisCrtRealloc<4>,
_thisCrtRealloc<5>, _thisCrtRealloc<6>, _thisCrtRealloc<7>, _thisCrtRealloc<8>, _thisCrtRealloc<9>
};
//-------------------------------------------
// free rerouter.
//-------------------------------------------
typedef void( __cdecl *pFuncFree ) (void*);
pFuncFree porigFree[CRTS_TO_HOOK] = { 0 };
template <int i>
void __cdecl _thisCrtFree( void* p )
{
if( !g_executingInCrt && g_monitorThread == GetCurrentThreadId() )
return free( p );
porigFree[i]( p );
}
pFuncFree thisCrtFree[CRTS_TO_HOOK] =
{
_thisCrtFree<0>, _thisCrtFree<1>, _thisCrtFree<2>, _thisCrtFree<3>, _thisCrtFree<4>,
_thisCrtFree<5>, _thisCrtFree<6>, _thisCrtFree<7>, _thisCrtFree<8>, _thisCrtFree<9>
};
//
// Normally we could just return true here. But just to minimize amount of hooks
// enabled accross whole process, we know which plugins are using which visual studio
// crt.
//
bool CrtNeedsToBeHooked( const wchar_t* pDll )
{
if( wcsicmp( pDll, L"msvcr120.dll") == 0 )
return true;
return false;
}
//
// Loading one dll might load another (dependent) dll as well.
// Same is with FreeLibrary. We keep here record of which dll's are loaded
// to compare with previous state.
//
void EnumDlls( bool bCheckNew )
{
EnterCriticalSection( &g_dllCheck);
HMODULE dlls[1024] = { 0 };
DWORD nItems = 0;
wchar_t path[MAX_PATH];
HANDLE hProcess = GetCurrentProcess();
if( !EnumProcessModules( hProcess, dlls, sizeof( dlls ), &nItems ) )
{
LeaveCriticalSection( &g_dllCheck);
return;
}
// Not visited.
for( auto it = g_dlls.begin(); it != g_dlls.end(); it++ )
it->second = false;
nItems /= sizeof( HMODULE );
for( unsigned int i = 0; i < nItems; i++ )
{
path[0] = 0;
if( !GetModuleFileNameExW( hProcess, dlls[i], path, sizeof( path ) / sizeof( path[0] ) ) )
continue;
_wcslwr_s( path, MAX_PATH );
auto it = g_dlls.find( path );
if( it != g_dlls.end() )
{
// Visited.
it->second = true;
continue;
}
g_dlls[path] = true;
if( !bCheckNew )
continue;
wchar_t* pDll = wcsrchr( path, L'\\' );
if( pDll ) pDll++;
//
// MSVCRxxx.dll (For example MSVCR100.DLL) is loading, let's hook it's memory allocation routines
// and route them to our CRT.
//
// (P.S. this might be different .dll name for vs2015, haven't tested)
//
if( _wcsnicmp( pDll, L"MSVCR", 5 ) == 0 && CrtNeedsToBeHooked(pDll) && g_myCrtDlls.find( pDll ) == g_myCrtDlls.end() )
{
// While we are executing our code in hookLoadLibrary, we can execute GetProcLibrary
// functions, and it's possible to get dead lock because of this.
// kernel32.dll is waiting for LoadLibrary to complete, but we are waiting for GetProcLibrary
// to complete.
LeaveCriticalSection( &g_dllCheck);
void* f = GetProcAddress( dlls[i], "malloc" );
void* f2 = GetProcAddress( dlls[i], "realloc" );
void* f3 = GetProcAddress( dlls[i], "free" );
EnterCriticalSection( &g_dllCheck);
int FoundFreeSlot = -1;
for( int freeSlot = 0; freeSlot < CRTS_TO_HOOK; freeSlot++ )
if( hookIsFree[freeSlot] == true )
{
FoundFreeSlot = freeSlot;
break;
}
if( FoundFreeSlot != -1 )
{
vector<void*> vecTargets;
// Hook malloc, realloc, free functions CRT compatibility.
vecTargets.push_back( f );
MH_CreateHook( f, thisCrtMalloc[FoundFreeSlot], (void**)&porigMalloc[FoundFreeSlot] );
vecTargets.push_back( f2 );
MH_CreateHook( f2, thisCrtRealloc[FoundFreeSlot], (void**)&porigRealloc[FoundFreeSlot] );
vecTargets.push_back( f3 );
MH_CreateHook( f3, thisCrtFree[FoundFreeSlot], (void**)&porigFree[FoundFreeSlot] );
g_mapHooks[path] = vecTargets;
MH_EnableHook( MH_ALL_HOOKS );
g_AllocationId[path] = FoundFreeSlot;
hookIsFree[FoundFreeSlot] = false;
}
}
} //for
//
// Check if .dll's were freed.
//
for( auto it = g_dlls.begin(); it != g_dlls.end(); )
{
if( !it->second )
{
// Release trampolines.
auto hooks = g_mapHooks.find( it->first );
if( hooks != g_mapHooks.end() )
{
// Release allocation slot.
int allocSlot = g_AllocationId[ it->first ];
if( allocSlot < CRTS_TO_HOOK )
hookIsFree[allocSlot] = true;
vector<void*>& vec = hooks->second;
for( size_t i = 0; i < vec.size(); i++ )
MH_RemoveHook2( vec[i], false );
}
// Dll was freed.
g_dlls.erase( it++ );
continue;
}
it++;
} //for
if( !bCheckNew )
{
// Collect CRT names upon which we are running at. .NET might try to draw multiple CRTs.
for( auto it = g_dlls.begin(); it != g_dlls.end(); it++ )
{
CStringW path = it->first;
wchar_t* pPath = path.GetBuffer( MAX_PATH );
_wcslwr_s( pPath, MAX_PATH );
wchar_t* pDll = wcsrchr( pPath, L'\\' );
if( pDll ) pDll++;
if( _wcsnicmp( pDll, L"MSVCR", 5 ) == 0 )
g_myCrtDlls[pDll] = true;
}
}
LeaveCriticalSection( &g_dllCheck );
} //EnumDlls
//-------------------------------------------
// Intercepts LoadLibraryW
//-------------------------------------------
typedef HMODULE( WINAPI *pFuncLoadLibraryW )(const wchar_t* file);
pFuncLoadLibraryW g_origLoadLibraryW = NULL;
HMODULE WINAPI hook_LoadLibraryW( const wchar_t* file )
{
bool bUpdateLock = g_monitorThread == GetCurrentThreadId();
if( bUpdateLock )
g_executingInCrt = true;
HMODULE h = g_origLoadLibraryW( file );
if( bUpdateLock )
g_executingInCrt = false;
if( !h )
return h;
EnumDlls( true );
return h;
} //hook_LoadLibraryW
//-------------------------------------------
// Intercepts LoadLibraryA
//-------------------------------------------
typedef HMODULE( WINAPI *pFuncLoadLibraryA )(const char* file);
pFuncLoadLibraryA g_origLoadLibraryA = NULL;
HMODULE WINAPI hook_LoadLibraryA( const char* file )
{
bool bUpdateLock = g_monitorThread == GetCurrentThreadId();
if( bUpdateLock )
g_executingInCrt = true;
HMODULE h = g_origLoadLibraryA( file );
if( bUpdateLock )
g_executingInCrt = false;
if( !h )
return h;
EnumDlls( true );
return h;
} //hook_LoadLibraryW
//-------------------------------------------
// Intercepts FreeLibrary
//-------------------------------------------
typedef BOOL( WINAPI *pFuncFreeLibrary ) (HMODULE h);
pFuncFreeLibrary g_origFreeLibrary;
BOOL WINAPI hook_FreeLibrary( HMODULE h )
{
bool bUpdateLock = g_monitorThread == GetCurrentThreadId();
if( bUpdateLock )
g_executingInCrt = true;
BOOL b = g_origFreeLibrary( h );
if( bUpdateLock )
g_executingInCrt = false;
if( !b )
return b;
EnumDlls( true );
return b;
} //hook_FreeLibrary
//
// This function intercepts and starts monitor what new dll's gets loaded and freed.
// If there is loaded MSVCRxxx.DLL different CRT run-time than we're running in - we intercepts
// it's memory allocation routines, so allocation in .dll would work identically to allocation in main .exe
//
void EnableCrtMonitor(void)
{
EnumDlls( false );
MH_Initialize();
MH_CreateHookApi( L"kernel32.dll", "LoadLibraryW", hook_LoadLibraryW, (void**)&g_origLoadLibraryW );
MH_CreateHookApi( L"kernel32.dll", "LoadLibraryA", hook_LoadLibraryA, (void**)&g_origLoadLibraryA );
MH_CreateHookApi( L"kernel32.dll", "FreeLibrary", hook_FreeLibrary, (void**)&g_origFreeLibrary );
MH_EnableHook( MH_ALL_HOOKS );
}
class CCrtCompatibilityEnabler
{
public:
CCrtCompatibilityEnabler()
{
InitializeCriticalSection( &g_dllCheck);
EnableCrtMonitor();
}
~CCrtCompatibilityEnabler()
{
MH_DisableHook( MH_ALL_HOOKS );
MH_Uninitialize();
DeleteCriticalSection(&g_dllCheck);
}
} g_CheckCrtShutdown;
//
// This function enables or disables CRT compatibility hooks.
//
// Enabling can be done like this:
// EnableDisableCrtCompatibility( GetCurrentThreadId() );
// and disabling - running without any argument.
//
// When hooks are enabled - for thread which is monitored - all memory allocations
// will be performed using main .exe CRT.
//
void EnableDisableCrtCompatibility( DWORD monitorThread = (DWORD) -1)
{
g_monitorThread = monitorThread;
}
EnableDisableCrtCompatibility( GetCurrentThreadId() );
<call to dll>
p = malloc(1024);
<back to exe>
EnableDisableCrtCompatibility( );
free( p );
void UseExeCrt( bool bExesCrt )
{
if( bExesCrt )
EnableDisableCrtCompatibility( GetCurrentThreadId() );
else
EnableDisableCrtCompatibility( );
}
... class implemented in .exe, declaration for .dll:
class __declspec(dllimport) CMyOwnClass
{
public:
void GetComplexData();
...
};
... data resides in .dll:
vector<String> g_someDllsData;
... function resides in .dll:
...
UseExeCrt( true ); // Use exe's CRT for allocating CMyOwnClass.
{
CMyOwnClass tempClass;
tempClass.GetComplexData(); // Since function resides in .exe - we use .exe's CRT.
UseExeCrt( false ); // Now we use some data which resides in .dll, and we must use .dll's crt.
g_someDllsData.resize( ... );
UseExeCrt( true ); // Before deleting CMyOwnClass - we must use again .exe's CRT
} //~CMyOwnClass is called.
UseExeCrt( false ); // Now back to .dll's CRT. (Just to be safe).
关于c++ - Visual Studio代码二进制兼容性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36811679/
#include using namespace std; class C{ private: int value; public: C(){ value = 0;
这个问题已经有答案了: What is the difference between char a[] = ?string?; and char *p = ?string?;? (8 个回答) 已关闭
关闭。此题需要details or clarity 。目前不接受答案。 想要改进这个问题吗?通过 editing this post 添加详细信息并澄清问题. 已关闭 7 年前。 此帖子已于 8 个月
除了调试之外,是否有任何针对 c、c++ 或 c# 的测试工具,其工作原理类似于将独立函数复制粘贴到某个文本框,然后在其他文本框中输入参数? 最佳答案 也许您会考虑单元测试。我推荐你谷歌测试和谷歌模拟
我想在第二台显示器中移动一个窗口 (HWND)。问题是我尝试了很多方法,例如将分辨率加倍或输入负值,但它永远无法将窗口放在我的第二台显示器上。 关于如何在 C/C++/c# 中执行此操作的任何线索 最
我正在寻找 C/C++/C## 中不同类型 DES 的现有实现。我的运行平台是Windows XP/Vista/7。 我正在尝试编写一个 C# 程序,它将使用 DES 算法进行加密和解密。我需要一些实
很难说出这里要问什么。这个问题模棱两可、含糊不清、不完整、过于宽泛或夸夸其谈,无法以目前的形式得到合理的回答。如需帮助澄清此问题以便重新打开,visit the help center . 关闭 1
有没有办法强制将另一个 窗口置于顶部? 不是应用程序的窗口,而是另一个已经在系统上运行的窗口。 (Windows, C/C++/C#) 最佳答案 SetWindowPos(that_window_ha
假设您可以在 C/C++ 或 Csharp 之间做出选择,并且您打算在 Windows 和 Linux 服务器上运行同一服务器的多个实例,那么构建套接字服务器应用程序的最明智选择是什么? 最佳答案 如
你们能告诉我它们之间的区别吗? 顺便问一下,有什么叫C++库或C库的吗? 最佳答案 C++ 标准库 和 C 标准库 是 C++ 和 C 标准定义的库,提供给 C++ 和 C 程序使用。那是那些词的共同
下面的测试代码,我将输出信息放在注释中。我使用的是 gcc 4.8.5 和 Centos 7.2。 #include #include class C { public:
很难说出这里问的是什么。这个问题是含糊的、模糊的、不完整的、过于宽泛的或修辞性的,无法以目前的形式得到合理的回答。如需帮助澄清此问题以便重新打开它,visit the help center 。 已关
我的客户将使用名为 annoucement 的结构/类与客户通信。我想我会用 C++ 编写服务器。会有很多不同的类继承annoucement。我的问题是通过网络将这些类发送给客户端 我想也许我应该使用
我在 C# 中有以下函数: public Matrix ConcatDescriptors(IList> descriptors) { int cols = descriptors[0].Co
我有一个项目要编写一个函数来对某些数据执行某些操作。我可以用 C/C++ 编写代码,但我不想与雇主共享该函数的代码。相反,我只想让他有权在他自己的代码中调用该函数。是否可以?我想到了这两种方法 - 在
我使用的是编写糟糕的第 3 方 (C/C++) Api。我从托管代码(C++/CLI)中使用它。有时会出现“访问冲突错误”。这使整个应用程序崩溃。我知道我无法处理这些错误[如果指针访问非法内存位置等,
关闭。这个问题不符合Stack Overflow guidelines .它目前不接受答案。 我们不允许提问寻求书籍、工具、软件库等的推荐。您可以编辑问题,以便用事实和引用来回答。 关闭 7 年前。
已关闭。此问题不符合Stack Overflow guidelines 。目前不接受答案。 要求我们推荐或查找工具、库或最喜欢的场外资源的问题对于 Stack Overflow 来说是偏离主题的,因为
我有一些 C 代码,将使用 P/Invoke 从 C# 调用。我正在尝试为这个 C 函数定义一个 C# 等效项。 SomeData* DoSomething(); struct SomeData {
这个问题已经有答案了: Why are these constructs using pre and post-increment undefined behavior? (14 个回答) 已关闭 6
我是一名优秀的程序员,十分优秀!