为什么这个程序会出现段错误?
Why is this program gives a segmentation fault?
我正在做一些结构练习,我无法理解分段错误。
我几乎一切都做对了,分段错误在循环中 for(i = 0;i<2;i++)
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<math.h>
#include<stdint.h>
#define MAX 50
int main(void)
{
typedef struct {
char *name;
char *l_name;
u_int32_t age;
}person;
u_int32_t i;
person p[2];
p->name = (char *) malloc(sizeof(char) * MAX);
p->l_name = (char *) malloc(sizeof(char)* MAX);
if(p->name == NULL || p->l_name == NULL){
fprintf(stderr,"Error allocating memory");
exit(1);
}
for(i = 0;i<2;i++){
if(!fgets(p[i].name,sizeof(p[i].name),stdin)){
fprintf(stderr,"Error reading string");
exit(2);
}
if(!fgets(p[i].l_name,sizeof(p[i].l_name),stdin)){
fprintf(stderr,"Error reading string");
exit(3);
}
}
}
您声明了一个包含两个元素的数组
person p[2];
而且你只初始化了第一个元素的数据成员p[0]
p->name = (char *) malloc(sizeof(char) * MAX);
p->l_name = (char *) malloc(sizeof(char)* MAX);
以上语句等同于
p[0].name = (char *) malloc(sizeof(char) * MAX);
p[0].l_name = (char *) malloc(sizeof(char)* MAX);
第二个元素 p[1]
的数据成员未初始化且具有不确定的值。
因此,当您尝试使用数组第二个元素的这些未初始化数据成员时,for 循环会调用未定义的行为,例如
if(!fgets(p[i].name,sizeof(p[i].name),stdin)){
此外,您在 fgets
的调用中使用了错误的表达式
sizeof(p[i].name)
数据成员name
(还有l_name
)是一个指针。所以上面的表达式将产生一个指针的大小。
相反,您只需要写 MAX
,例如
if(!fgets(p[i].name, MAX, stdin )){
代码无法为所有p[i].name
分配。
传递给 fgets()
的尺寸错误。
考虑在阅读后分配。读入本地缓冲区,然后形成大小合适的副本。
for(i = 0; i<2; i++) {
char buf[MAX + 2];
if (fgets(buf, sizeof buf, stdin)) {
fprintf(stderr,"Error reading string");
exit(2);
}
buf[strcspn(buf, "\n")] = 0; // Lop off potential \n
p[i].name = strdup(buf); // Common, but non-standard string allocation
if (fgets(buf, sizeof buf, stdin)) {
fprintf(stderr,"Error reading string");
exit(3);
}
buf[strcspn(buf, "\n")] = 0;
p[i].lname = strdup(buf);
}
如果您的图书馆中没有,请示例 。
我正在做一些结构练习,我无法理解分段错误。 我几乎一切都做对了,分段错误在循环中 for(i = 0;i<2;i++)
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<math.h>
#include<stdint.h>
#define MAX 50
int main(void)
{
typedef struct {
char *name;
char *l_name;
u_int32_t age;
}person;
u_int32_t i;
person p[2];
p->name = (char *) malloc(sizeof(char) * MAX);
p->l_name = (char *) malloc(sizeof(char)* MAX);
if(p->name == NULL || p->l_name == NULL){
fprintf(stderr,"Error allocating memory");
exit(1);
}
for(i = 0;i<2;i++){
if(!fgets(p[i].name,sizeof(p[i].name),stdin)){
fprintf(stderr,"Error reading string");
exit(2);
}
if(!fgets(p[i].l_name,sizeof(p[i].l_name),stdin)){
fprintf(stderr,"Error reading string");
exit(3);
}
}
}
您声明了一个包含两个元素的数组
person p[2];
而且你只初始化了第一个元素的数据成员p[0]
p->name = (char *) malloc(sizeof(char) * MAX);
p->l_name = (char *) malloc(sizeof(char)* MAX);
以上语句等同于
p[0].name = (char *) malloc(sizeof(char) * MAX);
p[0].l_name = (char *) malloc(sizeof(char)* MAX);
第二个元素 p[1]
的数据成员未初始化且具有不确定的值。
因此,当您尝试使用数组第二个元素的这些未初始化数据成员时,for 循环会调用未定义的行为,例如
if(!fgets(p[i].name,sizeof(p[i].name),stdin)){
此外,您在 fgets
sizeof(p[i].name)
数据成员name
(还有l_name
)是一个指针。所以上面的表达式将产生一个指针的大小。
相反,您只需要写 MAX
,例如
if(!fgets(p[i].name, MAX, stdin )){
代码无法为所有p[i].name
分配。
传递给 fgets()
的尺寸错误。
考虑在阅读后分配。读入本地缓冲区,然后形成大小合适的副本。
for(i = 0; i<2; i++) {
char buf[MAX + 2];
if (fgets(buf, sizeof buf, stdin)) {
fprintf(stderr,"Error reading string");
exit(2);
}
buf[strcspn(buf, "\n")] = 0; // Lop off potential \n
p[i].name = strdup(buf); // Common, but non-standard string allocation
if (fgets(buf, sizeof buf, stdin)) {
fprintf(stderr,"Error reading string");
exit(3);
}
buf[strcspn(buf, "\n")] = 0;
p[i].lname = strdup(buf);
}
如果您的图书馆中没有,请示例