我正在研究一种在运行时生成汇编代码的软件.例如,这是一个非常简单的函数,它生成用于调用GetCurrentProcess函数的汇编代码(对于Win64 ABI):
void genGetCurrentProcess( char *codePtr, FARPROC addressForGetCurrentProcessFunction )
{
#ifdef _WIN64
// mov rax, addressForGetCurrentProcessFunction
*codePtr++ = 0x48
*codePtr++ = 0xB8;
*((FARPROC *)codePtr)++ = addressForGetCurrentProcessFunction;
// call rax
*codePtr++ = 0xFF;
*codePtr++ = 0xD0;
#else
// mov eax, addressForGetCurrentProcessfunction
*codePtr++ = 0xB8;
*((FARPROC *)codePtr)++ = addressForGetCurrentProcessFunction;
// call eax
*codePtr++ = 0xFF;
*codePtr++ = 0xD0;
#endif
}
Run Code Online (Sandbox Code Playgroud)
通常我会使用内联汇编程序,但唉 - 这似乎不再适用于64位MSVC编译器.虽然我在这 - 我的代码应该与MSVC6一起使用到MSVC10和MinGW.还有更多的函数,比如genGetCurrentProcess,它们都发出汇编代码,其中许多都得到函数指针,可以作为参数传递.
令人烦恼的是,修改此代码很容易出错,我们必须手动处理ABI特定的事情(例如,在调用寄存器溢出函数之前保留32字节的堆栈空间).
所以我的问题是 - 我可以简化这段代码以便在运行时生成汇编程序代码吗?我的希望是我可以以某种方式直接编写汇编程序代码(可能在一个外部文件中然后用ml/ 汇编ml64)但是我不清楚如果汇编代码中的某些字节只在运行时知道它会如何工作(addressForGetcurrentProcessFunction例如,上例中的值).也许可以组装一些代码但是为代码中的某些位置分配"标签",以便我可以在运行时轻松修改代码然后将其复制到我的缓冲区中?
我最近一直在研究Haskell,从另一种观点来看,这似乎是一种非常好的方式来观察编程问题 - 至少可以替代我通常的命令(我有一个强大的C++背景)视图.
但是,我看到的所有文章似乎都处理了相同类型的编程问题:
我想通过编写一些GUI应用程序来自己尝试Haskell.因此,我想知道:在像Haskell这样的函数式编程语言中编写像GUI这样的事件驱动系统是否有意义?或者这是命令式语言优秀的问题领域?不幸的是,我仍然需要相当长的时间才能将我的想法转变为"功能"模式,所以我很难决定反对或赞成使用函数式编程语言来实现事件驱动的系统.
我也对在Haskell中实现的GUI应用程序(或一般的事件驱动系统)的示例感兴趣.
events user-interface haskell functional-programming event-handling
我想写一个模板函数
template <typename T>
void f( T v );
Run Code Online (Sandbox Code Playgroud)
v如果它足够小,将通过值传递,否则通过引用到const传递.为此,我使用了一个小帮手
template <typename T, bool>
struct parameter_helper;
template <typename T>
struct parameter_helper<T, true> {
typedef T type;
};
template <typename T>
struct parameter_helper<T, false> {
typedef const T& type;
};
template <typename T>
struct parameter {
typedef typename parameter_helper<T, sizeof(T) <= sizeof(void*)>::type type;
};
Run Code Online (Sandbox Code Playgroud)
在过去,我可以拥有
template <typename T>
void f( typename parameter<T>::type v );
Run Code Online (Sandbox Code Playgroud)
现在,在C++ 11中:这种辅助模板是否仍然有意义,还是有更好的方法来实现相同的效果?可能已经有现成的模板吗?我检查过<type_traits>但无法发现任何看似相关的东西.
我再次阅读git-blame手册页并注意到这一部分:
一种特别有用的方法是查看添加的文件是否具有通过现有文件的复制和粘贴创建的行.有时这表明开发人员很草率,并没有正确地重构代码.您可以先找到引入该文件的提交:
git log --diff-filter = A --pretty = short - foo
然后使用commit ^注释提交及其父项之间的更改!符号:
git blame -C -C -f $ commit ^! - foo
这听起来很有趣,但我不太了解它是如何工作的,以及为什么.我想知道是否可以在git钩子中使用它来检测复制和粘贴的代码.
有些git专家可以解释一起使用上面的git命令的效果,以及是否可以使用类似的东西来使git显示是否存在代码重复(可能使用git似乎在重命名文件时计算的'相似性索引') )?
更新:我添加了这个问题的答案,其中包含了几乎所有已经给出的建议.下面代码中给出的原始模板需要45605ms才能完成真实世界的输入文档(关于脚本编程的英文文本).社区维基回答中的修订模板将运行时间降至605毫秒!
我正在使用以下XSLT模板将字符串中的一些特殊字符替换为其转义变体; 它使用分而治之的策略递归调用自己,最终查看给定字符串中的每个字符.然后它决定是否应该按原样打印字符,或者是否需要任何形式的转义:
<xsl:template name="escape-text">
<xsl:param name="s" select="."/>
<xsl:param name="len" select="string-length($s)"/>
<xsl:choose>
<xsl:when test="$len >= 2">
<xsl:variable name="halflen" select="round($len div 2)"/>
<xsl:variable name="left">
<xsl:call-template name="escape-text">
<xsl:with-param name="s" select="substring($s, 1, $halflen)"/>
<xsl:with-param name="len" select="$halflen"/>
</xsl:call-template>
</xsl:variable>
<xsl:variable name="right">
<xsl:call-template name="escape-text">
<xsl:with-param name="s" select="substring($s, $halflen + 1)"/>
<xsl:with-param name="len" select="$halflen"/>
</xsl:call-template>
</xsl:variable>
<xsl:value-of select="concat($left, $right)"/>
</xsl:when>
<xsl:otherwise>
<xsl:choose>
<xsl:when test="$s = '"'">
<xsl:text>"\""</xsl:text>
</xsl:when>
<xsl:when test="$s = '@'">
<xsl:text>"@"</xsl:text>
</xsl:when>
<xsl:when …Run Code Online (Sandbox Code Playgroud) 在我的应用程序中,我正在挂钩创建COM对象的各种函数(例如CoCreateInstanceEx),以便在创建某个对象时得到通知.我正在跟踪所有创建的对象std::list,我正在迭代该列表以执行各种操作(例如检查已激活的OLE对象).
这个问题是,现在,每当添加一个IUnknown指向我的列表的指针时,我会调用IUnknown::AddRef它以确保它在我跟踪它时不会被破坏.这不是我真正想要的; 对象的生命周期应该与没有我的跟踪代码一样长(或短),所以我宁愿保持对象的弱引用.每当删除对某个跟踪的COM对象的最后一个引用(因此对象被销毁)时,我希望得到通知,以便我可以更新我的簿记(例如,通过在我的列表中设置指针NULL).*
最好的方法是什么?现在,我正在修补所有创建对象的(第一个)VTable,以便IUnknown::Release通过第一个vtable 的调用得到通知.但是,这不适用于从多个接口继承的COM接口(因此有多个vtable),但我不确定这是否真的是一个问题:给定实现QueryInterface的规则,应该总是只IUnknown返回一个用IUnknown::QueryInterface,对不对?所以我可以做到这一点然后修补那个vtable.
此外,这种方法也有点毛茸茸,因为它涉及创建产生一些代码的thunk.到目前为止我只为32位实现了这个.这不是一个大问题,但仍然存在.
我真的想知道是否有一种更优雅的方式来对COM对象进行弱引用.有人知道吗?
*:我要解决的下一件事是,如果我有活动迭代器(我使用自定义迭代器对象)遍历COM对象列表,那么这项工作正常.我可能需要跟踪活动迭代器,一旦完成最后一个迭代器,从列表中删除所有空指针.或类似的东西.
我正在尝试编写ActiveX控件,并注意到我似乎无法在Visual Basic(6.0)中创建一个ActiveX控件,它具有稍微复杂的控件.像标签,按钮和复选框这样的简单控件似乎工作正常,但是一旦我尝试将树控件添加到我的表单中,一旦我将其嵌入到另一台计算机上的某个主机应用程序中,ActiveX控件就会一直保持空白.它在我的开发盒上工作正常.
在浏览Projects-> Components(Ctrl + T)列表时,我发现了两个显然包含树控件的库:
只要我将这些库中的任何控件添加到我的表单中,当嵌入到另一台计算机上时,该表单将保持完全灰色.另一台计算机是一个Windows XP系统,所以我希望丢失的可再发行组件不会成为一个问题,因为Visual Basic 6有多大.可以肯定的是,我安装了VB6可再发行组件,但不幸的是,这并没有什么区别.
有没有人知道为什么我的ActiveX控件会在其他计算机上保持灰色,但不是我的,只要我将上述库中的任何控件添加到我的表单中?FWIW我只需要树控制,所以如果有其他更合适的库可用 - 这对我来说没问题.
更新:
事实证明,它有助于将MSCOMCTL.OCX下载到另一台计算机上的C:\ WINDOWS\SYSTEM32中,然后通过注册它regsvr32 C:\WINDOWS\SYSTEM32\MSCOMCTL.OCX.但是,我没有找到此文件的官方来源,并且手动运行COM注册看起来很麻烦.真的没有我可以使用的可再发行组件吗?
考虑这个程序:
#include <stdio.h>
int main() {
printf("%s\n", __FILE__);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
根据文件的名称,该程序可以工作 - 或不工作.我面临的问题是我想以编码安全的方式打印当前文件的名称.但是,如果文件具有无法在当前代码页中表示的有趣字符,编译器会发出警告(这是正确的):
?????????.c(3) : warning C4566: character represented by universal-character-name '\u043F' cannot be represented in the current code page (1252)
Run Code Online (Sandbox Code Playgroud)
我该如何解决这个问题?我想存储由__FILE__例如UTF-16 给出的字符串,以便我可以在运行时在任何其他系统上正确打印它(通过将存储的UTF-16表示转换为运行时系统使用的任何表示).为此,我需要知道:
__FILE__?看来,至少在Windows上,使用了当前的系统代码页(在我的例子中是Windows-1252) - 但这只是猜测.这是真的?我的真实生活用例:我有一个跟踪当前程序执行的宏,将当前源代码/行号信息写入文件.它看起来像这样:
struct LogFile {
// Write message to file. The file should contain the UTF-8 encoded data!
void writeMessage( const std::string &msg );
};
// Global function which returns a pointer to the 'active' log file.
LogFile *activeLogFile(); …Run Code Online (Sandbox Code Playgroud) 我正在尝试在我正在启动的某个过程中检测对CoCreateInstance的所有调用(理想情况下,我也能够检测子进程中的调用).
为了实现这一点,在Windows 7上使用Microsoft Visual Studio 2008,我创建了一个代理DLL,它在标准ole32.dll库中转发除一个调用之外的所有调用,如各种文章中所述,例如
Intercepted:Windows Hacking via DLL Redirection.生成的DLL看起来很好,但我只是不能使现有的程序(我使用标准的ActiveX控件测试容器(tstcon32.exe)作为测试应用程序)拿起我的代理DLL.无论我做什么,程序似乎总是C:\Windows\SysWow64\ole32.dll根据Process Explorer获取.到目前为止,我尝试了一些方法:
PATH然后调用该程序; 似乎没有任何影响..local如动态链接库重定向文章中所述,在与调用的程序相同的目录中创建一个文件,并将我的代理DLL放入同一目录中 - 也不起作用.但后来,我读到这停止了更新的Windows版本.另外,ole32.dll根据HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\KnownDLLs注册表设置是一个"已知的DLL" ,所以.local基于重定向可能无论如何都不会起作用.有没有人有重定向标准DLL调用的经验,比如ole32.dll使用存根DLL?你是如何强制应用程序获取存根DLL的?
在这种反应到另一个问题,被赋予了小Haskell代码草图,它使用的包装函数分解出做语法检查命令行参数的一些代码.这是我试图简化的代码部分:
takesSingleArg :: (String -> IO ()) -> [String] -> IO ()
takesSingleArg act [arg] = act arg
takesSingleArg _ _ = showUsageMessage
takesTwoArgs :: (String -> String -> IO ()) -> [String] -> IO ()
takesTwoArgs act [arg1, arg2] = act arg1 arg2
takesTwoArgs _ _ = showUsageMessage
Run Code Online (Sandbox Code Playgroud)
有没有办法(可能使用Template Haskell?)来避免为每个参数编写额外的函数?理想情况下,我希望能够编写类似的东西(我正在编写这种语法)
generateArgumentWrapper<2, showUsageMessage>
Run Code Online (Sandbox Code Playgroud)
并扩展到
\fn args -> case args of
[a, b] -> fn a b
_ -> showUsageMessage
Run Code Online (Sandbox Code Playgroud)
理想情况下,我甚至可以为generateArgumentWrapper元函数提供可变数量的参数,这样我就能做到
generateArgumentWrapper<2, asInt, …Run Code Online (Sandbox Code Playgroud)