当前位置:   article > 正文

g++链接so时,找不到类的static成员变量_static 成员函数在so中找不到

static 成员函数在so中找不到

前言

公司项目有个比较偏门的需求,需要在java进程里找到并修改libjvm.so里定义的一个类的static + private的成员变量,但是一直没有找到该变量的符号和地址。因此想通过c的程序来验证一下,确定是不是libjvm.so的问题,于是自己写了一个简单的demo,没想到折腾了2个小时,以此为记;

代码

so相关代码

代码很简单,so的代码分为b.h和b.cpp;
b.h:

#ifndef B_H_
#define B_H_

class BClass
{
	private:
		static int static_private_var;
	public:
		 int static_var;
		static void set_private_var(int var_in) ;
		static int get_private_var() ;
};
int b_test();
#endif
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

b.cpp:

#include <iostream>
#include <unistd.h>
#include "b.h"
using namespace std;

void BClass::set_private_var(int var_in) 
{ 
	static_private_var = var_in;
}
int BClass::get_private_var() 
{
	return static_private_var;
}
int b_test()
{
	BClass bClassObj;
	bClassObj.set_private_var(5);

	while(1)
	{
		int cur_private_var = bClassObj.get_private_var();
		cout << "cur_private_var = " << cur_private_var << endl;
		if(cur_private_var > 0)
		{
			cur_private_var = cur_private_var - 1;
			bClassObj.set_private_var(cur_private_var);
			sleep(10);
		}
		else
		{
			break;
		}	
	}

	cout << "end of b_test " << endl;

	return 1;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38

编译命令:

g++ b.cpp -o libb.so -fPIC -shared
  • 1

最终生成libb.so

主程序代码

就一个cpp:

#include <iostream>
#include <unistd.h>
#include "b.h"
using namespace std;

int main()
{
	b_test();

	return 1;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

编译命令:
g++ a.cpp -L. -lb -o a_out -I ./
ps:可能需要设置一下 LD_LIBRARY_PATH
export LD_LIBRARY_PATH=/home/admin/cus/cur:$LD_LIBRARY_PATH

链接libb.so的时候出问题了:

-bash-4.2$ g++ a.cpp -L. -lb -o a_out -I ./
./libb.so:对‘BClass::static_private_var’未定义的引用
collect2: 错误:ld 返回 1
  • 1
  • 2
  • 3

分析与定位

一开始看到这个错误,感觉很奇怪,为啥会有这个错误呢?为啥在编译libb.so时不出问题,但是链接libb.so的时候才出问题?
网上查了相关资料,比如说链接的顺序、模板类的定义与实现等,都不是这个错误的原因。
没有办法,为啥会只报这个变量的错误呢?就把这个static变量改成了普通的、非static的成员变量,是可以的。
那么可以确定就是“static”的问题了,static的成员变量,与全局变量类似,可以认为是一个未经初始化的全局变量,编译时是分在bss段里,不占用文件的静态空间;那么可以理解为啥编译libb.so的时候没有问题,但是链接libb.so的时候出问题了,这是因为链接libb.so的时候是成为可执行文件了;

修改

在b.cpp里添加该变量的初始化:

int BClass::static_private_var = 1;
  • 1

结论

还是要多读书

遗留问题

回头看了一下libjvm.so里的那个变量(_initialized),为何这个变量就不需要进行这样的显式的初始化呢?

class AttachListener: AllStatic {
 public:
  static void vm_start() NOT_SERVICES_RETURN;
  static void init()  NOT_SERVICES_RETURN;
  static void abort() NOT_SERVICES_RETURN;

  // invoke to perform clean-up tasks when all clients detach
  static void detachall() NOT_SERVICES_RETURN;

  // indicates if the Attach Listener needs to be created at startup
  static bool init_at_startup() NOT_SERVICES_RETURN_(false);

  // indicates if we have a trigger to start the Attach Listener
  static bool is_init_trigger() NOT_SERVICES_RETURN_(false);

#if !INCLUDE_SERVICES
  static bool is_attach_supported()             { return false; }
#else
 private:
  static volatile bool _initialized;

 public:
  static bool is_initialized()                  { return _initialized; }
  static void set_initialized()                 { _initialized = true; }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
本文内容由网友自发贡献,转载请注明出处:【wpsshop博客】
推荐阅读
相关标签
  

闽ICP备14008679号