Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/70.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 指针的危险_C_Pointers - Fatal编程技术网

C 指针的危险

C 指针的危险,c,pointers,C,Pointers,我正在尝试学习C语言。因为我已经对高级语言(PHP、Javascript、Python)有了一定的了解,我觉得我要做的大部分工作都涉及到如何通过使用指针来替换我认为理所当然的结构(比如可变大小的数组),以及手动管理内存。我的问题是我有点担心玩指针 通常我会尝试其他语言特性,但我的问题是指针的不当使用可能会产生意想不到的结果。特别是:如果我犯了错误,是否有可能损坏其他程序正在使用的内存段,导致这些程序行为异常?或者操作系统(在我的例子中是各种风格的Ubuntu)会阻止我使用分配给不同进程的内存吗

我正在尝试学习C语言。因为我已经对高级语言(PHP、Javascript、Python)有了一定的了解,我觉得我要做的大部分工作都涉及到如何通过使用指针来替换我认为理所当然的结构(比如可变大小的数组),以及手动管理内存。我的问题是我有点担心玩指针

通常我会尝试其他语言特性,但我的问题是指针的不当使用可能会产生意想不到的结果。特别是:如果我犯了错误,是否有可能损坏其他程序正在使用的内存段,导致这些程序行为异常?或者操作系统(在我的例子中是各种风格的Ubuntu)会阻止我使用分配给不同进程的内存吗

在前一种情况下,我想我可能会(尽管不太可能)导致其他程序在磁盘上写入坏数据,破坏硬盘上的一些信息。甚至最坏的情况(我想更不可能)可能会损坏某些硬件——例如,旧的显示器可能会被软件烧坏,从而导致刷新率超出范围

我知道我的担心可能是没有道理的,但我想知道当我管理指针出错时,编译器/操作系统能在多大程度上阻止我进行危险的操作

特别是:如果我犯了错误,是否有可能损坏其他程序正在使用的内存段,导致这些程序行为异常

目前大多数(所有?)主要操作系统上都没有。十年来,内存保护一直是大多数Unix/Linux系统、Windows和Mac OS的一项功能。内存保护是一种操作系统级的访问控制系统,可防止程序写入不属于它们的内存。正如您所建议的,这既可以防止软件写入属于其他进程的内存,也可以防止软件读取不属于它的内存(一个主要的安全风险)

这并不是说你将来可能不必担心这件事,但如果你开始在现代桌面上学习C,你就不应该真正去考虑这件事。如果您在C代码中犯了错误,您可能不会破坏操作系统

这是一个非常有趣的话题,我想每个人都会从中受益。当您试图访问不属于您的内存,并且您的进程被系统终止时,您在学习时几乎肯定会遇到这种情况。查看以下两篇wiki文章了解更多信息:


大多数现代的面向桌面的操作系统(包括Linux)都使用虚拟内存来防止行为异常的程序中断其他程序。每个进程都有自己的地址空间,如果缓冲区溢出或类似地误用指针,最糟糕的情况是进程崩溃。您不应该影响系统中的其他进程,除非您正在编写设备驱动程序或以root用户身份运行(如果您以root用户身份运行,则必须对另一个进程正在读取的文件执行某些操作,等等……您仍然无法直接访问另一个进程的内存)

关于在犯错误之前捕获错误,这里有一些规则可以帮助您:

  • 在使用任何新收到的指针(如
    malloc
    的返回值、函数参数等)之前,请始终检查它们是否为null
  • 将编译器的警告一直调高并注意它们
  • 释放
    动态分配内存后,将指针设置为null。这将帮助您捕获一些悬空指针或双自由错误。(当然,如果您复制了该指针并将其存储在代码中的其他位置,除非您非常小心,否则仍然可能存在这些问题。)

  • 损坏和崩溃是可能的,但只要小心指针指向的内存中的值的大小,并且确保不交换指针,并且确保不硬编码内存地址,就可以了

    除了一些罕见的操作系统之外,您不能影响其他进程。显然,您不能损坏任何硬件。(如果可能的话,我的iOS设备早就被烧掉了,因为app store中几乎每个应用都有内存故障,因为程序员懒得阅读该死的文档)

    好榜样 错误的例子 (不确定是否编译。取决于编译器标志。)

    可怕的例子是,99%的人保证腐败
    在大多数现代操作系统(包括Linux)中,每个进程都在一个单独的地址空间中运行,这意味着它可以寻址的所有内存不是真正的RAM,而是它自己的私有“内存沙盒”,不会影响其他应用程序(实际上,如果您与其他应用程序共享RW内存段,则可以,但您和其他应用程序必须显式创建它们)


    顺便说一句,如果你在指针上犯了错误,你最终会得到指向无效内存位置的指针,而当你第一次尝试去引用它们时,操作系统会因为一个分段错误而关闭你的应用程序;别担心,这只是操作系统告诉你你弄乱了指针。:)最严重的问题,另一方面,是那些操作系统无法检测到您的指针错误的地方。

    很抱歉,我不能接受两个答案。我最后选择了Nick Meyer的一个,因为他提供了一些避免指针错误的额外建议,但你的建议也一样好。不用担心,不要真的关心代表-乐于帮助:)在使用其返回值之前,你应该检查malloc是否返回非空值。如果你给出了一个保证损坏的示例,并注意到这一点,我会认为这是一个很好的例子。”Charles Ray:如果我愿意。
    int *i = malloc(sizeof(int));
    // Use I further.
    free(i);
    
    int *i;
    i = malloc(sizeof(int));
    double j;
    i = &j;
    j = 3.1415// Mem corruption due to differently sized values, given a double is LARGER than an int.
    
    int *i = 0x00ABCDEF; // Hard coded mem adress.
    int j = 123;
    int *k = &j;
    memcpy(i, k, sizeof(int));