我对C很新,基本上都是其他所有低级别的东西。我遇到了一段代码并且无法自己弄清楚:(我是从here发现的)
int main(){
void (*i_am_bleeding)() = (void(*)())15;
i_am_bleeding();
return 0;
}
这篇文章用它来支持这个论点:
由于没有被批评,C正遭受批评 应用程序编程语言的特征,例如 保护普通程序员免受尖锐的伤害 工具。
然而,作者没有解释其背后的原因,也没有在网上其他地方找到解释。我试图在我的机器上编译并运行代码。它只给了我一个“Segmentation fault(core dumped)”错误。
那么,有人能告诉我执行代码时我的机器发生了什么,以及这样做的危险吗?
答案 0 :(得分:4)
那么,有人能告诉我执行代码时我的机器发生了什么,以及这样做的危险吗?
在C中,运行未由C规范定义的格式错误的代码是未定义的行为 - UB。 15
不知道是函数的有效地址 - 因此赋值没有指定的行为。执行它的下一行也是UB。 C 允许编写这样的代码,可能甚至编译。然而,由于没有具体说明这种行为,因此这样做的危险性很大。 (运行可执行文件)是您的计算机可以做任何事情。通常代码会简单崩溃。
void (*i_am_bleeding)() = (void(*)())15; // UB
i_am_bleeding(); // UB
C正受到批评的强烈反对......C是44岁以上。它以前受到高度批评。它可能会在几十年后受到批评 - 并且仍在使用中。
答案 1 :(得分:2)
代码声明了一个变量i_am_bleeding
,其类型为:一个函数,它接受一个未指定数量的参数并且不返回任何内容(void
)。然后取数字15
,将其转换为上述类型并将其分配给i_am_bleeding
。第三行然后调用该函数。
这里的问题是地址15
的内存很可能不包含有效函数,因此不应该作为一个调用。在原始操作系统中,这可能导致程序执行任何未指定的数据驻留在15
,就好像它是代码一样,这显然是一个安全漏洞。然而,在几乎所有(现代)操作系统中,结果是segmentation fault
(程序以不应该的方式使用一块内存)并且程序被杀死。
这段代码不是C的危险的一个很好的例子。代码不符合语言规范并展示未定义的行为,这意味着编译器/主机环境可以自由地执行他们想要的操作。
强制转换(void(*)())
告诉编译器'这可能看起来不对,但我知道我在做什么,所以无论如何'并且编译器有责任。如果没有那个演员,大多数编译器都会拒绝编译,或者至少会发出警告,告诉你它看起来不对。
C旨在实现(特别是Unix)中的操作系统,因此对于编写用户级应用程序并不总是实用的。但批评它是为了批评大锤,因为它不适合挂画。