通过返回的指针访问函数静态结构时出现分段错误

时间:2011-09-12 16:10:21

标签: c debugging data-structures segmentation-fault shared-libraries

我有以下结构:

struct sys_config_s
{
  char server_addr[256];
  char listen_port[100];
  char server_port[100];
  char logfile[PATH_MAX];
  char pidfile[PATH_MAX];
  char libfile[PATH_MAX];
  int  debug_flag;
  unsigned long connect_delay;
};
typedef struct sys_config_s sys_config_t;

我还在静态库中定义了一个函数(让我们称之为A.lib):

sys_config_t* sys_get_config(void)
{
  static sys_config_t config;
  return &config;
}

然后我有一个程序(我们称之为B)和一个动态库(我们称之为C)。 B和C都与A.lib链接。在运行时B通过dlopen()打开C,然后通过调用func()获取C函数dlsym()的地址。

void func(void)
{
  sys_get_config()->connect_delay = 1000;
}

上面的代码是C func()函数的主体,它到达时会产生分段错误。只有在gdb之外运行时才会发生段错误。

为什么会这样?

编辑:使sys_config_t config成为全局变量无济于事。

2 个答案:

答案 0 :(得分:1)

解决方案很简单。不知何故,通过标头不匹配,PATH_MAX常量在B和C的编译单元中的定义不同。我将来需要更加小心。 (的 facepalms

答案 1 :(得分:0)

变量是静态局部变量或静态全局变量之间没有区别。静态变量是STATIC,这意味着,在函数调用需求中,它不是在当前函数帧内的堆栈上分配的,而是在可执行文件的二进制头中定义的内存的一个预先存在的段中分配。

这就是我100%肯定的。问题是,他们在哪个部分确切地放置,以及它们是否被正确共享 - 是另一个问题。我已经看到在模块之间共享全局/静态变量的类似问题,但通常,问题的核心对于确切的设置非常具体。

请注意,代码示例很小,很久以前我在这些平台上工作过。我上面写的可能会措辞错误甚至在某些方面明显错误!

我认为,重要的是你在接触那条线时会在C中得到那个段错误。如果目标地址有效且没有写保护,则将整数字段设置为常量不会失败,永远不会失败。这留下了两个选择: - 你的函数sys_get_config()崩溃了 - 或者它返回了无效指针。

既然你说这里引发了segfault,而不是在sys_get_config中,那么唯一剩下的就是后一点:破碎的指针。

向sys_get_config添加一些简单的printf,它将转储要返回的地址,然后在调用函数“func”中执行相同操作。检查它是否为null,并检查sys_get_config中是否与返回后相同,只是为了确保调用约定是正确的等等。进行双/三检查的一个好主意是在内部添加模块“A”是函数sys_get_config的副本(当然具有不同的名称),并检查从sys_get_config返回的地址及其副本是否相同。如果他们不是 - 在链接期间出现了一些错误

模块加载延迟的可能性非常小,而且你试图引用尚未完全初始化的模块的内存..我很久以前在linux上工作,但我记得dlopen有各种加载选项。但你写道,你得到了dlsym的地址,所以我认为模块已加载,因为你已经得到了符号的最终地址..