实际上,我用相同的代码问了另一个问题,但这是非常不同的。 我在下面的代码显示了一个非常烦人的行为。我尽可能多地在代码中添加注释,以便您可以了解正在发生的事情。
#include <stdio.h>
#include <stdlib.h>
/* This is a struct describing properties of an element */
struct element{
int age;
char* name;
};
/* This struct contains a pointer to a pointer on a element "struct element" */
struct person{
struct element** p;
size_t size;
unsigned int id;
};
/* This function initializes a struct person by allocating memory for it */
struct person* init(int _size)
{
if(_size == 0)
{
printf("You gonna have to make some choices \n");
exit(1);
}
struct person* sample = (struct person* )malloc(_size*sizeof(struct person));
sample->p = (struct element** ) malloc(_size*sizeof(struct element*));
sample->id = 0;
sample->size = _size;
return sample;
}
/* use this function to insert a new element in the struct */
void insert(struct person* sample, char* _name, int _age)
{
if (sample->id >= sample->size) {
sample->p = (struct element** ) realloc(sample->p, (sample->size*2) * sizeof(struct element*));
if(sample->p == NULL){
printf("Get a new RAM buddy \n");
exit(1);
}
}
sample->p[sample->id]->name = _name;
sample->p[sample->id]->age = _age; /* of course, this will cause trouble too because it has the same construct as the previous one */
sample->id++;
}
/* main entry */
int main(int argc, char** argv)
{
int i = 0;
struct person* student = init(10); /* Allocating space for 10 students */
insert(student, "baby", 2);
insert(student, "dady", 33);
/* if you remove this line, the program runs, but GDB will signal a segmentation fault. If you keep it, the program will freeze and GDB will behave as expected */
/* I don't understand why this is happening!!!??? */
insert(student, "grandma", 63);
printf("Your name is %s and your age is %d \n", student->p[1]->name, student->p[1]->age);
/* When you only insert two elements, use the results here to match with GDB's results*/
printf("student->p: %p \n", &student->p);
printf("student->p[0]: %p \n", &student->p[0]);
printf("student->p[1]: %p \n", &student->p[1]);
printf("student->p[0]->age: %p \n", &student->p[0]->age);
printf("student->p[0]->name: %p \n", &student->p[0]->name);
/* Won't work for more than two elements inserted */
for(i = 0; i < 2; i++){
printf("Your name is %s and your age is %d \n", student->p[i]->name, student->p[i]->age);
}
return 0;
}
我希望你能弄明白发生了什么。 这是调试会话的一部分。
(gdb) run
The program being debugged has been started already.
Start it from the beginning? (y or n) y
Starting program: C:\Users\NTWALI\Desktop\tests\help\bin\Debug/help.exe
[New thread 11408.0x1228]
Error: dll starting at 0x770a0000 not found.
Error: dll starting at 0x76ab0000 not found.
Error: dll starting at 0x770a0000 not found.
Error: dll starting at 0x76d40000 not found.
Program received signal SIGSEGV, Segmentation fault.
0x0040146f in insert (sample=0x6816c0, _name=0x409031 "ntwali", _age=22) at C:\Users\NTWALI\Desktop\tests\help\main.c:44
44 sample->p[sample->id]->name = _name;
(gdb) p sample
$4 = (struct person *) 0x6816c0
(gdb) p sample->p
$5 = (struct element **) 0x681750
(gdb) p sample->p[0]
$6 = (struct element *) 0xbaadf00d
(gdb) p sample->p[1]
$7 = (struct element *) 0xbaadf00d
(gdb)
正如您在代码注释中看到的那样,程序在工作时提供的数据与GDB获得的数据不匹配。
感谢您的帮助。
答案 0 :(得分:3)
就我所见,你还没有为元素分配任何内存。 在这里,您为指向元素的指针分配内存:
sample->p = (struct element** ) malloc(_size*sizeof(struct element*));
答案 1 :(得分:3)
如果调试器的存在改变了程序的行为方式,则很可能会误用内存或线程。就像daven11 points out一样,你没有自己分配元素。
答案 2 :(得分:0)
您的问题的根本原因是您正在分配指向struct element
的指针,但这些指针未初始化 - 您没有分配任何实际的struct element
对象。当您取消引用这些无效指针时,您会得到未定义的行为。
也没有必要分配_size
结构的struct person
- 你只使用一个。{1}}结构。您的struct person
应该是这样的(注意p
的类型不同):
struct person{
struct element *p;
size_t size;
unsigned int id;
};
然后您的init()
函数应如下所示:
struct person* init(int _size)
{
if(_size < 1)
{
printf("You gonna have to make some choices \n");
exit(1);
}
struct person* sample = malloc(sizeof *sample);
sample->p = malloc(_size * sizeof sample->p[0]);
sample->id = 0;
sample->size = _size;
return sample;
}
insert()
函数应如下所示:
void insert(struct person* sample, char* _name, int _age)
{
if (sample->id >= sample->size) {
sample->size *= 2;
sample->p = realloc(sample->p, sample->size * sizeof sample->p[0]);
if(sample->p == NULL){
printf("Get a new RAM buddy \n");
exit(1);
}
}
sample->p[sample->id].name = _name;
sample->p[sample->id].age = _age; /* of course, this will cause trouble too because it has the same construct as the previous one */
sample->id++;
}
然后,主要功能应使用student->p[i].name
和student->p[i].age
来访问数据。
答案 3 :(得分:0)
这里你使用p []而没有先将其初始化为指向任何东西。你只为指针分配了空间,但没有初始化它们指向任何东西。所以当你这样做时
sample->p[sample->id]->name = _name;
sample->p[sample->id]->age = _age;
p指向内存中的某个位置并且您正在修改它所指向的位置。
而是插入
sample->p[sample->id] = malloc(struct element);
sample->p[sample->id]->name = _name;
sample->p[sample->id]->age = _age;
它应该有效
PS。通常你不会在C
中投射malloc