Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/68.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 - Fatal编程技术网

C中通过指针的内存分配

C中通过指针的内存分配,c,C,我正在学习如何使用指针,所以我编写了下面的程序,将间隔[1100]中的整数值分配给内存中的一些随机位置 当我读取这些内存位置时,printf显示所有的值,然后给我一个分段错误。这似乎是一种奇怪的行为,因为我希望看到所有值或seg故障,但不是同时看到两者 有人能解释一下为什么我两个都要看吗 谢谢。这是密码 #include <stdio.h> #include <stdlib.h> int main() { char first = 'f'; char *

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

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

有人能解释一下为什么我两个都要看吗

谢谢。这是密码

#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;
} 
#包括
#包括
int main()
{
char first='f';
char*ptr_first=&first;
int i=1;

对于(i=1;i您正在访问超出分配给
first
的内存。它只是一个字符,通过
ptr_first
指针,您正在访问超过此字符的100个位置到未保留内存。这可能会导致SEGFULTS

您必须确保原始变量为指针访问保留了足够的内存。例如:

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


还要注意的是,您正在将
int
插入到char指针中。这将起作用,但int的值将被截断。您应该使用
char
作为
i
的类型,这一点都不奇怪。您正在使用堆栈上的变量
first
。您实际上所做的是愉快地覆盖stack(或者从堆栈上的缓冲区溢出中知道)并因此可能破坏任何返回地址等等


由于libc调用了
main
,返回libc会导致崩溃。

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

我想补充一点:从不(有意地)如果你不知道存储在那里的是什么,尝试访问指针。在最好的情况下,你会立即崩溃…在最坏的情况下,你会造成难以追踪的困难,如果你碰巧真的很幸运,你永远不会意识到你犯了这个错误。上面是什么情况?我不会读写他成功地释放了内存,但我也收到了类似警告的通知,最后发生了seg故障。seg故障的行为不是由任何posix标准定义的吗?它不是释放内存。如果堆栈向下增长,则是返回地址,可能是帧指针,然后是调用
ma的代码的堆栈帧在()
等等。如果堆栈向上增长,则需要使用任何填充来对齐指针变量,后跟指针变量本身的第一个字节,然后所有下注都将被取消。那么我的结果是否意味着c将允许我读取和写入堆栈,但最后只需给出一个警告,说明我导致了seg错误?这似乎不安全,我希望该程序要么完全崩溃,我看到一个seg错误,要么我看到我的值。但事实上,两者都发生了,似乎seg错误只是发出警告,而不是致命错误。在某些系统中,这将在不执行的情况下崩溃。例如,Linux与ExecShield处于活动状态。回答不错。只是为了详细说明。OP的问题是,为什么数字打印正常,而他仍然得到一个segfault,而不是mem write上的立即segfault,或者根本没有segfault。许多流行体系结构(例如x86)上的堆栈都在下降,即内存地址越来越低,所以
*(ptr+i)
它指向更高的内存地址,通常不指向未分配的内存区域,而是指向当前程序控制的更高的堆栈位置。正如答案中所解释的,这允许读取和写入无segfault,并且以后,如果覆盖了重要的堆栈数据,libc将抛出segfault。这就是这是C委托程序员处理的一部分-如果是堆栈,请小心处理。如果操作系统或某个虚拟机在每次内存访问时都执行内务管理,则会降低执行速度。不,这完全是一个致命错误。segfault始终是。您看到这两个错误是因为正如状态所述,您用返回地址重写了堆栈的部分。因此,由于您重写了堆栈,您仍然很好,因为您没有开始干扰其他人的内存,因此没有segfault。但是,当您尝试返回到现在无效的地址时,它将是segfault,因为您很可能不再在分配的内存中。