SIOF

SIOF 是static initialization order fiasco的缩写,涉及的问题为初始化顺序;

下面为 stack overflow 中 Hans Passant 的解释:

SIOF is very much a runtime artifact, the compiler and linker don't have much to do with it. Consider the atexit() function, it registers functions to be called at program exit. Many CRT implementations have something similar for program initialization, let's call it atinit().

Initializing these global variables requires executing code, the value cannot be determined by the compiler. So the compiler generates snippets of machine code that execute the expression and assigns the value. These snippets need to be executed before main() runs.

That's where atinit() comes into play. A common CRT implementation walks a list of atinit function pointers and execute the initialization snippets, in order. The problem is the order in which the functions are registered in the atinit() list. While atexit() has a well defined LIFO order, and it is implicitly determined by the order in which the code calls atexit(), such is not the case for atinit functions. The language specification doesn't require an order, there is nothing you could do in your code to specify an order. SIOF is the result.

One possible implementation is the compiler emitting function pointers in a separate section. The linker merges them, producing the atinit list. If your compiler does that then the initialization order will be determined by the order in which you link the object files. Look at the map file, you should see the atinit section if your compiler does this. It won't be called atinit, but some kind of name with "init" is likely. Taking a look at the CRT source code that calls main() should give insight as well.

使用代码测试:
file1.cpp

extern int x;
int y = x + 1;


file2.cpp

extern int y;
int x = y + 1;

main.cpp

#include <stdio.h>
#include <stdlib.h>

extern int x;
extern int y;

int main()
{
    printf("x : %d, y : %d\n", x, y);
    return 0;
}

liuzebo@ubuntu:/mnt/hgfs/Workspace/SnippetTest/siof$ g++ main.o file1.o file2.o -o main
liuzebo@ubuntu:/mnt/hgfs/Workspace/SnippetTest/siof$ ./main
x : 2, y : 1
liuzebo@ubuntu:/mnt/hgfs/Workspace/SnippetTest/siof$ g++ main.o file2.o file1.o -o main
liuzebo@ubuntu:/mnt/hgfs/Workspace/SnippetTest/siof$ ./main
x : 1, y : 2


### 三菱FX3U PLC项目案例与实际应用 #### 高速计数器的实际应用场景 在工业自动化领域,三菱FX3U系列PLC的高速计数功能被广泛应用于各种场景。例如,在包装机械中,可以通过配置AB相双向计数模式来实现精确的位置控制[^1]。这种模式能够有效减少因电磁干扰引起的误计数现象。 以下是基于三菱FX3U PLC的一个简单高速计数程序示例: ```plc ; 初始化设置 LD X0 ; 启动信号输入 OUT C200 H ; 复位高速计数器C200 ; 开始计数 SET C200 M100 ; 设置M100作为启动条件触发计数器C200 ; 判断计数值并执行动作 MOV K100 D0 ; 将目标值K100写入数据寄存器D0 CMP EQ D0 C200 Y0 ; 当计数值等于设定值时,输出Y0置位 ``` 此代码片段展示了如何利用三菱FX3U的内置高速计数器完成特定数量的产品检测任务。 --- #### FX3U与485继电器模块通信的应用实例 除了高速计数外,三菱FX3U还支持与其他外部设备(如RS-485继电器模块)进行串口通信。以下是一个典型的开关控制例子,其中涉及发送命令帧以操作远程继电器的状态[^2]。 假设需要通过PLC开启连接到首个继电器模块上的负载,则可以编写如下梯形图逻辑: ```plc ; 定义变量 DM W0 :="AA"; DM W1 := "00"; DM W2 := "02"; DM W3 := "01"; DM W4 := "BB"; ; 发送指令至端口 CALL SIOF ; 调用标准异步传输子程序 INSTR DATA:=W0, LENGTH:=5, PORT:=S0 ; ``` 以上脚本说明了怎样构建完整的十六进制字符串并通过指定通道传递给目标硬件单元。 --- #### 综合工程实例分析 综合来看,三菱FX3U不仅具备强大的本地I/O处理能力,而且还能轻松集成第三方组件形成复杂控制系统。比如某饮料灌装线可能同时运用到了上述提到的功能——一方面依靠高精度传感器配合PLCs内部定时/计数机制监控容器移动轨迹;另一方面借助MODBUS RTU协议管理阀门启闭状态从而确保液体注入量恒定不变。 此类跨学科解决方案往往能显著提升生产效率降低成本开支同时也增强了系统的灵活性适应更多样化的市场需求变化趋势。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值