环顾四周,我看到的主要是关于解码C++符号而不是如何破坏它们的问题.是的,可以g++使用该-S选项调用包含要修改的符号的一些虚拟代码,然后检查生成的程序集,但是我无法找到关于GCC名称修改的良好引用或规范.我能找到的最接近的东西是http://www.int0x80.gr/papers/name_mangling.pdf,但它似乎没有涵盖名称模板实例化如何被破坏或为什么_Z3fooIN3BarEE3FooIXT_EEv会被翻译成的东西Foo<Bar> foo<Bar>()(尽管我可以善待看看怎么样,但到底是IXT_EE什么?为什么在这个N之后没有_Z?这甚至意味着什么?).
假设我有以下异常过滤器
try {
...
} catch (Exception e) when (e is AggregateException ae && ae.InnerException is ValueException<int> ve || e is ValueException<int> ve) {
...
}
Run Code Online (Sandbox Code Playgroud)
我可以简单地写了两个单独的catch块,但我希望看到一个如何使用模式匹配功能来捕获异常,要么是本身或在一个包裹AggregateException.然而,在这里,编译器抱怨重新定义ve,这是可以理解的.我见过一个模式匹配变量在同一个表达式中重用的情况,如下所示:https://blogs.msdn.microsoft.com/dotnet/2016/08/24/whats-new-in-csharp-7- 0 /
if (o is int i || (o is string s && int.TryParse(s, out i)) { /* use i */ }
Run Code Online (Sandbox Code Playgroud)
所以可能有办法做我想做的事.还是有吗?
通常,可以使用GCC 和 Clang 中的标志从源文件中获取 GCC 的优化汇编器输出,-S如下例所示。
gcc -O3 -S -c -o foo.s foo.c
Run Code Online (Sandbox Code Playgroud)
但是假设我编译所有源文件-O3 -flto以启用链接时整个程序优化,并希望查看最终编译器生成的函数优化程序集,和/或查看代码在哪里/如何内联。
编译的结果是一堆.o文件,正如预期的那样,这些文件实际上是伪装成目标文件的 IR 文件。在链接可执行文件或共享库时,它们会被混合在一起,作为一个整体进行优化,然后编译成目标二进制文件。
但是如果我想要这个过程的汇编输出怎么办?也就是说,在链接时优化之后、在将 IR 编译为程序集期间以及在实际程序集和链接到最终可执行文件之前产生的程序集源。
我尝试简单地向-S链接步骤添加一个标志,但这并没有真正起作用。
我知道反汇编可执行文件是可能的,甚至与源代码交错,但有时查看实际编译器生成的程序集会更好,尤其是使用-fverbose-asm.
就像一个小项目一样,我一直试图做一个小东西,读取序列化的lambdas(本地或从FTP)并调用它们的运行函数作为测试的一部分来试验Windows中的文件关联(即打开某些文件类型)用某个程序打开它们等等,但无论我尝试什么,它似乎都没有正确地反序列化.
lambda被宣布为这样
Runnable r = (Runnable & Serializable) () -> {
// blah blah
// made sure not to capture anything
};
Run Code Online (Sandbox Code Playgroud)
并使用由ObjectOutputStream包装的[n optional] BufferedOutputStream包装的FileOutputStream进行序列化,没有问题.但是,当[在不同的项目中]反序列化时,它会失败,说它无法找到包含序列化代码的封闭类.我已经尝试过各种各样的东西,比如将它们包装在一个可序列化的类中(用于测试目的的是用serialVersionUID = 0L)或者定义一个扩展Runnable和Serializable的接口,但无济于事.
是的,我知道序列化lambda不是很好的做法(或者我们被告知),但我不知道如何将函数和子程序转换成我可以存储为文件或FTP的东西.如果这根本不是正确的方法,请告诉我们.
哦,我正在使用最新版本的Eclipse Luna.
编辑:
像这样反序列化
File f = new File(somePath);
FileInputStream fish = new FileInputStream(f);
BufferedInputStream bos = new BufferedInputStream(fish); // not really necessary
ObjectInputStream ois = new ObjectInputStream(bos);
Runnable r = (Runnable) ois.readObject();
ois.close();
r.run();
Run Code Online (Sandbox Code Playgroud) 使用MethodHandles.Lookup,MethodHandles,MethodTypes等手动创建lambda时,如何实现变量捕获?
例如,没有捕获:
public IntSupplier foo() {
return this::fortyTwo;
}
/**
* Would not normally be virtual, but oh well.
*/
public int fortyTwo() {
return 42;
}
Run Code Online (Sandbox Code Playgroud)
和它的笨拙形式,使用的东西java.lang.invoke:
public IntSupplier foo() {
MethodHandles.Lookup lookup = MethodHandles.lookup();
MethodType methodType = MethodType.methodType(int.class),
lambdaType = MethodType.methodType(IntSupplier.class);
MethodHandle methodHandle = lookup.findVirtual(getClass(), "fortyTwo", methodType);
CallSite callSite = LambdaMetafactory.metafactory(lookup, "getAsInt", lambdaType, methodType, methodHandle, methodType);
return (IntSupplier) callSite.getTarget().invokeExact();
}
/**
* Would not normally be virtual, but oh well. …Run Code Online (Sandbox Code Playgroud) 根据Hoogle的说法,<=<(Kleisli monad组合,或"左鱼")和=<<(反向monad bind)的固定性是infixr 1.如果我正确地看着它们,就像说的那样
print <=< return =<< return "foo"
Run Code Online (Sandbox Code Playgroud)
应该是无效的,因为它等同于同样无效的
print <=< (return =<< return "foo")
Run Code Online (Sandbox Code Playgroud)
但出于某种原因,尽管第一个表达似乎在Haskell中是无效的,正如预期的那样,弗雷格似乎没有抱怨,并<=<在之前进行评估=<<.
当我在pointfree.io上弄乱如何弄清楚如何制作类似的东西时,我发现了这一点
foo >>= (bar <=< baz)
Run Code Online (Sandbox Code Playgroud)
没有点,它给了我
bar <=< baz =<< foo
Run Code Online (Sandbox Code Playgroud)
考虑到固定性,这看起来不太对劲.
(使用Apple LLVM version 8.1.0 (clang-802.0.42) Target: x86_64-apple-darwin16.6.0)
当反汇编编译的一些代码时-O2,我注意到它们中的很多都有一个看似不必要的保存和恢复基指针rbp,通常看起来像下面的
pushq %rbp
movq %rsp, %rbp
...
popq %rbp
Run Code Online (Sandbox Code Playgroud)
我知道这将是什么,但它似乎甚至在似乎完全没有必要的情况下使用,例如在下面的反汇编的复杂身份函数中由 objdump
__Z8identityI5arrayIiLm2EEET_S2_:
60: 55 pushq %rbp
61: 48 89 e5 movq %rsp, %rbp
64: 48 89 f8 movq %rdi, %rax
67: 5d popq %rbp
68: c3 retq
69: 0f 1f 80 00 00 00 00 nopl (%rax)
Run Code Online (Sandbox Code Playgroud)
其中只有两个有意义的指令来自移动rdi到rax(第一自变量返回寄存器)和明显必要retq(I假设nopl为填充或对准用于任何如下).
这种看似不必要的背景保存是否有原因?
在像非专用模板struct pointer_traits(即template <class Ptr> struct pointer_traits)这样的类型中,存在一个成员别名模板rebind,该模板定义为Ptr::rebind<U>,如果存在,则为其他类型。尽管我在检查某个成员是否存在时看到了一些答案,但是如何实现一个“条件”别名模板,如pointer_traits::rebind?也就是说,就像通过以下伪C ++:
template <typename T> using type = has_type<T::U> ? int : float;
Run Code Online (Sandbox Code Playgroud)
要么
template <typename T> using type = if_has_type<T::U, int, float>::type;
Run Code Online (Sandbox Code Playgroud)
我考虑使用类似https://en.wikibooks.org/wiki/More_C%2B%2B_Idioms/Member_Detector(“检测成员类型”一节)中描述的方法,但是我不知道如何实现其帮助结构[唯一]成员类型取决于另一个成员类型的存在。
x86_64 有一条指令movdir64b,据我了解,它是 64 字节(高速缓存行)的非临时副本(好吧,至少是存储)。AArch64 似乎有类似的指令st64b,它执行相同大小的原子存储。但是,官方 ARMv9 文档并不清楚 是否st64b也是非临时存储。
英特尔的指令集参考文档要movdir64b详细得多,但我的研究还不够深入,无法完全理解每种内存类型协议所代表的含义。
据我目前所知, x86_64 指令movntdq大致相当于stnp, ,并且是写组合。由此看来,似乎就像movdir64b一个原子存储中的四个,因此我对 的猜测st64b。
这几乎肯定是对实际情况的过度简化(当然,可能是错误/不准确的),但这是迄今为止可以推断出的。
是否st64b可以将其视为四个stnp指令的原子序列,以这种方式作为缓存行的非临时写入?
如果我没记错的话,函数必须是CLR世界中一个类的成员,然而在C++/CLI中可以实现全局函数.这是否意味着这些全局函数是某种隐藏的"全局"类的一部分?如果是这样的话,为了反思的目的,如何获得它的类型呢?