- 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/
这不是我的专业领域,所以我希望问的是正确的问题。 我们有一台滚动租用的服务器。旧服务器是32位windows服务器,新服务器是64位windows 2008 R2 SP1。 其中一个 Web 应用程序
按照目前的情况,这个问题不适合我们的问答形式。我们希望答案得到事实、引用或专业知识的支持,但这个问题可能会引发辩论、争论、投票或扩展讨论。如果您觉得这个问题可以改进并可能重新打开,visit the
我已将 Oracle 数据库从 10g 迁移到 12c。从 12c 开始,oracle 不支持 PLSQL_V2_COMPATIBILITY 参数。 该参数用于: https://www.safari
开发环境db server为SqlServer 2005(开发版) 有什么方法可以确保我的 SQL 查询将在 SqlServer 2000 中运行? 此数据库设置为兼容级别“SQL Server 20
我有一个这种形式的类: public class Foo implements Serializable { private static final long serialVersionUI
我有以下代码来隐藏状态栏,取自 http://developer.android.com/training/system-ui/status.html和 Hide status bar android
我正在尝试测试 .prop() 是否方法存在于当前包含的 jQuery 中(出于兼容性原因): if(typeof $.prop === 'function') 我期望上面的条件是 true对于 jQ
当收到新消息时,我在项目中使用BroadcastChannel更改所有选项卡的标题。 问题在于它仅适用于chrome和firefox。因此,我决定使用localStorage创建一个Broadcast
我正在使用一个函数通过 FTP 将一个文件上传到我的服务器。这是我的代码并且工作正常但是创建的文件 example.json 不兼容 UTF8,因为它有 Atlético 而不是 Atlético 例
我正在使用兼容性类来构建用户代理字符串: public abstract class Compatibility { private static int sdkInt = 0; pr
我需要实现一个 C 例程来(解)压缩 gzip 格式的文件。 谁能举个例子? 我试过 zlib,但它似乎不兼容。 谢谢。 最佳答案 zlib 与 gzip 文件完全兼容,但您需要确保您使用的是面向 g
我正在使用以下 CSS 代码,它与 Chrome 完美兼容,但与 IE 浏览器不兼容 .collapse{ display:block; } .collapse + input[type="c
我的应用程序以 android Sdk 的 v10 为目标,但具有 minSdkVersion 的 v6。默认情况下,“match_parent”属性将用于宽度或高度。我应该为 fill_parent
我正在阅读有关 dynamic_cast 的内容,然后我遇到了以下语句 ( from cplusplus.com ): Compatibility note: This type of dynamic
我正在尝试在 Linux 下使用 QtCreator 构建一个用 VS 2008 编写的项目,但我遇到了很多错误: /home/ga/dev/CppGroup/MonteCarlo/main.cpp:
因此,我正在构建一个网站,用户可以在该网站上上传观看视频。我正在使用标准的 HTML5 视频播放器 ( ... )目前,我使用多个来源:MP4、OGG 和 WEBM,以实现跨浏览器兼容性 由于维护三
mozilla 和其他浏览器是否有类似-webkit-box-reflect 的属性?我无法在谷歌上找到哪些其他浏览器支持这个。因此,如果有人可以告诉我或给我链接,那就太好了。 最佳答案 这不仅可以使
我定义了一个自定义的 ValidateSet 参数属性,如下所示: Class MyValidValuesAttribute : System.Management.Automation.IValid
我使用 .net 4.0、linq 等编写 winforms 应用程序。它可以在带有 .net 2.0 的机器上运行吗? 最佳答案 不,不会。为 Framework 4.0 版编译的应用程序将要求该框
我如何专门检查 @keyframes translate3d 动画 与浏览器的兼容性? 请不要关闭这个问题,因为在问这个问题之前我已经尝试了很多 stackoverflow 解决方案。 我想检查我的网
我是一名优秀的程序员,十分优秀!