【问题标题】:Memory assignment in C through pointers通过指针在 C 中分配内存
【发布时间】:2011-06-02 12:39:23
【问题描述】:

我正在学习如何使用指针,所以我编写了以下程序来将区间 [1,100] 中的整数值分配给内存中的一些随机位置。

当我读取这些内存位置时,printf 会显示所有值,然后给我一个分段错误。这似乎是一种奇怪的行为,因为我希望看到所有值或段错误,但不能同时看到两者。

有人能解释一下为什么我会看到这两个吗?

谢谢。这是代码

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

int main()
{
    char first = 'f';
    char *ptr_first = &first;
    int i=1;
    for(i=1;i<101;i++)
        *(ptr_first+i) = i;
    for(i=1;i<101;i++)
        printf("%d\n", *(ptr_first+i));
    return EXIT_SUCCESS;
} 

【问题讨论】:

    标签: c


    【解决方案1】:

    一点也不奇怪。您正在使用堆栈上的变量first。您本质上所做的是愉快地覆盖堆栈(否则从堆栈上的缓冲区溢出已知),因此可能会破坏任何返回地址等等。

    由于main被libc调用,返回libc会导致crash。

    【讨论】:

    • 那么我的结果是否意味着 c 会让我读取和写入堆栈,但最后只是简单地发出警告说我导致了 seg 错误?这似乎不安全,我希望程序要么完全崩溃,要么我看到一个段错误,或者我能看到我的值。但事实上两者都发生了,似乎 Seg 故障只是像警告一样发出,而不是致命错误。
    • 在某些系统中,这将在不执行的情况下崩溃。例如,激活 ExecShield 的 Linux。
    • 不错的答案。只是为了详细说明。 OP 的问题是为什么数字打印正常,而他仍然遇到段错误,而不是 mem-write 立即出现段错误,或者根本没有段错误。许多流行架构(例如 x86)上的堆栈向下增长,即朝向较低的内存地址,因此指向 更高 内存地址的*(ptr+i) 通常不指向未分配的内存区域,而是当前程序控制的更高堆栈位置。
    • 所以正如答案中所解释的那样,它允许在没有段错误的情况下进行读写,稍后,如果您覆盖了重要的堆栈数据,libc 将抛出段错误。这是 C 委托程序员的一部分——如果它是你的堆栈,请小心对待。如果操作系统或某些 VM 对每次内存访问都执行内务处理,则会减慢执行速度。
    • 不,这完全是一个致命错误。段错误总是如此。您会同时看到这两种情况,因为正如 STATUS 所说,您用返回地址覆盖了堆栈的一部分。所以,既然你覆盖了堆栈,你仍然很好,因为你还没有开始弄乱其他人的记忆,因此没有段错误。但是,当您尝试返回现在无效的地址时,它会出现段错误,因为您很可能不再在分配的内存中。
    【解决方案2】:

    您正在访问超出分配给first 的内存。它只是一个字符,并且通过ptr_first 指针,您可以访问该字符之后的100 个位置以访问未保留的内存。这可能会导致段错误。

    您必须确保原始变量有足够的内存用于指针访问。例如:

    char first[100];
    

    这将首先转换为 100 个字符的数组(基本上是 100 个字节的内存空间,您可以通过指针访问)。

    另请注意,您将int 插入到 char 指针中。这将起作用,但 int 的值将被截断。您应该使用char 作为i 的类型。

    【讨论】:

    • 我要补充一点:如果您不知道那里存储的确切内容,请不要(有意)尝试访问指针。在最好的情况下,你会立即崩溃......在最坏的情况下,你会导致很难追踪,如果你碰巧真的很幸运,你永远不会意识到你犯了这个错误。
    • 以上是什么情况?我能够成功地在未保留的内存中读写,但我也收到了一个警告,比如最后发生了段错误的通知。 Seg fault 的行为不是由任何 posix 标准定义的吗?
    • 不是未预留的内存。如果堆栈向下增长,则返回地址可能是帧指针,然后是调用main() 的代码的堆栈帧,依此类推。如果堆栈向上增长,则需要任何填充来对齐指针变量,然后是指针变量本身的第一个字节,那么所有的赌注都关闭了。
    【解决方案3】:

    因为 ptr_first 指针首先指向一个 char 变量。现在,当您递增 ptr_first 时,递增的内存地址位置可能超出进程内存地址空间,这就是内核向该进程发送分段错误的原因。

    【讨论】:

      猜你喜欢
      • 2020-06-14
      • 1970-01-01
      • 2016-02-21
      • 1970-01-01
      • 2018-08-11
      • 2021-11-29
      • 2021-12-11
      • 2015-02-27
      相关资源
      最近更新 更多