c - 安全的 C 编程

标签 c memory

我注意到我的 C 编译器 (gcc) 可以让我执行以下操作:

#include <stdio.h>
main(){
    short m[32768];
    short y = -1;
    short z = -1;
    printf("%u\n", y);
    m[y] = 12;
    printf("%d\n%d\n", y, m[z]);
}

当我运行它时它会吐出来:

4294967295
12
12

这对我来说似乎有点莫名其妙。

首先,运行这样的程序对我来说安全吗?我是否有可能意外覆盖操作系统(我正在运行 OS X,以防万一)?

另外,我预计至少会出现像过去遇到的某种段错误,但悄悄地忽略这样的错误真的让我害怕。这个程序怎么不对我产生段错误?

最后,出于好奇(这可能是最愚蠢的问题),有没有办法解决这种疯狂?我可以期望所有 ANSI C 编译器都以这种方式工作吗?不同平台上的 gcc 怎么样?内存布局是否明确定义为可利用(也许如果您要编写跨平台混淆代码)?

最佳答案

C 语言将某些程序的行为定义为“未定义”。他们可以做任何事情。我们将此类程序称为错误的。

其中一个是访问数组的声明/分配边界之外的程序,您的程序非常小心地这样做了。

你的程序是错误的;你的错误程序发生的事情就是你看到的:-}它可能“覆盖操作系统”;实际上,大多数现代操作系统都阻止您这样做,但您可以覆盖进程空间中的关键值,您的进程可能会崩溃、死亡或挂起。

简单的回答是“不要编写错误的程序”。那么你看到的行为就会使“C”有意义。

在这种特殊情况下,使用您的特定编译器,数组索引“有点”起作用:您在数组外部进行索引,它会获取 some 值。分配给 m 的空间在栈帧中; m[0] 位于堆栈帧中的某个位置,“m[-1]”基于结合数组地址和索引的机器算术,因此不会发生段错误并且访问内存位置。这使编译后的程序可以读取和写入该内存位置……作为错误程序。基本上,编译后的 C 程序不会检查您的数组访问是否越界。

我们的CheckPointer应用于此程序的工具会告诉您数组索引在执行时是非法的。因此,您可以自己观察程序以查看您是否犯了错误,或者让 CheckPointer 在您犯错时告诉您。我强烈建议你无论如何都要目测。

关于c - 安全的 C 编程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10778570/

相关文章:

c - 在 C 中放置新的等价物

c - 只有一个元素的数组的意义

如果没有足够的文件描述符,重命名会失败吗?

c++ - 内存和性能之间的权衡

iphone - UIViewController View 即使在可见时也被卸载

c - 字符串文字 : Where do they go?

c - 是否可以使用 libspotify 获取关注艺术家的列表?

c - 将时间间隔结构化为可打印格式

c++ - 在某个内存区域中查找字节模式

c++ - 更改 C++ vector 的保留内存