首页 > 解决方案 > 发送参数地址是否安全?

问题描述

考虑以下代码片段:

void read_write(unsigned* ptr, bool r_or_w) {
    if (r_or_w) {
        *ptr = read_from_device_register();
    } else {
        write_to_device_register(*ptr);
    }
}

unsigned read(void) {
    unsigned data = 0;
    read_write(&data, 1);
    return data;
}

void write(unsigned data) {
    read_write(&data, 0); // <--- sending address of received argument
}

具体来说,考虑void write(unsigned data)发送一个指向它作为参数接收的值的指针的事实。

比较:

void write(unsigned w_data) {
    unsigned data = w_data;
    read_write(&data, 0); // <--- sending address of local variable
}

在这两种情况下data都存储在堆栈中,只有在第一种情况下data存储在调用者的调用帧中,而不是作为局部变量存储在被调用者中。安全吗?有什么陷阱吗?如果有的话,它有多普遍?

标签: cfunctionargumentsparameter-passing

解决方案


这里的生命周期没有问题,只要read_write不将指针存储在可以比框架中的指针data寿命write更长的地方。因此,从程序正确性的角度来看,这是安全的。事实上,给定的两个选项之间没有区别——传入参数的地址可以像获取局部变量的地址一样被获取。至于在write's 调用者的框架中修改变量的问题,这也无关紧要 -data是按值传递的。

但是,如果经常调用函数或在紧密循环中调用函数,则无符号整数的指针间接可能会产生很大的开销。

此外,从设计的角度来看,这似乎是一个笨拙的设计,有点难以阅读。最终委托给的write代表。直观地遵循这有点尴尬,并且不必要地将读取和写入路径混合在一起只是为了让它们再次发散;这可能是不安全的,因为与更简单的设计相比,代码更脆弱且更容易维护错误。read_writewrite_to_device_register


推荐阅读