#include <stdio.h>
#include <stdlib.h>
struct ver{
double x;
double y;
};
struct ver *v=NULL;
int main(){
v=(struct ver*)realloc(v,1*sizeof(struct ver));
v[0].x=1.444;
v[0].y=1.555;
v[1].x=1.333;
v[1].y=1.222;
v[3].x=1.111;
v[3].y=1.777;
v[8].x=1.999;
v[8].y=1.888;
printf("x:%f y:%f \n", v[0].x, v[0].y);
printf("x:%f y:%f \n", v[1].x, v[1].y);
printf("x:%f y:%f \n", v[3].x, v[3].y);
printf("x:%f y:%f \n", v[8].x, v[8].y);
}
结果是:
x:1.444000 y:1.555000
x:1.333000 y:1.222000
x:1.111000 y:1.777000
x:1.999000 y:1.888000
我不应该得到分段错误吗?它忽略了realloc。 我想创建一个结构数组,我想每次扩展1个数组单元格。
答案 0 :(得分:2)
您正在呼叫realloc
分配一个条目。访问v[0]
之外的任何内容未定义的行为 可能导致崩溃,或者可能不会。
从技术上讲,像你这样定义main
(没有任何参数,甚至不是void
)也是C中的未定义行为。你要么必须用void
作为参数声明它,或int
和char**
。
答案 1 :(得分:1)
使用realloc
指针调用NULL
是明确定义的行为。所以v指向足够的内存,只有一个struct ver。
v[1]
没有产生分段错误的原因:这样的错误不一定要发生 - 你可以幸运...也许realloc
也会给你更多的记忆要求16个字节。
答案 2 :(得分:1)
如果您正在访问的地址后面没有内存,则只会出现分段错误。这在物理意义上意味着,段错误首先由硬件而非软件发出信号。现在,物理内存映射总是以完整页面的形式发生。在大多数硬件上都是4 kiB。您从realloc()
请求的大小只有16个字节。
当然,realloc()
返回的地址后面必须有内存。因此,您的结构周围必须至少有4080个地址,这些地址在硬件眼中与属于结构本身的16个地址一样有效。这意味着硬件无法向您的操作系统发出可能有问题的信号,并且您的操作系统无法向您发送分段错误。如果您尝试访问v[1000]
,可能会遇到段错误,但即使这样也不确定。
这并不意味着您可以访问这些地址,这只意味着您在访问它们时不能依赖段错误。可能有其他分配可能会破坏,或者更糟糕的是,可能存在信息,malloc使用这些信息来确定使用哪些内存区域,哪些内存区域不使用。如果您访问realloc()
请求的区域之外的任何地址,则您的程序具有未定义的行为,并且可能发生任何。
答案 3 :(得分:0)
有时malloc
从操作系统中获取一大块(因此可以在以后使用它),而无需进行上下文切换。
这很贵。
所以你很幸运