在本文中,以下是一段可以触发除零的代码示例:
if (arg2 == 0)
ereport(ERROR, (errcode(ERRCODE_DIVISION_BY_ZERO),
errmsg("division by zero")));
/* No overflow is possible */
PG_RETURN_INT32((int32) arg1 / arg2);
Run Code Online (Sandbox Code Playgroud)
ereport
这是一个宏,它扩展为对 - bool
返回函数的调用,该函数errstart
可能会或可能不会返回,并且?:
对其返回值有条件(使用a ),调用另一个函数.在这种情况下,我认为ereport
水平ERROR
无条件地导致longjmp()
其他地方.
因此,对上述代码的简单解释是,如果arg2
非零,则将发生除法并返回结果,而如果arg2
为零,则将报告错误并且不会发生除法.然而,链接的论文声称C编译器可以在零检查之前合法地提升除法,然后推断零检查从未被触发.他们唯一的推理似乎是不正确的
程序员没有通知编译器对ereport的调用(ERROR,:: :)没有返回.这意味着除法将始终执行.
John Regehr有一个更简单的例子:
void bar (void);
int a;
void foo3 (unsigned y, unsigned z)
{
bar();
a = y%z;
}
Run Code Online (Sandbox Code Playgroud)
根据这篇博文,clang在调用之上提升了模运算bar
,并且他展示了一些汇编代码来证明它.
我对C的理解是适用于这些片段的
没有或不可以返回的函数在标准C中是格式良好的,并且这样的声明不需要特定的属性,钟声或哨声.
调用不返回或不返回的函数的语义是明确定义的,特别是通过C99中的6.5.2.2"函数调用".
由于ereport
调用是一个完整的表达式,因此有一个序列点;
.类似地,由于bar
John Regehr的代码中的调用是一个完整的表达式,因此在该处有一个序列点 …
2 1
1----------2---------4
| | |
|3 |3 |1
| 6 | |
3---------5 ---------
Run Code Online (Sandbox Code Playgroud)
好的,这就是图表.我的源节点是1
和目标节点5
我的问题是.
算法是否会提供相同的输出?也就是说,双方都会回归1->2->4->5
吗?(除非在dijkstra中不允许负权重)
在此先感谢您的帮助.
假设我在一般位置有n个线段.对于我的每个n段,我如何快速计算它相交的其他n-1的数量?
我可以在O(n 2)时间内天真地做这件事.我可以在O((n + k)log n)时间内使用相当简单的扫描线算法(Bentley-Ottmann)找到所有交叉点,其中k是这样的交叉点的数量,然后将我发现的交叉点聚合成一堆计数.
不过,我不需要找到交叉路口; 我只是想知道有多少.我没有看到如何将扫描线算法修改得更快,因为它需要为每个交叉点重新排序树中的两个东西,我想不出任何其他没有遇到同样问题的技术.
我也有兴趣听听如何计算总交叉口数量.
在询问"如何实现符合严格别名规则的memcpy函数"时,一般的答案就是这样的
void *memcpy(void *dest, const void *src, size_t n)
{
for (size_t i = 0; i < n; i++)
((char*)dest)[i] = ((const char*)src)[i];
return dest;
}
Run Code Online (Sandbox Code Playgroud)
但是,如果我理解正确的话,编译器可以自由地重新排序对memcpy的调用并访问dest,因为它可以使用任何其他指针类型的读取重新排序写入char*(严格的别名规则阻止仅对char*的读取进行重新排序)到任何其他指针类型).
这是正确的,如果是的话,有没有办法正确实现memcpy,还是我们应该依赖内置的memcpy?
请注意,这个问题不仅涉及memcpy,还涉及任何反序列化/解码功能.
以下模式在许多软件中很常见,这些软件想告诉用户它做了多少事情:
int num_times_done_it; // global
void doit() {
++num_times_done_it;
// do something
}
void report_stats() {
printf("called doit %i times\n", num_times_done_it);
// and probably some other stuff too
}
Run Code Online (Sandbox Code Playgroud)
不幸的是,如果多个线程可以在doit
没有某种同步的情况下调用,则并发读取 - 修改 - 写入num_times_done_it
可能是数据争用,因此整个程序的行为将是未定义的.此外,如果report_stats
可以在doit
没有任何同步的情况下同时调用,则在线程修改num_times_done_it
和报告其值的线程之间存在另一个数据争用.
通常,程序员只想要doit
尽可能少的开销来调用大多数正确的次数.
(如果你认为这个例子是微不足道的,Hogwild!比使用基本上这个技巧的数据无竞争随机梯度下降获得了显着的速度优势.而且,我相信Hotspot JVM正是这种无人看守,多线程访问共享计数器对于方法调用计数---虽然它是明确的,因为它生成汇编代码而不是C++ 11.)
明显的非解决方案:
volatile
到组合,使数据的比赛好了,更换的声明num_times_done_it
由volatile int num_times_done_it
不能解决任何事情.report_stats
,但这并不能解决doit
和之间的数据竞争report_stats
.此外,它很乱,它假设更新是关联的,并不真正适合Hogwild!的用法.是否有可能在一个非平凡的多线程C++ 11程序中实现具有良好定义语义的调用计数器,而无需某种形式的同步?
编辑:似乎我们可以使用memory_order_relaxed
以下方式稍微间接地执行此操作:
atomic<int> num_times_done_it;
void doit() …
Run Code Online (Sandbox Code Playgroud) 这是对C++实现的一种后续行为,理论上可以并行化两个函数参数的评估吗?
假设我有以下C++ 11程序:
#include <cstdio>
using std::printf;
int g() { printf("1\n"); printf("3\n"); return 2; }
int h() { printf("2\n"); printf("4\n"); return 3; }
void f(int a, int b) { printf("%i\n", a+b); }
int main() { f(g(), h()); }
Run Code Online (Sandbox Code Playgroud)
当然可以观察到以下输出:
1 3 2 4 5
2 4 1 3 5
Run Code Online (Sandbox Code Playgroud)
1 2 3 4 5怎么样?
(据我所知,唯一的限制是1在3之前测序,2在4之前测序,3和4在5之前测序)
我是Cucumber java的新手,并且在初始阶段存在此问题:由于某种原因,我没有使用MAVEN项目。我刚刚在eclipse中创建了一个简单的Java项目。
我的功能位于“ src / dummy / pkg / features”下,我的实现“ StepDef.java”位于“ src / dummy / pkg / features / implementation”下
我已经为“给定”,“何时”和“然后”编写了步骤定义,但是当我运行功能文件时,它无法识别实现。如何将功能与步骤定义链接?
我写了一个简单的程序,以为我可以从反汇编中找到:
int main() {
double a, b, c;
scanf("%lf %lf %lf", &a, &b, &c);
__float128 foo = a;
foo += b; foo += c;
printf("%f\n", (double)foo);
}
Run Code Online (Sandbox Code Playgroud)
main
编译(-O3)为以下内容:
400630: 48 83 ec 38 sub $0x38,%rsp
400634: bf 34 08 40 00 mov $0x400834,%edi
400639: 31 c0 xor %eax,%eax
40063b: 48 8d 4c 24 28 lea 0x28(%rsp),%rcx
400640: 48 8d 54 24 20 lea 0x20(%rsp),%rdx
400645: 48 8d 74 24 18 lea 0x18(%rsp),%rsi
40064a: e8 c1 ff ff ff callq …
Run Code Online (Sandbox Code Playgroud) 为什么在使用开放寻址作为冲突解决技术和线性探测的散列中的主聚类上下文中,接下来填充 i 个满槽的空槽的概率是 (i + 1)/m?这是算法简介 CLRS 的摘录“占用槽的长运行会累积,增加平均搜索时间。簇的出现是因为前面有 i 个满槽的空槽接下来会以 (i + 1)/m 的概率填充。长运行占用的槽位往往会变长,平均搜索时间也会增加。” 请帮忙。
c++ ×4
algorithm ×2
c ×2
c++11 ×2
cucumber ×1
cucumber-jvm ×1
gcc ×1
geometry ×1
hash ×1
java ×1
memcpy ×1
memory-model ×1
networking ×1