Windbg之内存里都有啥

1、程序运行一段时间后,可能会随着程序的运行,所消耗的内存不断的增大,缩小。我们有时候很好奇,

程序运行时,这些用户对象处在什么位置,怎么能找到它的位置呢?我们可以通过抓取dump内存快照,

通过windbg找到答案。

2、照例写了一个测试程序,这次从网上找了一份鹿鼎记小说(再次缅怀为我们带来了诸多欢乐的金庸老师)

,大概有1万多行,每次从中随机读取5行,如果行号是3的倍数的话,加入到一个局部的List变量里,让它不要被释放掉。

然后我们从dump文件中找到这些分配的对象。

  1 using System;
  2 using System.Collections.Generic;
  3 using System.Linq;
  4 using System.Text;
  5 using System.Text.RegularExpressions;
  6 using System.Threading.Tasks;
  7 using System.Threading;
  8 using System.Runtime.InteropServices;
  9 using System.IO;
 10 
 11 namespace WindbgDemo
 12 {
 13     public delegate void DisposeDelgate(MemoryApply memory);
 14 
 15     public class Program
 16     {
 17 
 18         static void Main(string[] args)
 19         {
 20             string directory = System.AppDomain.CurrentDomain.SetupInformation.ApplicationBase;
 21             string fileName = Path.Combine(directory, "story.txt");
 22             FileReaderHelper helper = new FileReaderHelper(fileName);
 23             List<MemoryApply> list = new List<MemoryApply>();
 24 
 25             while (true)
 26             {
 27                 int lineNumber = GenerateRandomNumber(1000, 10000);
 28                 string text = helper.ReadString(lineNumber);
 29                 using (MemoryApply apply = new MemoryApply(text, lineNumber))
 30                 {
 31                     Console.Clear();
 32                     Console.WriteLine(string.Format("{0} read from line No.{1}...", apply.ApplyTime, lineNumber));
 33                     Console.WriteLine(new string('-', 20));
 34                     Console.WriteLine(text);
 35                     if (lineNumber % 3 == 0)
 36                     {
 37                         list.Add(apply);
 38                     }
 39                     Console.WriteLine(new string('-', 20));
 40                 }
 41                 System.Threading.Thread.Sleep(500);
 42             }
 43 
 44             Console.ReadKey();
 45         }
 46 
 47         static void DisposeMemory(MemoryApply memoryObject)
 48         {
 49             Console.WriteLine("Release Line No." + memoryObject.LineNumber.ToString() + "...");
 50         }
 51 
 52         static int GenerateRandomNumber(int min, int max)
 53         {
 54             var seed = Convert.ToInt32(Regex.Match(Guid.NewGuid().ToString(), @"\d+").Value);
 55             return new Random(seed).Next(min, max);
 56         }
 57 
 58     }
 59 
 60     public class FileReaderHelper
 61     {
 62 
 63         private string currentFileName = string.Empty;
 64 
 65         public FileReaderHelper(string fileName)
 66         {
 67             currentFileName = fileName;
 68 
 69         }
 70 
 71         public string ReadString(int lineNumber)
 72         {
 73             string result = string.Empty;
 74             try
 75             {
 76                 IEnumerable<string> query = File.ReadLines(currentFileName, System.Text.Encoding.GetEncoding("gb2312"));
 77 
 78                 var list = query.Skip(lineNumber).Take(5);
 79 
 80                 StringBuilder sb = new StringBuilder();
 81                 foreach (string item in list)
 82                 {
 83                     sb.AppendLine(item);
 84                 }
 85                 result = sb.ToString();
 86             }
 87             catch (Exception ex)
 88             {
 89                 Console.WriteLine(ex.Message);
 90             }
 91             return result;
 92         }
 93     }
 94 
 95     public class MemoryApply : IDisposable
 96     {
 97         public string Content;
 98         public int LineNumber;
 99         public string ApplyTime = string.Empty;
100         public DisposeDelgate DisposeDelgateEvent;
101 
102         public MemoryApply(string text, int lineNumber)
103         {
104             this.Content = text;
105             this.LineNumber = lineNumber;
106             this.ApplyTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff");
107         }
108 
109         public void Dispose()
110         {
111             Dispose(true);
112             GC.SuppressFinalize(this);
113         }
114 
115         protected virtual void Dispose(bool disposing)
116         {
117             if (!m_disposed)
118             {
119                 //Release unmanaged or managed resources
120                 m_disposed = true;
121             }
122         }
123 
124         ~MemoryApply()
125         {
126             if (DisposeDelgateEvent != null)
127                 DisposeDelgateEvent(this);
128             Dispose(false);
129         }
130 
131         private bool m_disposed;
132     }
133 
134 }

3、首先用dumpheap命令查看托管堆

0:004> !dumpheap -stat
Statistics:
      MT    Count    TotalSize Class Name
65cef390        1           12 System.Collections.Generic.GenericArraySortHelper`1[[System.String, mscorlib]]
65ce2cfc        1           12 System.Security.Permissions.SecurityPermission
65ca7f9c        1           12 System.AppDomainPauseManager
...
00234e98       67         1876 WindbgDemo.MemoryApply
65ca1ab0       10        16378 System.Byte[]
65c9d878        9        17716 System.Object[]
65ca0d14      701        19628 System.Text.StringBuilder
65c9de90      722       332254 System.Char[]
65c9d484     3076       713074 System.String
Total 4928 objects

4、带入mt参数,继续查看

0:004> !dumpheap -mt 00234e98       
 Address       MT     Size
01eebc24 00234e98       28     
01eed134 00234e98       28     
01eed780 00234e98       28     
01eed950 00234e98       28     
01eede84 00234e98       28     
01eee084 00234e98       28        
...
01f05e34 00234e98       28     
01f0a4c8 00234e98       28     
01f12e50 00234e98       28     
01fee004 00234e98       28     

Statistics:
      MT    Count    TotalSize Class Name
00234e98       67         1876 WindbgDemo.MemoryApply
Total 67 objects

5、我们随机查看一个对象,并观察这个对象的跟对象。

0:004> !do 01eed950;!gcroot 01eed950
Name:        WindbgDemo.MemoryApply
MethodTable: 00234e98
EEClass:     002318ec
Size:        28(0x1c) bytes
File:        D:\Projects\05Dump\bin\WindbgDemo.exe
Fields:
      MT    Field   Offset                 Type VT     Attr    Value Name
65c9d484  4000002        4        System.String  0 instance 01eed7e4 Content
65c9f2d8  4000003       10         System.Int32  1 instance     9315 LineNumber
65c9d484  4000004        8        System.String  0 instance 01eed96c ApplyTime
00000000  4000005        c ...mo.DisposeDelgate  0 instance 00000000 DisposeDelgateEvent
65ce1f0c  4000006       14       System.Boolean  1 instance        1 m_disposed
Thread fb4:
    0021f3a0 0028065d WindbgDemo.Program.Main(System.String[]) [d:\Projects\WindbgDemo\WindbgDemo\05Dump.cs @ 41]
        ebp+3c: 0021f3dc
            ->  01ee3ee4 System.Collections.Generic.List`1[[WindbgDemo.MemoryApply, WindbgDemo]]
            ->  01efa04c WindbgDemo.MemoryApply[]
            ->  01eed950 WindbgDemo.MemoryApply

Found 1 unique roots (run '!GCRoot -all' to see all roots).

6、发现这个对象行号9315,是可以被三整除的的,属于要被加到List中的元素。同时发现这个对象属于01efa04c 这个数组,来

查看一下未被释放的67个对象都属于这个数组呢?一个一个去验证,太笨拙了,当然我们可以通过token command来实现。

0:004> .load sosex.dll
This dump has no SOSEX heap index.
The heap index makes searching for references and roots much faster.
To create a heap index, run !bhi
0:004> .foreach /pS 0n20 /ps 0n1 (str {!da 01efa04c }) { !sosex.mdt ${str} }
This command may not work correctly without full memory info.
WindbgDemo.MemoryApply
    Content: string
    LineNumber: int
    ApplyTime: string
    DisposeDelgateEvent: WindbgDemo.DisposeDelgate
    m_disposed: bool
This command may not work correctly without full memory info.
01eebc24 (WindbgDemo.MemoryApply)
    Content:01eeb7a4 (System.String) Length=568, String="  康熙笑道:“什么胜过三个诸葛亮?你这马屁未免拍得太过。只是如何盯着刺客,不让他们发觉,倒不大易办。小桂子,我给你一件差使,你假装好人,将他们救出宫去,那些刺客当你是同道,自然带你去了。”韦小宝沉吟道:“这个……”康熙道:“这件事自然颇为危险,倘若给他们察觉了,非立时要了你的小命不可,只可惜我是皇帝,否则的话,我真想自己去干一下子。这滋味可妙得很哪。”
  韦小宝道:“皇上叫我去干,自然遵命,再危险的事也不怕。”
  康熙大喜,拍拍他的肩膀,笑道:“我早知你又聪明,又勇敢,很肯替我办事。你是小孩子,刺客不会起疑。我本想派两个武功好的侍卫去干,可是刺客不是笨人,未必会上当。一次试了不灵,第二次就不能再试了。小桂子,你去办这件事,就好象我亲身去办一样。”
  康熙学武功之后,跃跃欲试。一直想干几件危险之事,但身为皇帝,毕竟不便涉险,派韦小宝去干,就拿他当作自已替身,就算这件事由侍卫去办可能更好,他也宁可差韦小宝去。他想小桂子年纪和我相若,武功不及我,聪明不及我,他办得成,我自然也办得成,差他去办,和自己亲手去干,也已差不了多少,虽然不能亲历其境,但也可想象得之。
  康熙又道:“你要装得越像越好,最好能当着刺客之面,杀死一两名看守的侍卫,让这些刺客对你毫不怀疑。我再吩咐多隆,叫他放松盘查,让你带着他们出宫。”
"
    LineNumber:0xba3 (System.Int32)
    ApplyTime:01eebc4c (System.String) Length=23, String="2021-09-12 05:52:57.360"
    DisposeDelgateEvent: null
    m_disposed:true (System.Boolean)
This command may not work correctly without full memory info.
01eed134 (WindbgDemo.MemoryApply)
    Content:01eebc88 (System.String) Length=2639, String="  司徒伯雷身首异处,首级给巴朗星带了下山,王屋派众弟子无不悲愤已极。司徒鹤仍恐有诈,走近棺木,见棺盖并未上榫,揭开一看,果见父亲的首级赫然在内,不由得大恸,拜伏在地,放声大哭。其余弟子见他如此,一齐跪倒哀哭。司徒鹤站起身来,叫过四名师弟,抬了棺木上山,对韦小宝道:“便请尊驾赴先父灵前上一炷香。”韦小宝道:“自当去向老英雄灵前磕头。”命众亲兵在山口等候,只带了双儿和天地会兄弟,随着司徒鹤上山。
  韦小宝走到曾柔身边,低声道:“曾姑娘,你好!”曾柔脸上泪痕未干,一双眼哭得红红地,更显得楚楚可怜,抬起头来,抽抽噎噎的道:“你……你是花差……花差将军?”韦小宝大喜,道:“你记得我名字?”曾柔低头嗯了一声,脸上微微一红。她脸上这么一红,韦小宝心中登时一荡:“她为甚么见了我要脸红?男人笑眯眯,不是好东西,女人面孔红,心里想老公。莫非她想我做她老公?不知我给她的骰子还在不在?”低声问道:“曾姑娘,上次我给你的东西,你还收着吗?”曾柔脸上又是一红,转开了头,问道:“甚么东西?我忘啦?”韦小宝好生失望,叹了口气。曾柔回过头来,轻轻一笑,低声道:“别十!”韦小宝大喜,不由得心痒难搔,低声道:“我是别十,你是至尊!”曾柔不再理他,快步向前,走到司徒鹤身畔。那王屋山四面如削,形若王者车盖,以此得名,绝顶处称为天坛,东有日精峰,西有月华峰。一行人随着司徒鹤来到天坛以北的王母洞。一路上苍松翠柏,山景清幽。王屋山于道书中称“清虚小有洞天”,天下三十六洞天中名列第一,相传为黄帝会王母之处。王屋派人众聚居于王母洞及附近各洞之中,冬暖夏凉,胜于屋宇。
  司徒伯雷的灵位设在王母洞中。弟子将首级和身子缝上入殓。韦小宝率领天地会众兄弟在灵前上香致祭,跪下磕头,心想:“要讨好曾姑娘,须得越悲哀越好。”装假哭原是他的拿手好戏,想起在宫中数次给老婊子殴击的惨酷、为洪教主所擒后的惊险、一再被方怡欺骗的倒霉、阿珂只爱郑克* 的无可奈何,不由得悲从中来,放声大哭。初哭时尚颇勉强,这一哭开头,便即顺理成章,越哭越是悲切,大声道:“司徒老英雄,晚辈久闻你是一位忠臣义士,大大的英雄好汉。当年见到你公子的剑法,更知你武功了得,只盼能拜在你的门下,做个徒子徒孙,学几招武功,也好在江湖上扬眉吐气。哪知道你老人家为奸人所害,呜呜……呜呜……真叫人伤心之极了。”司徒鹤、曾柔等本已伤心欲绝,听他这么一哭,登时王母洞中哭声震天,哀号动地。徐天川、钱老本等本来不想哭的,也不禁为众人悲戚所感,洒了几滴眼泪。韦小宝捶胸顿足,大哭不休,反是王屋派弟子不住劝慰,这才收泪。他将巴朗星拉了过来,取过一柄钢刀,交在司徒鹤手里,说道:“司徒少侠,你杀了这奸贼,为令尊报仇。”司徒鹤一刀割下巴朗星的首级,放在供桌上。王屋派弟子齐向韦小宝拜谢大恩。本来韦小宝小小年纪,原也想不出这个收买人心的计策,那是他从《卧龙吊孝》这出戏中学来的。周瑜给诸葛亮气死后,诸葛亮亲往柴桑口致祭,哭拜尽哀,引得东吴诸将人人感怀。幸好戏中诸葛亮所念的祭文太长,辞句又太古雅,韦小宝一句也记不得,否则在王屋山上依样葫芦的念了出来,可就立时露出狐狸尾巴了。这么一来,王屋派诸人自然对他感恩戴德,何况当日韦小宝将司徒鹤等擒住之后,赠银释放,卖过一番大大的交情。但他是清廷贵官,何以如此,众人始终不解。钱老本将司徒鹤叫在一旁,说明自己一伙人乃天地会青木堂兄弟。但韦小宝在朝廷为官,他的身份却不能吐露,只怕一有泄漏,坏了大事,只含糊其辞,说他为人极有义气,“身在曹营心在汉”,众兄弟都当他是好朋友。司徒鹤一听之下,恍然大悟,更连连称谢,其时语出至诚,比之适才心中疑虑未释,又是不同了。跟着谈起王屋派今后出处,司徒鹤说派中新遭大丧,又逢官兵围山,也没想过这回事。钱老本微露招揽之意。天地会在江湖上威名极盛,隐为当世反清复明的领袖,王屋派向来敬慕,又是志同道合。司徒鹤一听大喜,便与派中耆宿及诸师兄弟商议,人人赞同。他当即向钱老本请求加盟。钱老本这时才对他明言,韦小宝实是青木堂的香主。当日下午,天地会青木堂在王母洞中大开香堂,接纳王屋派诸人入会。众人拜过香主,便都是韦小宝的部属了。他心中欢喜,饮过结盟酒后,便想开赌,和新旧兄弟大赌一场。李力世、钱老本等连忙劝阻,说道兴高采烈的赌钱,未免对刚逝世的司徒伯雷不敬。韦小宝赌不成钱,有些扫兴,问起王屋派的善后事宜。李力世道:“王屋山在山西、河南两省交界,不属咱们青木堂管辖。按照本会规矩,越界收兄弟入会,是不妨的,但各堂兄弟不能越界办事,最好司徒兄弟各位移去直隶省居住。”钱老本道:“鞑子皇帝差韦香主来攻打王屋山,司徒兄弟各位今后不在王屋山了,韦香主就易于上报。”司徒鹤道:“正是,小弟谨遵各位大哥吩咐。”韦小宝道:“司徒大哥,现下我们要去扬州,给史阁部起一座忠烈祠。这祠堂起好,大伙儿就去打吴三桂了。”司徒鹤站起身来,大声道:“韦香主去打吴三桂,属下愿为前锋,率同师兄弟姊妹,跟吴三桂这恶贼拚个死活,为先父报仇雪恨。”韦小宝喜道:“那再好也没有了,各位这就随我去扬州罢。只不过须得扮作鞑子官兵,委屈了一些。”司徒鹤道:“为了打吴三桂,再大的委屈也是甘心。韦香主做得鞑子官,我们自也做得鞑子兵。何况李大哥、徐大哥各位,不也都扮作了鞑子兵吗?”当晚众人替司徒伯雷安葬后,收拾下山。会武功的男子随着韦小宝前赴扬州。老弱妇孺则到保定府择地安居,该处有天地会青木堂的分舵,自有人妥为照应。
  韦小宝对张勇等言道,王屋山匪徒眼见大军围住,知道难以脱逃,经一番开导,大家一起归降。他已予以招安,收编为官兵。张勇等齐向他庆贺,说道都统兵不血刃,平定了王屋山的悍匪,立下大功。韦小宝道:“这是四位将军之功,若不是你们团团围住,众匪插翅难飞,他们也决计不肯投降。待兄弟申报朝廷,各有升赏。”四将大喜,知道兵部尚书明珠对他竭力奉承,只要是韦都统奏报的功劳,兵部一定从优叙议。韦小宝初时担心曾柔跟随王屋派妇孺,前赴保定府安居,如指定要她同去扬州,可有些说不出口。待见她换上男装,与司徒鹤等同行,心中说不出的欢喜。一路之上,他总想寻个机会,跟她亲热一番。可是曾柔和众位师兄寸步不离,见到了他,只腼腼腆腆的微笑不语。韦小宝想要和她说句亲热话儿,始终不得其便,不由得心痒难搔。倘若他只是清军主帅,早就假公济私,调这小亲兵入营侍候,但身为天地会香主,调戏会中妇女乃是厉禁,众兄弟面上也不好看,只有干咽馋涎,等候机会了。
  <图片>
"
    LineNumber:0x1d70 (System.Int32)
    ApplyTime:01eed15c (System.String) Length=23, String="2021-09-12 05:52:58.406"
    DisposeDelgateEvent: null
    m_disposed:true (System.Boolean)
This command may not work correctly without full memory info.

7、.foreach /pS 0n20 /ps 0n1 (str {!da 01efa04c }) { !sosex.mdt ${str} } 这个命令可以打印出这个数组里所有的对象。查阅帮助文档,很容易知道 /ps表示跳过多少个元素之类的。但这个20,这个1是怎么算出来的呢?

0:004> !da 01efa04c
Name:        WindbgDemo.MemoryApply[]
MethodTable: 002352fc
EEClass:     65874b80
Size:        268(0x10c) bytes
Array:       Rank 1, Number of elements 64, Type CLASS
Element Methodtable: 00234e98
[0] 01eebc24
[1] 01eed134
[2] 01eed780
...
[62] 01f057a8
[63] 01f05e34

8、对以上标红输出结果,按照空格分隔,来数个数吧。

1 Name:        
2 WindbgDemo.MemoryApply[]
3 MethodTable: 
4 002352fc
5 EEClass:     
6 65874b80
7 Size:        
8 268(0x10c) 
9 bytes
10 Array:       
11 Rank 
12 1,  
13 Number 
14 of 
15 elements 
16 64, Type 
17 CLASS
18 Element 
19 Methodtable: 
20 00234e98


1 [0] 
01eebc24

9、也可以使用其他命令来显示 .foreach (address  {!DumpHeap -mt 00234e98  -short }) {!do poi(${address}+0x4) }

0:004> .foreach (address  {!DumpHeap -mt 00234e98  -short }) {!do poi(${address}+0x4) }
Name:        System.String
MethodTable: 65c9d484
EEClass:     65874a50
Size:        1150(0x47e) bytes
File:        C:\Windows\Microsoft.Net\assembly\GAC_32\mscorlib\v4.0_4.0.0.0__b77a5c561934e089\mscorlib.dll
String:        康熙笑道:“什么胜过三个诸葛亮?你这马屁未免拍得太过。只是如何盯着刺客,不让他们发觉,倒不大易办。小桂子,我给你一件差使,你假装好人,将他们救出宫去,那些刺客当你是同道,自然带你去了。”韦小宝沉吟道:“这个……”康熙道:“这件事自然颇为危险,倘若给他们察觉了,非立时要了你的小命不可,只可惜我是皇帝,否则的话,我真想自己去干一下子。这滋味可妙得很哪。”
  韦小宝道:“皇上叫我去干,自然遵命,再危险的事也不怕。”
  康熙大喜,拍拍他的肩膀,笑道:“我早知你又聪明,又勇敢,很肯替我办事。你是小孩子,刺客不会起疑。我本想派两个武功好的侍卫去干,可是刺客不是笨人,未必会上当。一次试了不灵,第二次就不能再试了。小桂子,你去办这件事,就好象我亲身去办一样。”
  康熙学武功之后,跃跃欲试。一直想干几件危险之事,但身为皇帝,毕竟不便涉险,派韦小宝去干,就拿他当作自已替身,就算这件事由侍卫去办可能更好,他也宁可差韦小宝去。他想小桂子年纪和我相若,武功不及我,聪明不及我,他办得成,我自然也办得成,差他去办,和自己亲手去干,也已差不了多少,虽然不能亲历其境,但也可想象得之。
  康熙又道:“你要装得越像越好,最好能当着刺客之面,杀死一两名看守的侍卫,让这些刺客对你毫不怀疑。我再吩咐多隆,叫他放松盘查,让你带着他们出宫。”

Fields:
      MT    Field   Offset                 Type VT     Attr    Value Name
65c9f2d8  4000273        4         System.Int32  1 instance      568 m_stringLength
65c9decc  4000274        8          System.Char  1 instance     3000 m_firstChar
65c9d484  4000278       50        System.String  0   shared   static Empty
    >> Domain:Value  002d6480:NotInit  <<
Name:        System.String
MethodTable: 65c9d484
EEClass:     65874a50
Size:        5292(0x14ac) bytes
File:        C:\Windows\Microsoft.Net\assembly\GAC_32\mscorlib\v4.0_4.0.0.0__b77a5c561934e089\mscorlib.dll
String:        司徒伯雷身首异处,首级给巴朗星带了下山,王屋派众弟子无不悲愤已极。司徒鹤仍恐有诈,走近棺木,见棺盖并未上榫,揭开一看,果见父亲的首级赫然在内,不由得大恸,拜伏在地,放声大哭。其余弟子见他如此,一齐跪倒哀哭。司徒鹤站起身来,叫过四名师弟,抬了棺木上山,对韦小宝道:“便请尊驾赴先父灵前上一炷香。”韦小宝道:“自当去向老英雄灵前磕头。”命众亲兵在山口等候,只带了双儿和天地会兄弟,随着司徒鹤上山。
  韦小宝走到曾柔身边,低声道:“曾姑娘,你好!”曾柔脸上泪痕未干,一双眼哭得红红地,更显得楚楚可怜,抬起头来,抽抽噎噎的道:“你……你是花差……花差将军?”韦小宝大喜,道:“你记得我名字?”曾柔低头嗯了一声,脸上微微一红。她脸上这么一红,韦小宝心中登时一荡:“她为甚么见了我要脸红?男人笑眯眯,不是好东西,女人面孔红,心里想老公。莫非她想我做她老公?不知我给她的骰子还在不在?”低声问道:“曾姑娘,上次我给你的东西,你还收着吗?”曾柔脸上又是一红,转开了头,问道:“甚么东西?我忘啦?”韦小宝好生失望,叹了口气。曾柔回过头来,轻轻一笑,低声道:“别十!”韦小宝大喜,不由得心痒难搔,低声道:“我是别十,你是至尊!”曾柔不再理他,快步向前,走到司徒鹤身畔。那王屋山四面如削,形若王者车盖,以此得名,绝顶处称为天坛,东有日精峰,西有月华峰。一行人随着司徒鹤来到天坛以北的王母洞。一路上苍松翠柏,山景清幽。王屋山于道书中称“清虚小有洞天”,天下三十六洞天中名列第一,相传为黄帝会王母之处。王屋派人众聚居于王母洞及附近各洞之中,冬暖夏凉,胜于屋宇。
  司徒伯雷的灵位设在王母洞中。弟子将首级和身子缝上入殓。韦小宝率领天地会众兄弟在灵前上香致祭,跪下磕头,心想:“要讨好曾姑娘,须得越悲哀越好。”装假哭原是他的拿手好戏,想起在宫中数次给老婊子殴击的惨酷、为洪教主所擒后的惊险、一再被方怡欺骗的倒霉、阿珂只爱郑克* 的无可奈何,不由得悲从中来,放声大哭。初哭时尚颇勉强,这一哭开头,便即顺理成章,越哭越是悲切,大声道:“司徒老英雄,晚辈久闻你是一位忠臣义士,大大的英雄好汉。当年见到你公子的剑法,更知你武功了得,只盼能拜在你的门下,做个徒子徒孙,学几招武功,也好在江湖上扬眉吐气。哪知道你老人家为奸人所害,呜呜……呜呜……真叫人伤心之极了。”司徒鹤、曾柔等本已伤心欲绝,听他这么一哭,登时王母洞中哭声震天,哀号动地。徐天川、钱老本等本来不想哭的,也不禁为众人悲戚所感,洒了几滴眼泪。韦小宝捶胸顿足,大哭不休,反是王屋派弟子不住劝慰,这才收泪。他将巴朗星拉了过来,取过一柄钢刀,交在司徒鹤手里,说道:“司徒少侠,你杀了这奸贼,为令尊报仇。”司徒鹤一刀割下巴朗星的首级,放在供桌上。王屋派弟子齐向韦小宝拜谢大恩。本来韦小宝小小年纪,原也想不出这个收买人心的计策,那是他从《卧龙吊孝》这出戏中学来的。周瑜给诸葛亮气死后,诸葛亮亲往柴桑口致祭,哭拜尽哀,引得东吴诸将人人感怀。幸好戏中诸葛亮所念的祭文太长,辞句又太古雅,韦小宝一句也记不得,否则在王屋山上依样葫芦的念了出来,可就立时露出狐狸尾巴了。这么一来,王屋派诸人自然对他感恩戴德,何况当日韦小宝将司徒鹤等擒住之后,赠银释放,卖过一番大大的交情。但他是清廷贵官,何以如此,众人始终不解。钱老本将司徒鹤叫在一旁,说明自己一伙人乃天地会青木堂兄弟。但韦小宝在朝廷为官,他的身份却不能吐露,只怕一有泄漏,坏了大事,只含糊其辞,说他为人极有义气,“身在曹营心在汉”,众兄弟都当他是好朋友。司徒鹤一听之下,恍然大悟,更连连称谢,其时语出至诚,比之适才心中疑虑未释,又是不同了。跟着谈起王屋派今后出处,司徒鹤说派中新遭大丧,又逢官兵围山,也没想过这回事。钱老本微露招揽之意。天地会在江湖上威名极盛,隐为当世反清复明的领袖,王屋派向来敬慕,又是志同道合。司徒鹤一听大喜,便与派中耆宿及诸师兄弟商议,人人赞同。他当即向钱老本请求加盟。钱老本这时才对他明言,韦小宝实是青木堂的香主。当日下午,天地会青木堂在王母洞中大开香堂,接纳王屋派诸人入会。众人拜过香主,便都是韦小宝的部属了。他心中欢喜,饮过结盟酒后,便想开赌,和新旧兄弟大赌一场。李力世、钱老本等连忙劝阻,说道兴高采烈的赌钱,未免对刚逝世的司徒伯雷不敬。韦小宝赌不成钱,有些扫兴,问起王屋派的善后事宜。李力世道:“王屋山在山西、河南两省交界,不属咱们青木堂管辖。按照本会规矩,越界收兄弟入会,是不妨的,但各堂兄弟不能越界办事,最好司徒兄弟各位移去直隶省居住。”钱老本道:“鞑子皇帝差韦香主来攻打王屋山,司徒兄弟各位今后不在王屋山了,韦香主就易于上报。”司徒鹤道:“正是,小弟谨遵各位大哥吩咐。”韦小宝道:“司徒大哥,现下我们要去扬州,给史阁部起一座忠烈祠。这祠堂起好,大伙儿就去打吴三桂了。”司徒鹤站起身来,大声道:“韦香主去打吴三桂,属下愿为前锋,率同师兄弟姊妹,跟吴三桂这恶贼拚个死活,为先父报仇雪恨。”韦小宝喜道:“那再好也没有了,各位这就随我去扬州罢。只不过须得扮作鞑子官兵,委屈了一些。”司徒鹤道:“为了打吴三桂,再大的委屈也是甘心。韦香主做得鞑子官,我们自也做得鞑子兵。何况李大哥、徐大哥各位,不也都扮作了鞑子兵吗?”当晚众人替司徒伯雷安葬后,收拾下山。会武功的男子随着韦小宝前赴扬州。老弱妇孺则到保定府择地安居,该处有天地会青木堂的分舵,自有人妥为照应。
  韦小宝对张勇等言道,王屋山匪徒眼见大军围住,知道难以脱逃,经一番开导,大家一起归降。他已予以招安,收编为官兵。张勇等齐向他庆贺,说道都统兵不血刃,平定了王屋山的悍匪,立下大功。韦小宝道:“这是四位将军之功,若不是你们团团围住,众匪插翅难飞,他们也决计不肯投降。待兄弟申报朝廷,各有升赏。”四将大喜,知道兵部尚书明珠对他竭力奉承,只要是韦都统奏报的功劳,兵部一定从优叙议。韦小宝初时担心曾柔跟随王屋派妇孺,前赴保定府安居,如指定要她同去扬州,可有些说不出口。待见她换上男装,与司徒鹤等同行,心中说不出的欢喜。一路之上,他总想寻个机会,跟她亲热一番。可是曾柔和众位师兄寸步不离,见到了他,只腼腼腆腆的微笑不语。韦小宝想要和她说句亲热话儿,始终不得其便,不由得心痒难搔。倘若他只是清军主帅,早就假公济私,调这小亲兵入营侍候,但身为天地会香主,调戏会中妇女乃是厉禁,众兄弟面上也不好看,只有干咽馋涎,等候机会了。
  <图片>

 

posted @ 2021-09-20 16:36  hzwanglw  阅读(265)  评论(0)    收藏  举报