g++链接so时,找不到类的static成员变量

37 篇文章 0 订阅
15 篇文章 0 订阅

前言

公司项目有个比较偏门的需求,需要在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

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;
}

编译命令:

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

最终生成libb.so

主程序代码

就一个cpp:

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

int main()
{
	b_test();

	return 1;
}

编译命令:
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

分析与定位

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

修改

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

int BClass::static_private_var = 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; }
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

lqw198421

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值