前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >CLR card_table位移和数组

CLR card_table位移和数组

作者头像
江湖评谈
发布2023-10-26 17:58:00
890
发布2023-10-26 17:58:00
举报
文章被收录于专栏:天下风云天下风云

1.前言 数组和位移基本上没啥关系,但可以通过位移的方式来操控数组的内存运作方式。比较细微的容易被疏忽的处理,然后引申下CLR的card_table这个表,本篇来看下。

2.概述 先上示例代码:

代码语言:javascript
复制
typedef unsigned int       uint32_t;
int main(int argc,char** argv) {

    uint32_t card_table[] = { 1,3,5,7,9,11,13,15,17 };
    uint32_t* g_card_table = card_table;
    uint32_t bone = g_card_table[2];
    uint32_t btwo = *(g_card_table + 8);
}

示例通过索引取数组的值,比如索引2:

代码语言:javascript
复制
uint32_t bone = g_card_table[2];

可以写成如下:

代码语言:javascript
复制
uint32_t boneone = *(g_card_table+2);

前者数组后者指针,我们可以通过指针的偏移量来操控数组。

3.card_table card_table有两个功能 其一:当2代对象引用了0代对象,此时如果0代对象进行了GC。可能这个0代对象被GC压缩或者移动了地址。2代对象此时指向的就是空地址或者错误地址,这就需要card_table位来标记0代移动对象的地址。修正2代对象指向正确的地址。

其二:是当GC堆的2代引用了0代对象,而此时GC回收了0代,如果这个0代对象除了2代引用了它,没有其它引用,那么它可能被面临回收,为了防止回收,card_table里面做了位标记,GC的时候除了扫描GC堆,还扫描card_table的位标记,防止对象误回收。

可见card_table是比较重要的一个CLR功能。

示例当中

代码语言:javascript
复制
uint32_t btwo = *(g_card_table + 8);

当我们在*(g_card_table + 8)此处进行了赋值0xFF,表示此处有0代对象移动或者是面临被回收。我们取值的时候可以往前扩大下范围,防止card_table漏扫。

代码语言:javascript
复制
bone = g_card_table[2];

我们看到这里的索引是2,而赋值的时候索引是8。这样的话取值bone的范围是大于btwo的范围。可以正确扫描处引用0代的2代对象大致的范围。

实际的操作如下:

代码语言:javascript
复制
赋值:
g_card_table + n1.selfName(2代对象) >> 0x0B = 0xFF

取值:
card_table [card_word (card)];

可以看到2代对象右移了0x0B位,card和card_word总共位移了0x0D位。多出了两位,也就是把数组取值向左边扩展了。以便正确扫描二代。

另外一个比较奇特功能就是通过余数来获取正确的card_table值

代码语言:javascript
复制
last_card_word = &card_table [card_word (card)];
bit_position = card_bit (card);
card_word_value = (*last_card_word) >> bit_position;

card_bit里面是%,然后把得到的*last_card_word按照余数右移,获取真正的card_table数值。

以上极为细致的操作是CLR骚操的一部分,有一些东西依然需要更进一步

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2023-10-20,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 江湖评谈 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档