【发布时间】:2015-08-07 17:21:58
【问题描述】:
我有一个错误,其中不正确的值作为参数传递给 C 程序中的函数。它的工作方式是,我将一个指向 typedef 数据结构的静态指针声明为全局变量。有一个初始化函数,用于初始化此变量。该函数分配内存、初始化数据字段并返回指针。像这样的:
static my_type *my_ptr;
...
void init(void){
my_ptr = init_my_type();
}
init_my_type 函数非常简单:
void *init_my_type(void){
my_type *x = malloc(sizeof(my_type);
x->arg1 = 0;
... // more field initializations
return x;
}
稍后我使用my_ptr 作为另一个函数的参数:
void do_stuff(void){
func(my_ptr);
}
我遇到的问题是,当访问my_ptr 指向的数据结构中的某些数据时,我在func 的内部出现了段错误。
当我运行调试器时,当我在init_my_type 上中断时,我会得到一个漂亮的十六进制值:
(gdb) finish
Value returned is $26 (void *) 0x79b6c0
稍后,在do_stuff 函数内部,my_ptr 具有相同的十六进制值:
(gdb) print my_ptr
$26 = (my_type *) 0x79b6c0
但是,当我打破func 时,它得到的论点具有完全不同的价值。
Breakpoint 2, func(arg=0x1388)
我到处都是类型双关语指针,但我认为这不会改变它们指向的内存地址,对吧?此外,函数func 被声明为inline,但为什么会影响这个呢?这一切对我来说似乎都是正确的——我完全有可能在做一些我看不到的愚蠢的事情。
这里是简化代码的完整程序。实际上,所有这些函数都不是由 main 调用的,而是由动态加载的辅助函数调用的。不过,我看不出my_ptr 指向的地址在传递给func 时应该如何变化。
#include "stdlib.h"
#include "stdio.h"
typedef struct _type{
int *i1;
float *f1;
}my_type;
static my_type *my_ptr;
void *init_my_type(void){
my_type *x = malloc(sizeof(my_type));
x->f1 = malloc(sizeof(float));
x->i1 = malloc(sizeof(int));
x->f1[0] = 123.456;
x->i1[0] = 789;
return x;
}
void init(void){
my_ptr = init_my_type();
}
inline void func(void *arg){
my_type *x = (my_type *)arg;
printf("%d %f\n", *x->i1, *x->f1);
}
void do_stuff(void){
func(my_ptr);
}
int main(void){
init();
do_stuff();
}
【问题讨论】:
-
请在minimal, complete, verifiable example 上发布您遇到的问题。到目前为止,根据这里的小代码,不可能知道发生了什么。
-
@dmedine,您不会在出现错误的地方提供
func。你认为我们应该如何猜测这个。 MCVE 对我们来说真的很重要,这样我们就可以快速检查发生了什么,这对您也很重要,因为它有助于澄清您的代码。 -
扩展 bpgeck 的注释,在与 bug 实际位置完全无关的部分代码中可能会发生 seg 错误。这就是为什么需要一段显示问题的可编译代码的原因。
-
在这种情况下,我建议在 valgrind 下运行您的代码。如果你正在访问你不应该访问的内存,它会告诉你。
-
我猜你是在 64 位平台上编译,
init_my_type没有在调用时声明(在init内)。编译器假定它返回int并将 64 位指针值修剪为 32 位int值。这个修剪后的值随后被传递给func。如果是这种情况,那么您一定忽略了编译器发出的一堆警告。
标签: c pointers inline type-punning