给出以下代码:
oc tag docker-registory.svc:5000/myproject/myapp@sha256:231d3371ad687233f7a6140c67a314c416105b424c19f28b124ca298989998b3 myproject/myapp:test
Tag myapp:test set to docker-registory.svc:5000/myproject/myapp@sha256:231d3371ad687233f7a6140c67a314c416105b424c19f28b124ca298989998b3.
root@018fdb569d8a:/# oc get is
NAME DOCKER REPO TAGS UPDATED
myapp docker-registory.svc:5000/myproject/myapp latest,test 5 minutes ago
root@018fdb569d8a:/# oc describe is
Name: myapp
Namespace: myproject
Created: 7 minutes ago
Labels: app=myapp
Description: Keeps track of changes in the application image
Annotations: openshift.io/generated-by=OpenShiftNewApp
openshift.io/image.dockerRepositoryCheck=2019-01-07T03:44:42Z
Docker Pull Spec: docker-registory.svc:5000/myproject/myapp
Image Lookup: local=false
Unique Images: 1
Tags: 2
latest
no spec tag
docker-registory.svc:5000/myproject/myapp@sha256:231d3371ad687233f7a6140c67a314c416105b424c19f28b124ca298989998b3
5 minutes ago
test
tagged from docker-registory.svc:5000/myproject/myapp@sha256:231d3371ad687233f7a6140c67a314c416105b424c19f28b124ca298989998b3
! error: Import failed (InternalError): Internal error occurred: Get https://docker-registory.svc:5000/v2/: x509: certificate signed by unknown authority
鉴于unsigned int global_flag = 0;
void exception_handle()
{
global_flag = 1;
}
void func()
{
/* access will cause exception which will assign global_flag = 1
then execution continues */
volatile unsigned int x = *(unsigned int *)(0x60000000U); /* memory protection unit configured to raise exception upon accessing this address */
if (global_flag == 1)
{
/* some code */
}
}
must not be reordered across sequence points:
最低要求是所有先前的序列点 对易失性对象的访问已稳定,此后没有任何访问 发生访问
给出有关sequence points的以下信息:
序列点出现在以下位置...(1)..(2)..(3)完整表达式的结尾。此类别包括表达 语句(例如赋值 a = b ;),返回语句, 控制 if 的表达式,switch,while或do-while语句, 以及for语句中的所有三个表达式。
是否已承诺volatile
将在volatile unsigned int x = *(unsigned int *)(0x60000000U);
之前发生(在二进制asm中,CPU的无序执行在这里不相关)?
根据以上引用,if (global_flag == 1)
必须在下一个序列点结束之前进行评估,并且volatile unsigned int x = *(unsigned int *)(0x60000000U);
本身就是一个序列点,因此这意味着每个volatile unsigned int x = *(unsigned int *)(0x60000000U);
分配在分配时间进行评估?
如果以上问题的答案为否,则下一个序列点位于volatile
的末端,是否表示可以执行类似的操作?
if
系统是嵌入式单ARM cortex m0,单核,单线程应用程序。
答案 0 :(得分:2)
是否已承诺volatile unsigned int x = *(unsigned int *)(ILLEGAL_ADDRESS);将在if(global_flag == 1)之前发生
来自内容丰富的C11 AnnexC(添加了换行符/格式以提高可读性):
以下是5.1.2.3中描述的顺序点:
...
-在评估一个完整表达式和下一个要评估的完整表达式之间。
-以下是完整的表达方式:
-不属于复合文字(6.7.9)的初始化程序;
-表达式语句中的表达式(6.8.3);
-选择语句(if或switch)的控制表达式(6.8.4);
-while或do语句的控制表达式(6.8.5);
-for语句(6.8.5.3)的每个(可选)表达式;
-return语句(6.8.6.4)中的(可选)表达式。
由于*(unsigned int *)(ILLEGAL_ADDRESS);
是一个初始化程序(赋值表达式),并且该初始化程序不是复合文字的一部分,因此它是一个完整表达式。下一个完整表达式是if
中的控制语句,因此在if
和x
的初始化之间有一个序列点。
来自著名的C11 5.1.2.3p6:
符合标准的实现的最低要求是:
严格根据抽象机的规则评估对易失对象的访问。
...
由于x
是一个易失对象,因此严格地将其初始化为抽象机,因此在序列点之后,它的右值必须等于*(unsigned int *)(ILLEGAL_ADDRESS)
操作的结果。
是的,x
对象的初始化必须在if
内部的控件表达式之前进行。
关于未定义的行为,引自C11 6.5.3.2p4:
如果已将无效值分配给指针,则一元*运算符的行为是不确定的。
您评论过:
我的系统内存模型中不允许访问地址0x60000000
可以推断出(unsigned int*)0x60000000
是无效的指针,因此一元*运算符应该spawn dragons。
答案 1 :(得分:2)
在您的代码段中,变量global_flag
不易失,因此没有什么可以阻止编译器跨序列点移动对global_flag
的访问,或者在环境允许的情况下完全删除它。谈论访问x
和访问global_flag
的顺序是没有意义的,因为后者不是一个可观察到的事件,只有前者是可见的。
(还请注意,表达式volatile
中没有*(unsigned int *)(0x60000000U)
限定符。我认为确实是您要特别对待的表达式,但是您的代码却没有这样做。编译器是允许产生事先对*(unsigned int *)(0x60000000U)
进行评估的代码,然后在其板上进行大量其他处理,然后将获得的值分配给x
,这将满足C的约束标准放在volatile
左值上。)
如果您的代码段中包含unsigned int volatile global_flag = 0;
和*(volatile unsigned int *)(0x60000000U)
,那么“是否答应……”这个问题的答案将是明确的“是”。