联合作为 C 中的结构变量
Union as a Structure Variable in C
我有以下结构:
complex_attribute
generic_attribute
我定义了这两者的并集,像这样:
union union_attribute{
struct complex_attribute *complex;
struct generic_attribute *generic;
};
然后我定义了另一个结构来跟踪联合和与之关联的代码:
struct tagged_attribute{
int code;
union union_attribute *attribute;
};
然后,我定义了另一个名为 Disk 的结构,它包含指向 tagger_attribute 个对象的指针数组:
struct disk {
struct tagged_attribute *attribute_ptr[100];
}
现在我正在尝试像这样访问标记属性的代码:
printf("%i", disk_ptr->attribute_ptr[counter]->code);
但是我遇到了分段错误。我访问结构变量 "code" 的方式不正确吗?
这是我尝试访问的所有相关代码 "code":
struct disk* construct_disk(char* name, char* serial, char* vendor, char* model, int RPM, char *raid_type, int num_args, ...){
struct disk *disk_ptr;
disk_ptr = malloc (sizeof (struct disk));
va_list ap;
va_start(ap, num_args);
int counter;
int incrementer;
//subattributes is a global variable
incrementer = subattributes[counter];
for(counter = 0; counter < num_attributes; counter++, incrementer = subattributes[counter]){
printf("Counter = %i\n", counter);
printf("incrementer = %i\n", incrementer);
if (1){
printf("Populating generic attribute");
printf("%i", disk_ptr->attribute_ptr[counter]->code);
//disk_ptr->attribute_ptr[counter]->code = GENERIC_ATTRIBUTE_TYPE;
//disk_ptr->attribute_ptr[counter]->attribute->generic = construct_generic_attribute(va_arg(ap, int));
}else{
printf("Populating complex attribute");
//struct generic_attribute* input_to_complex_attribute[incrementer];
//int stepper;
//for(stepper = 0; stepper<incrementer; stepper++){
// input_to_complex_attribute[stepper] = construct_generic_attribute(va_arg(ap, int));
//}
//disk_ptr->attribute_ptr[counter]->code = COMPLEX_ATTRIBUTE_TYPE;
//disk_ptr->attribute_ptr[counter]->attribute->complex = construct_complex_attribute(5, incrementer, input_to_complex_attribute);
}
}
va_end(ap);
return disk_ptr;
}
您根本没有访问 code
(当然,您应该使用它来检查哪个工会成员有效)。
您正在访问 attribute_ptr
数组的第 counter
个元素,它是指向 tagged_attribute
的指针并试图取消引用它(使用 ->
) .可能没有首先分配该指针(或该数组中的任何其他指针),也没有在分配后初始化内存(您没有显示任何相关信息......未能正确分配可能是您的段错误的原因。)
当然,这假定 disk_ptr
已正确分配和初始化......您没有显示,也可能没有。
如前所述,如果您想更具体地回答您的问题,请显示所有相关代码。此外,在启用警告的情况下进行编译,并学习使用 gdb
(GNU 调试器)和 valgrind
(用于内存问题)等工具来调试代码。
编辑:现在你已经添加了代码,你已经分配了 disk_ptr
但你从来没有在 attribute_ptr
中分配任何东西,所以它只是指向内存中任意位置的 100 个指针。
在 C 中,如果指针未指向有效内存,您将有未定义的行为。发生的常见事情之一是分段错误,因为指针具有随机块或初始化为零,当您尝试访问它指向的内存时,硬件检测到您正在访问无效的内存页面。每次使用 ->
时,都会取消对指针的引用,并且 运行 存在段错误的风险。您应该使用调试器来查找不正确的值。另一种方法是在取消引用之前打印这些值:
printf("disk_ptr = %p\n", disk_ptr);
printf("disk_ptr->attribute_ptr[counter] = %p\n", disk_ptr->attribute_ptr[counter]);
您应该将此代码放在您显示的打印件之前。如果 disk_ptr
是无效值,则第二次打印将失败。第一次打印总是会成功,但您应该查看它是否为 NULL。如果您没有看到第二个打印,则表示 disk_ptr
是无效指针。这是因为在第二个打印中 disk_ptr
是通过 ->
运算符取消引用的,如果它指向块,它可能(让我强调 可能 )导致段错误(它还可能会覆盖一些其他数据,这可能会在以后导致段错误)。如果第二个打印有效但您显示的打印无效,则 disk_ptr->attribute_ptr[counter]
可能是无效指针。让我再次强调,因为它很重要。如果指针未指向正确的内存位置,则您有未定义的行为。取消对该指针的引用可能会立即导致段错误,或者可能以某种方式修改内存,以便稍后发生段错误。
您正在取消引用 disk_ptr->attribute_ptr[1]
,但该指针数组未初始化(指针指向任何地方)。
您必须先 malloc
每个指针的 struct tagged_attribute
条目。
我有以下结构:
complex_attribute
generic_attribute
我定义了这两者的并集,像这样:
union union_attribute{
struct complex_attribute *complex;
struct generic_attribute *generic;
};
然后我定义了另一个结构来跟踪联合和与之关联的代码:
struct tagged_attribute{
int code;
union union_attribute *attribute;
};
然后,我定义了另一个名为 Disk 的结构,它包含指向 tagger_attribute 个对象的指针数组:
struct disk {
struct tagged_attribute *attribute_ptr[100];
}
现在我正在尝试像这样访问标记属性的代码:
printf("%i", disk_ptr->attribute_ptr[counter]->code);
但是我遇到了分段错误。我访问结构变量 "code" 的方式不正确吗?
这是我尝试访问的所有相关代码 "code":
struct disk* construct_disk(char* name, char* serial, char* vendor, char* model, int RPM, char *raid_type, int num_args, ...){
struct disk *disk_ptr;
disk_ptr = malloc (sizeof (struct disk));
va_list ap;
va_start(ap, num_args);
int counter;
int incrementer;
//subattributes is a global variable
incrementer = subattributes[counter];
for(counter = 0; counter < num_attributes; counter++, incrementer = subattributes[counter]){
printf("Counter = %i\n", counter);
printf("incrementer = %i\n", incrementer);
if (1){
printf("Populating generic attribute");
printf("%i", disk_ptr->attribute_ptr[counter]->code);
//disk_ptr->attribute_ptr[counter]->code = GENERIC_ATTRIBUTE_TYPE;
//disk_ptr->attribute_ptr[counter]->attribute->generic = construct_generic_attribute(va_arg(ap, int));
}else{
printf("Populating complex attribute");
//struct generic_attribute* input_to_complex_attribute[incrementer];
//int stepper;
//for(stepper = 0; stepper<incrementer; stepper++){
// input_to_complex_attribute[stepper] = construct_generic_attribute(va_arg(ap, int));
//}
//disk_ptr->attribute_ptr[counter]->code = COMPLEX_ATTRIBUTE_TYPE;
//disk_ptr->attribute_ptr[counter]->attribute->complex = construct_complex_attribute(5, incrementer, input_to_complex_attribute);
}
}
va_end(ap);
return disk_ptr;
}
您根本没有访问 code
(当然,您应该使用它来检查哪个工会成员有效)。
您正在访问 attribute_ptr
数组的第 counter
个元素,它是指向 tagged_attribute
的指针并试图取消引用它(使用 ->
) .可能没有首先分配该指针(或该数组中的任何其他指针),也没有在分配后初始化内存(您没有显示任何相关信息......未能正确分配可能是您的段错误的原因。)
当然,这假定 disk_ptr
已正确分配和初始化......您没有显示,也可能没有。
如前所述,如果您想更具体地回答您的问题,请显示所有相关代码。此外,在启用警告的情况下进行编译,并学习使用 gdb
(GNU 调试器)和 valgrind
(用于内存问题)等工具来调试代码。
编辑:现在你已经添加了代码,你已经分配了 disk_ptr
但你从来没有在 attribute_ptr
中分配任何东西,所以它只是指向内存中任意位置的 100 个指针。
在 C 中,如果指针未指向有效内存,您将有未定义的行为。发生的常见事情之一是分段错误,因为指针具有随机块或初始化为零,当您尝试访问它指向的内存时,硬件检测到您正在访问无效的内存页面。每次使用 ->
时,都会取消对指针的引用,并且 运行 存在段错误的风险。您应该使用调试器来查找不正确的值。另一种方法是在取消引用之前打印这些值:
printf("disk_ptr = %p\n", disk_ptr);
printf("disk_ptr->attribute_ptr[counter] = %p\n", disk_ptr->attribute_ptr[counter]);
您应该将此代码放在您显示的打印件之前。如果 disk_ptr
是无效值,则第二次打印将失败。第一次打印总是会成功,但您应该查看它是否为 NULL。如果您没有看到第二个打印,则表示 disk_ptr
是无效指针。这是因为在第二个打印中 disk_ptr
是通过 ->
运算符取消引用的,如果它指向块,它可能(让我强调 可能 )导致段错误(它还可能会覆盖一些其他数据,这可能会在以后导致段错误)。如果第二个打印有效但您显示的打印无效,则 disk_ptr->attribute_ptr[counter]
可能是无效指针。让我再次强调,因为它很重要。如果指针未指向正确的内存位置,则您有未定义的行为。取消对该指针的引用可能会立即导致段错误,或者可能以某种方式修改内存,以便稍后发生段错误。
您正在取消引用 disk_ptr->attribute_ptr[1]
,但该指针数组未初始化(指针指向任何地方)。
您必须先 malloc
每个指针的 struct tagged_attribute
条目。