2024年1月

热点随笔:

·
为什么Java中“1000==1000”为false,而”100==100“为true?
(
YSOcean
)
·
微软用它取代了`Nginx`吞吐量提升了百分之八十!
(
tokengo
)
·
园子开店记-周边第一款:收到鼠标垫样品(新增另外3款照片)
(
博客园团队
)
·
别让“防御性编程”毁了我们的职业
(
MeteorSeed
)
·
屎山代码风格指南(避免被优化&&避免被接盘)
(
有只橘猫
)
·
C# 成为2023年度编程语言之王
(
张善友
)
·
高并发扣款,如何保证结果一致性
(
架构成长指南
)
·
现代 CSS 解决方案:文字颜色自动适配背景色!
(
ChokCoco
)
·
程序员创业该做什么产品?
(
闲者何去
)
·
.NET开源、强大的Web报表统计系统
(
追逐时光者
)
·
2024年,在风云际会的编程世界里,窥探Java的前世今生,都说它穷途末路,我认为是柳暗花明!
(
JavaBuild
)
·
去年最火的 JS 开源项目「GitHub 热点速览」
(
削微寒
)

热点新闻:

·
外卖盒、瓶装水正摧毁你的身体!最新研究:仅2小时就能穿透血脑屏障,抵达大脑组织
·
每年多放25天,乐视的假期遥遥领先
·
新型固态电池充满电仅需几分钟
·
R语言社区知名开发者 “谢益辉” 被 RStudio/Posit 公司解雇
·
C919执飞京沪线!东航已接收四架,国产大飞机进入常态化运营阶段
·
Visual Studio 17.9第2个预览版发布,改进.NET MAUI、C++、远程 Linux 单元测试、团队工具包等
·
每多吃100g猪肉或牛肉,患糖尿病风险高27%,患心血管疾病高11%
·
西溪码农,滨江网红,杭州消逝的大平层
·
欧洲芯片,四面楚歌
·
脉脉,终尝大厂之苦
·
三七互娱创始人7年前朋友圈被挖:员工不情愿6天工作制悲哀
·
京东宣布大幅涨薪,真的该叫好吗?

操作滚动条可以通过锚点跳转,JS操作滚动条,与scrollIntoView等方法。对此,我来考古一下。

锚点跳转滚动滚动条

网页中的锚点跳转是HTML早期功能之一,
锚点(anchor)跳转是1991年发布的HTML标准的一部分,这是超文本链接的基本特性

锚点跳转通过使用<a>标签的href属性来创建指向页面内部某个ID或名称(使用id或name属性标记的)的链接来实现。

<!-- 目标位置 -->
<div id="section1">This is Section 1</div>
**************长内容********************
<!-- 页内跳转链接,条件跳转到 Section 1-->
<a href="#section1">Jump to Section 1</a>

即使是最早的Web浏览器,如NCSA Mosaic,也支持页面内通过锚点进行跳转!

关于浏览器历史,参看:《
浏览器史话中chrome霸主地位的奠定与国产浏览器的割据混战

浏览器始祖NCSA
Mosaic
在1993年1月发布(于1992年末由国家超级计算机应用中心—National Center for Supercomputing Applications开发)。Mosaic可以同时展示文字和图片,从此浏览器变得有趣多了。 在当时人气爆发的大受欢迎。
Mosaic的出现,算是点燃了后期互联网热潮的火种之一
。NCSA将Mosaic的商业运营权转售给了Spyglass公司,该公司又向包括微软公司在内的多家公司技术授权,允许其在 Mosaic的基础上开发自己的产品

1994年10月13日,网景通信公司推出发布了Mosaic Netscape 0.9

1994年开始,网景通信公司推出了代号为
Netscape Navigator
1.0(网景导航者、网景浏览器),随后迭代版本迅速占领浏览器大部分份额。Netscape自称“
Mozilla
/1.0(Win3.1)”,一说 Mozilla = Mosaic + Killer,意为Mosaic杀手,也有说法是 Mozilla = Mosaic & Godzilla,意为马赛克和哥斯拉,而Mozilla最初的吉祥物是只绿色大蜥蜴,后来更改为红色暴龙,跟哥斯拉长得一样。

1995年起搭载cookie、框架和JavaScript等多样独自功能的2.0版上市。从前前端码农开始可以大踏步干活了,与通宵达旦干兼容血战到底。网景支持框架(frame),但是Mosaic不支持框架,于是网站管理员探测user agent,对Mozilla浏览器发送含有框架的页面,对非Mozilla浏览器发送没有框架的页面。

关于JavaScript,参看:《
ECMAScript进化史(1):话说Web脚本语言王者JavaScript的加冕历史
》与《
JS引擎(0):JavaScript引擎群雄演义—起底JavaScript引擎

1995年Sun公司将Oak语言改名为Java,正式向市场推出(次年,LiveScript改名为JavaScript)。

Sun公司大肆宣传,许诺这种语言可以"一次编写,到处运行"(Write Once, Run Anywhere),它看上去很可能成为未来的主宰。

网景公司动了心,决定与Sun公司结成联盟。它不仅允许Java程序以applet(小程序)的形式,直接在浏览器中运行;甚至还考虑直接将Java作为脚本语言嵌入网页,只是因为这样会使HTML网页过于复杂,后来才不得不放弃。总之,当时的形势就是,
网景公司的整个管理层,都是Java语言的信徒,Sun公司完全介入网页脚本语言的决策

1995年4月,网景公司录用34岁Brendan Eich( JavaScript 之父 闪亮登场)。

Brendan Eich被指定为这种"简化版Java语言"的设计师
。但是,他对Java一点兴趣也没有。为了完成(应付)公司安排的任务,他只用10天时间就把JavaScript设计出来了。虽然语言的设计者水平非常NB,但谁也架不住“时间紧,任务重”。由于设计时间太短,语言的一些细节考虑得不够严谨,导致后来很长一段时间,Javascript写出来的程序混乱不堪。如果不是公司的决策,Brendan Eich绝不可能把Java作为Javascript设计的原型。作为设计者,他都不喜欢这个作品!

1995年浏览器有JavaScript 功能,可以通过JavaScript 手动更爱hash进行跳转

window.location.hash="section1"

JavaScript操作滚动条,还是不尽人意

操作滚动条滚动

1997年,
JavaScript由ECMA International采纳为标准(ECMAScript),从而确保了不同浏览器之间的一致性和兼容性

scroll和scrollTo在现代浏览器中都支持的

// 使用scrollTo滚动页面到指定位置(100px, 100px)
window.scrollTo(100, 100);

// 使用scroll执行相同的操作
window.scroll(100, 100);

允许你指定滚动行为(如是否平滑滚动):

// 使用对象参数带有平滑滚动
window.scrollTo({ top: 100, left: 100, behavior: 'smooth' });

// 使用scroll实现同样的滚动效果
window.scroll({ top: 100, left: 100, behavior: 'smooth' });

但是要滚动锚点位置,需要计算滚动的位置,如果是嵌套套娃,就非常复杂——可以复习下:《
再谈BOM和DOM(6):dom对象及event对象位值计算—如offsetX/Top,clentX

这个方法,我劝读者放弃!

scrollIntoView滚动到指定为止

2000年,DOM2规范 带来了scrollIntoView API,但是微软从屠龙少年变恶龙后,就奔对新规范置之不理了!——这个API目前除了IE,可以放心用!

document.getElementById("section1").scrollIntoView();
// 或者
document.querySelector("#section1").scrollIntoView(true);

更加精细化控制:

element.scrollIntoView({ behavior: "smooth", block: "end", inline: "nearest" });

具体查看:
https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollIntoView

animate大法

是否还记得jquery时代的(2006年8月发布的jquery1.0 版本就推出了animate)

$("#button").click(function() {
  $("html, body").animate({
    scrollTop: $("#section1").offset().top }, {duration: 500,easing: "swing"});
    return false;
});

animate()方法使得很容易对CSS属性实施动画效果,并且随着jQuery库的普及,animate()方法也迅速成为一个广为人知的标准做法。


css过去及未来展望—分析css演进及排版布局的考量

1999年,CSS 3的草稿开始制定

2001年5月23日W3C完成了CSS3的工作草案,主要包括盒子模型、列表模块、超链接方式、语言模块、背景和边框、文字特效、多栏布局等模块

2005 年 12 月,W3C 开始 CSS3 标准的制定。css是有一系列的标准组成。每个系列完成的时间不一样。所以css3是不断的演进的,直到现在。

CSS逐步普及,但是精确控制css3的动画,还是非常麻烦。


复杂web动画,不慌,选择 web Animations API
》,比如直播的世界消息或者弹幕:

我们需要消息先运动到屏幕中间,消息最少需要在停留2秒,如果消息过长,消息还需要
匀速滚动
,之后再滑出屏幕。

  1. 滑入

  2. 暂停,如果消息过长,消息还需要匀速滚动

  3. 滑出

难点就在于,暂停阶段,消息滚动的时间并不是确定的,需要计算。 这个时候,纯CSS3的动画,难度就有些高了,采用 Web Animations API,天然的和JS亲和,那就简单多了。

2013年,W3C 提出 Web Animation API(简称 WAAPI)工作草案,但是知道如今(截止2024年1月)还是草案状态(十年磨一剑——CSS3又何尝不是如此!)。但是目前chrome基本都支持!

具体可以MDN例子:
https://developer.mozilla.org/zh-CN/docs/Web/API/Element/animate

这里不在赘述,但是只是为了滚动条滚动,用这个api 是大材小用哈!


转载
本站
文章《
操作滚动条小结:scrollIntoView/animate等方法的来龙去脉
》,
请注明出处:
https://www.zhoulujun.cn/html/webfront/SGML/htmlBase/2022_1223_9017.html

介绍

最近,AI 引起了广泛关注,而 Kubernetes 驱动的 DevOps 也不例外。软件工程师是自动化的忠实拥护者,因此针对 Kubernetes 操作员的 AI 驱动工具自然也开始涌现。

这些工具大多专为终端 (CLI) 使用而设计。Kubernetes 是容器编排的首选平台,而在 AI 驱动工具的帮助下可以从自动化任务、提高可靠性和提供洞察力等方面来帮助您更好掌握它。

OpenAI 是 Kubernetes AIOps 最有前途的 AI 平台之一。它提供了一套开源工具,可用于为 Kubernetes 构建 AI 驱动的解决方案。我们将分成两个 parts 来探讨 OpenAI 的一些开源工具如何帮助您实现 Kubernetes AIOps。

概述

Kubernetes 用户不可避免地会遇到一些需要调试和修复的集群问题,以保证其 pod 和服务顺利运行。尤其是云端原生的DevOps 可能在管理容器、微服务和自动扩展功能方面涉及很多复杂问题。GenAI 可以
帮助排除故障,并执行一些与 Kubernetes 等平台相关的操作任务
。这可能涉及使用自然语言提示来启动、回滚或获取集群的可见性。

例如,在 KubeCon + CloudNativeCon 2023 大会上,Kubiya 首次展示了一个生成式 AI 工作流引擎,它能够在 Slack 中解释此类命令。扩展自然语言处理功能可以帮助平台团队创建新的工作流程,从而抽象出云端原生平台工作的复杂性。

K8sGPT

K8sGPT 是一个相对较新的开源项目,
它使用 AI 模型来解释 Kubernetes 的错误信息并提供集群见解
。它已被两个组织用于生产,并已申请成为 CNCF 沙盒项目。

其主要功能有:

  • 提供 Kubernetes 错误信息的详细情境解释
  • 提供集群洞察
  • 支持多种安装选项
  • 支持不同的 AI 后端

K8sGPT 的项目由是同类 CLI 工具中最知名、使用最广泛的一个,其主要命令是
k8sgpt analyze

旨在揭示 Kubernetes 集群中的问题
。它通过使用 analyzers 来做到这一点。这种 analyzers 定义了每个 Kubernetes 对象的逻辑以及可能遇到的问题。例如,Kubernetes Services 的 analyzers 会检查特定 Services 是否存在、是否有端点,以及端点是否准备就绪。

更厉害的在于当您要求 K8sgpt 解释能做些什么——为此,需要运行
k8sgpt analyze --explain
命令。这将要求 AI 为您的具体情况提供说明,并显示出来。这些说明包括
排除故障的操作以及具体的 kubectl 命令
,您只需复制和粘贴这些命令即可执行。而之所以能做到这一点,是因为 Kubernetes 资源的名称已经就位了。

image

安装

根据您的偏好和操作系统,有多种安装选项可供选择。您可以在文档的安装部分找到不同的选项。安装 K8sGPT 的前提条件是在 Mac 上安装 Homebrew 或在 Windows 机器上安装 WSL。

接下来,您可以运行以下命令:

brew tap k8sgpt-ai/k8sgpt 
brew install k8sgpt

如要查看 K8sGPT 提供的所有命令,请使用
- help
标志:

k8sgpt --help

前提条件

后续步骤的前提条件是拥有一个 OpneAI 账户和一个正在运行的 Kubernetes 集群;任何集群,比如 microk8s 或 minikube 都足够了。

有了 OpneAI 账户后,您需要去其网站生成一个新的 API 密钥

或者,你也可以运行以下命令,K8sGPT 会在你的默认浏览器中打开相同的网站:

k8sgpt generate

K8sGPT 与 OpenAI 交互时需要此密钥。使用新创建的 API 密钥/令牌授权 K8sGPT:

k8sgpt auth add openai 
Enter openai Key: openai added to the AI backend provider list

您可以使用以下命令列出您的后端:

k8sgpt auth list
Default: 
> openai 
Active: 
> openai 
Unused: 
> localai 
> azureopenai 
> noopai

其次,我们将在 Kubernetes 集群中安装恶意部署。该 pod 将进入 CrashLoopBackOff。下面是 YAML:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
  labels:
    app: nginx
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.14.2
        ports:
        - containerPort: 80
        securityContext:
          readOnlyRootFilesystem: true

接下来,我们将为示例应用程序创建一个专用命名空间,并安装 Deployment:

kubectl create ns demo 
namespace/demo created
kubectl apply -f ./deployment.yaml -n demo
deployment.apps/nginx-deployment created

现在,您将看到演示命名空间中的 pod 标明错误:

image

如果我们想查看其中一个 pod 的事件,就会显示:

Warning  BackOff        3s (x8 over 87s)  kubelet                Back-off restarting failed container

因此,我们可以运行 K8sGPT 命令来获取更多有关这些 pod 出错原因的详细信息:

k8sgpt analyse

这将显示 K8sGPT 在集群中发现的问题:

AI Provider: openai

若想要获得更多信息以及如何解决问题的建议,我们则可以使用
--explain
标志:

k8sgpt analyse --explain
0 demo/nginx-deployment-5f4c7db77b-hq74n(Deployment/nginx-deployment)
- Error: back-off 1m20s restarting failed container=nginx pod=nginx-deployment-5f4c7db77b-hq74n_demo(7854b793-21b7-4f81-86e5-dbb4113f64f4)
1 demo/nginx-deployment-5f4c7db77b-phbq8(Deployment/nginx-deployment)
- Error: back-off 1m20s restarting failed container=nginx pod=nginx-deployment-5f4c7db77b-phbq8_demo(74038531-e362-45a6-a436-cf1a6ea46d8a)
2 demo/nginx-deployment-5f4c7db77b-shkw6(Deployment/nginx-deployment)
- Error: back-off 1m20s restarting failed container=nginx pod=nginx-deployment-5f4c7db77b-shkw6_demo(2603f332-3e1c-45da-8080-e34dd6d956ad)

kubectl-ai

该项目是一个
kubectl
插件,基于 GTP 生成和应用 Kubernetes Manifests 去
生成和应用 Kubernetes 清单
。为让其更有趣并以可视化的方式理解,我们将利用 Kubectl + OpenAI。

安装

Homebrew
:添加到
brew
tap 并安装

brew tap sozercan/kubectl-ai https://github.com/sozercan/kubectl-ai
brew install kubectl-ai

Krew
:添加到
krew
index再使用

kubectl krew index add kubectl-ai https://github.com/sozercan/kubectl-aikubectl 
krew install kubectl-ai/kubectl-ai

前提条件

kubectl-ai
需要有效的 Kubernetes 配置和以下条件之一:

  • OpenAI API 密钥
  • Azure OpenAI 服务 API 密钥和端点
  • LocalAI

对于这些工具,可以使用以下环境变量:

export OPENAI_API_KEY=<your OpenAI key>
export OPENAI_DEPLOYMENT_NAME=<your OpenAI deployment/model name. defaults to "gpt-3.5-turbo-0301">
export OPENAI_ENDPOINT=<your OpenAI endpoint, like "https://my-aoi-endpoint.openai.azure.com" or "http://localhost:8080/v1">

如果设置了
OPENAI_ENDPOINT
变量,则将使用端点。否则,将使用 OpenAI API。

Azure OpenAI 服务不允许在部署名称中使用某些字符,如
.
。因此,对于 Azure,kubectl-ai 会自动将
gpt-3.5-turbo
替换为
gpt-35-turbo
。但是,如果使用的 Azure OpenAI 部署名称与模型名称完全不同,可以设置
AZURE_OPENAI_MAP
环境变量,将模型名称映射到 Azure OpenAI 部署名称。例如:

export AZURE_OPENAI_MAP="gpt-3.5-turbo=my-deployment"

演示

Nginx Pod 的命令

kubectl ai "create an nginx pod"

kubectl ai "create an nginx pod"
✨ Attempting to apply the following manifest:
apiVersion: v1
kind: Pod
metadata:
  name: nginx-pod
spec:
  containers:
  - name: nginx
    image: nginx
    ports:
    - containerPort: 80
Use the arrow keys to navigate: ↓ ↑ → ← 
? Would you like to apply this? [Reprompt/Apply/Don't Apply]: 
+   Reprompt
  ▸ Apply
    Don't Apply

Deployment
:选择 "Reprompt" 并输入 "make this into deployment"

Reprompt: make this into deployment
✨ Attempting to apply the following manifest:
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.7.9
        ports:
        - containerPort: 80

ReplicaSet

Reprompt: Scale to 3 replicas
Reprompt: Scale to 3 replicas
✨ Attempting to apply the following manifest:
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx
        ports:
        - containerPort: 80

KoPylot

KoPylot 是一款由 AI 驱动的开源 Kubernetes 助手。其目标是
帮助开发人员和 DevOps 工程师轻松管理和监控 Kubernetes 集群

功能

在当前版本中,KoPylot 有四个主要功能。这些功能可以转化为
kopylot
CLI 的子命令。这些子命令是
Audit, Chat, Diagnose 和 Ctl
。现在让我们深入了解一下这些命令。

image

Audit
:Audit 资源,例如 pod、部署和服务。KoPylot 会根据单个资源的清单文件查找漏洞。

image

Chat
:用简单的英语询问 KoPylot 以生成 kubectl 命令。在运行命令之前,您可以查看命令。

image

Diagnose
:您可以使用诊断工具来帮助您调试应用程序的不同组件。诊断命令会为您列出损坏资源的可能修复方法。

image

Ctl
:kubectl 的包装器。传递给 ctl 子命令的所有参数都由 kubectl 解释。

image

运行原理

目前,KoPylot 的工作方式是从 Kubernetes 资源描述(kubectl describe ...)或清单中提取信息,并将其与提示一起输入 OpenAI 的 Davinci 模型。提示告诉模型如何处理 Kubernetes 资源。

提示还负责指导模型如何构建输出。例如,用于 Audit 命令的提示符要求模型将结果输出为包含漏洞及其严重程度的双列 JSON。

路线图的目标之一是用内部托管模型取代 OpenAI 模型。这将解决向 OpenAI 服务器发送潜在敏感数据的问题。

您可以按以下步骤使用 KoPylot:

  • 向 OpenAI 申请一个 API 密钥。
  • 使用以下命令导出密钥
export KOPYLOT_AUTH_TOKEN=
  • 使用 pip 安装 Kopylot:
pip install kopylot
  • 运行 Kopylot
kopylot --help

总的来说,KoPylot 是诊断 Kubernetes 工作负载并排除故障的有用工具。
它基于网络的聊天界面和 CLI 使其易于使用,适合所有级别的用户

Kopilot

Kopilot 是这些项目中唯一一个用 Go 编写的项目。它包括两个功能:故障排除和审计。

安装

macOS

brew install knight42/tap/kopilot

Krew:

kubectl krew install kopilot

目前,您需要设置两个 ENV 才能运行 Kopilot:

  • 设置
    KOPILOT_TOKEN
    以指定令牌。
  • 设置
    KOPILOT_LANG
    以指定语言,默认为
    English
    。有效选项包括
    Chinese

    French

    Spain
    等。

优势

  • 诊断集群中任何不健康的工作负载,并告诉您原因

image

  • Audit Kubernetes 资源并查找安全错误配置

image

想象一下,当您的 Pod 被卡或在
Pending

CrashLoopBackOff
的状态时,
kopilot diagnose
的命令就会派上用场了。它或将向 AI 寻求帮助,并将结论展示出来,其中还包括可能的原因解释。

image

并且,
kopilot audit
命令采用了类似的方法,能根据众所周知的优秀实践和可能的安全错误配置进行检查。该工具将使用您的 OpenAI API 令牌和您选择的语言来回答问题。

本篇 Part 1 主要介绍了 K8sGPT、kubectl-ai、KoPylot 和 Kopilot 四款 AI 工具,后续的 Part 2 会延续并介绍更多的工具内容,帮助您简化 K8s 的使用过程,敬请期待!

一、简介
今天是《Net 高级调试》的第十六篇文章,
也是这个系列的最后一篇文章了

既然是最后一篇文章,我需要在这里说明一下,我当前的这个系列,不是针对《Net 高级调试》这本书来的,而是根据“
一线码农
”的视频做的这个系列。当然了,他的视频是根据《Net 高级调试》这本书来的,内容上做了一些调整,可以说是与时俱进的。说实在的,我第一次看《Net 高级调试》这个本书是蒙的,不知道从何处入手,有一个视频带我入门,相对而言是更容易下一下。入门之后,在深入研究《Net 高级调试这个本书》。

好了废话就说这么多。今天是这个系列的最后一章,主要说一下【互用性】调试相关的内容,比如:P/Invoke调用的调试,互操作中的内存泄漏,COM互用性中终结操作的调试。我们写 C# 代码的,有时候也会用到P/Invoke调用的,多积累点经验是好事,我们可以做到有事不怕事,来者不拒。这些底层的东西,肯定不是一次就能接受的,所以,我们需要多次调试,才能慢慢体会其中之意,俗话说的好,书读千遍,其意自现。
如果在没有说明的情况下,所有代码的测试环境都是 Net Framewok 4.8,但是,有时候为了查看源码,可能需要使用 Net Core 的项目,我会在项目章节里进行说明。好了,废话不多说,开始我们今天的调试工作。

调试环境我需要进行说明,以防大家不清楚,具体情况我已经罗列出来。
操作系统:Windows Professional 10
调试工具:Windbg Preview(可以去Microsoft Store 去下载)
开发工具:Visual Studio 2022
Net 版本:Net Framework 4.8
CoreCLR源码:
源码下载


二、基础知识
1、平台调用 P/Invoke

1.1、简介
平台调用服务 P/Invoke 是 CLR 的一部分,负责确保托管代码可以调用从非托管程序集中导出的各种函数,原因很简单,托管类型参数和非托管类型参数是不一致的,比如:托管的引用类型是带有附加信息的,二非托管类型是不可能有的。

2、P/Invoke 的崩溃
2.1、调用协定引发的崩溃。
很多时候调用协定不一致容易造成程序的崩溃,这种问题需要通过【调试器】检查。

2.2、委托异步引发的崩溃
【托管代码】到【非托管代码】的切换过程中,对象的固定是有 P/Invoke 层全权负责的,但是这个固定的范围这个同步的 Request-Response 周期,如果超过请求相应周期,那就容易出现各种问题,比如:Example_16_1_4。

2.3、非托管内存泄漏
非托管内存泄露,这里就不多说,我们举例说明,直接看调试代码。(
这个方案没有完全解决,有些命令没有执行结果。


三、源码调试
废话不多说,这一节是具体的调试过程,又可以说是眼见为实的过程,在开始之前,我还是要啰嗦两句,这一节分为两个部分,第一部分是测试的源码部分,没有代码,当然就谈不上测试了,调试必须有载体。第二部分就是根据具体的代码来证实我们学到的知识,是具体的眼见为实。

1、项目源码
1.1、Example_16_1_1


1 usingSystem;2 usingSystem.Diagnostics;3 usingSystem.Runtime.InteropServices;4 
5 namespaceExample_16_1_16 {7     internal classProgram8 {9         /// <summary>
10         /// 
11         /// </summary>
12         /// <param name="freq"></param>
13         /// <param name="dur"></param>
14         /// <returns></returns>
15         [DllImport("Kernel32.dll", SetLastError = true)]16         private static extern bool Beep(uint freq, uintdur);17 
18 
19         static void Main(string[] args)20 {21 Debugger.Break();22 
23             Beep(1000, 1000);24 
25 Console.ReadLine();26 }27 }28 }

View Code


1.2、Example_16_1_2


1 usingSystem;2 usingSystem.Runtime.InteropServices;3 
4 namespaceExample_16_1_25 {6     internal classProgram7 {8         [DllImport("Example_16_1_3.dll", CallingConvention = CallingConvention.ThisCall, CharSet =CharSet.Unicode)]9         //[DllImport("Example_16_1_3.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode)]
10         public static extern void Alloc(stringstr);11         static void Main(string[] args)12 {13             var str = "hello world";14 
15 Alloc(str);16 
17 Console.ReadLine();18 }19 }20 }

View Code


1.3、Example_16_1_3(C++项目)


1 //Example_16_1_3.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
2 
3 extern "C"
4 {5     __declspec(dllexport) void Alloc(wchar_t*c);6 }7 
8 #include "iostream"
9 #include <Windows.h>
10 
11 using  namespacestd;12 
13 void Alloc(wchar_t*c)14 {15     wprintf(L"%s \n", c);16 }

View Code


1.4、Example_16_1_4


1 usingSystem;2 usingSystem.Runtime.InteropServices;3 
4 namespaceExample_16_1_45 {6     internal classProgram7 {8         public delegate void Callback(uinti);9         static void Main(string[] args)10 {11 Test();12             GC.Collect(); //不出问题的情况。
13 Console.ReadLine();14 }15 
16         //static GCHandle handle;
17         private static voidTest()18 {19             Callback callback =MyRun;20 
21             //handle=GCHandle.Alloc(callback, GCHandleType.Normal);
22 AsyncProcess(callback);23 
24             callback = null;25 }26 
27         private static void MyRun(uinti)28 {29             Console.WriteLine("这是非托管代码回调我的实现!");30 }31 
32         private static void MyCallback(stringresult)33 {34             Console.WriteLine($"Result={result}");35 }36 
37         [DllImport("Example_16_1_5", CallingConvention =CallingConvention.StdCall)]38         private static extern voidAsyncProcess(Callback callback);39 }40 }

View Code


1.5、Example_16_1_5(C++项目)


1 //Example_16_1_5.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。2 //3 
4 #include <iostream>
5 #include <Windows.h>
6 
7 using namespacestd;8 
9 typedef void(__stdcall*PCallback)(UINT result);10 
11 extern "C"
12 {13     _declspec(dllexport) void__stdcall AsyncProcess(PCallback ptr);14 }15 
16 DWORD WINAPI ThreadWorkItem(LPVOID lpParameter)17 {18     printf("我是非托管的工作线程,tid=%d \n", GetCurrentThreadId());19 
20     Sleep(2000);21 
22     PCallback callback =(PCallback)lpParameter;23 
24     callback(0);25 
26     return 0;27 }28 
29 void__stdcall AsyncProcess(PCallback ptr)30 {31     HANDLE hThread = CreateThread(NULL, 0, ThreadWorkItem, ptr, 0, NULL);32 }

View Code


1.6、Example_16_1_6


1 usingSystem;2 usingSystem.Runtime.InteropServices;3 usingSystem.Threading.Tasks;4 
5 namespaceExample_16_1_66 {7     internal classProgram8 {9         [DllImport("Example_16_1_7", CallingConvention =CallingConvention.StdCall)]10         private static extern int InitData(intlen);11 
12         static void Main(string[] args)13 {14             var task = Task.Factory.StartNew(() =>
15 {16                 for (int i = 0; i < int.MaxValue; i++)17 {18                     InitData(10000);19 
20                     Console.WriteLine($"i={i} 次操作!");21 }22 });23 
24 Console.ReadLine();25 }26 }27 }

View Code


1.7、Example_16_1_7(C++项目)


1 //Example_16_1_7.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。2 //3 
4 #include <iostream>
5 #include <Windows.h>
6 
7 using namespacestd;8 
9 extern "C"
10 {11     _declspec(dllexport) int __stdcall InitData(intlen);12 }13 
14 int __stdcall InitData(intlen) {15     char* c = new char[len];16     return 1;17 }

View Code



2、眼见为实
项目的所有操作都是一样的,所以就在这里说明一下,但是每个测试例子,都需要重新启动,并加载相应的应用程序,加载方法都是一样的。流程如下:我们编译项目,打开 Windbg,点击【文件】----》【launch executable】附加程序,打开调试器的界面,程序已经处于中断状态。

我们需要使用【g】命令,继续运行程序,然后到达指定地点停止后,我们可以点击【break】按钮,就可以调试程序了。
有时候可能需要切换到主线程,可以使用【~0s】命令。

2.1、如何观察 P/Invoke 是CLR的一部分。
调试源码:Example_16_1_1
因为【Beep】是Windows 提供的蜂鸣函数,可以直接用【bp】命令下断点,过了这么多年,这个函数的名称也有了变化,现在是【
KERNEL32!BeepImplementation
】。
当我们进入 Windbg 调试器界面后,我们使用【x】命令,查找一下【Beep】这个函数。

1 0:000> x kernel32!*beep*
2 7771194c          KERNEL32!_imp__Beep = <no type information>
3 776c0660          KERNEL32!BeepImplementation (_BeepImplementation@8)

然后我们在这个方法上下断点,通过【bp
KERNEL32!BeepImplementation
】命令下断点,然后继续【g】运行调试器。

1 0:000> bp KERNEL32!BeepImplementation2 0:000>g3 ModLoad: 75760000757d9000   C:\Windows\SysWOW64\ADVAPI32.dll4 ModLoad: 76de0000 76e9f000   C:\Windows\SysWOW64\msvcrt.dll5 ModLoad: 75a10000 75a85000   C:\Windows\SysWOW64\sechost.dll6 ModLoad: 754c0000 7557a000   C:\Windows\SysWOW64\RPCRT4.dll7 ModLoad: 750f0000 7517d000   C:\Windows\Microsoft.NET\Framework\v4.0.30319\mscoreei.dll8 ModLoad: 75ed0000 75f15000   C:\Windows\SysWOW64\SHLWAPI.dll9 ModLoad: 764000007640f000   C:\Windows\SysWOW64\kernel.appcore.dll10 ModLoad: 75340000 75348000C:\Windows\SysWOW64\VERSION.dll11 ModLoad: 74740000 74ef0000   C:\Windows\Microsoft.NET\Framework\v4.0.30319\clr.dll12 ModLoad: 75a90000 75c24000   C:\Windows\SysWOW64\USER32.dll13 ModLoad: 75f90000 75fa8000   C:\Windows\SysWOW64\win32u.dll14 ModLoad: 739c0000 73a6b000   C:\Windows\SysWOW64\ucrtbase_clr0400.dll15 ModLoad: 73a70000 73a84000   C:\Windows\SysWOW64\VCRUNTIME140_CLR0400.dll16 ModLoad: 75c30000 75c53000   C:\Windows\SysWOW64\GDI32.dll17 ModLoad: 76410000764eb000   C:\Windows\SysWOW64\gdi32full.dll18 ModLoad: 76360000763db000   C:\Windows\SysWOW64\msvcp_win.dll19 ModLoad: 755a0000 756c0000   C:\Windows\SysWOW64\ucrtbase.dll20 ModLoad: 75fb0000 75fd5000   C:\Windows\SysWOW64\IMM32.DLL21 ModLoad: 760d0000 76350000C:\Windows\SysWOW64\combase.dll22 (ef0.18fc): Unknown exception - code 04242420(first chance)23 ModLoad: 72340000 7374e000   C:\Windows\assembly\NativeImages_v4.0.30319_32\mscorlib\218db16dceaef380c6daf35c6a48f313\mscorlib.ni.dll24 ModLoad: 75890000 75973000C:\Windows\SysWOW64\ole32.dll25 ModLoad: 760d0000 76350000C:\Windows\SysWOW64\combase.dll26 ModLoad: 764f0000 7654c000   C:\Windows\SysWOW64\bcryptPrimitives.dll27 ModLoad: 71c00000 71c8a000   C:\Windows\Microsoft.NET\Framework\v4.0.30319\clrjit.dll28 ModLoad: 770d0000 7716b000   C:\Windows\SysWOW64\OLEAUT32.dll29 (ef0.18fc): Break instruction exception - code 80000003(first chance)30 eax=00f3f358 ebx=00000000 ecx=01045e60 edx=00f3f530 esi=02f524d4 edi=00f3f39c31 eip=75e0f262 esp=00f3f2f0 ebp=00f3f37c iopl=0nv up ei pl zr na pe nc32 cs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00000246
33 KERNELBASE!wil::details::DebugBreak+0x2:34 75e0f262 cc              int     3

这个断点,还没有到我们的Beep方法,到了【Debugger.Break();】这行代码,然后,我们继续【g】。

1 0:000>g2 Breakpoint 0hit3 eax=776c0660 ebx=00f3f460 ecx=74813ac3 edx=00000000 esi=01045e60 edi=00f3f3d04 eip=776c0660 esp=00f3f340 ebp=00f3f3a4 iopl=0nv up ei pl zr na pe nc5 cs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00000246
6 KERNEL32!BeepImplementation:7 776c0660 8bff            mov     edi,edi

红色标注的就是我们想要断住的方法。到了这里,我们看看当前的调用栈,使用【!clrstack】命令。

1 0:000> !clrstack2 OS Thread Id: 0x18fc (0)3 Child SP       IP Call Site4 00f3f350 776c0660 [InlinedCallFrame: 00f3f350]5 00f3f34c 02db092d DomainBoundILStubClass.IL_STUB_PInvoke(UInt32, UInt32)6 00f3f350 02db087a [InlinedCallFrame: 00f3f350] Example_16_1_1.Program.Beep(UInt32, UInt32)7 00f3f3ac 02db087a Example_16_1_1.Program.Main(System.String[]) [E:\Visual Studio 2022\...\Example_16_1_1\Program.cs @ 23]8 00f3f530 7474f036 [GCFrame: 00f3f530] 

InlinedCallFrame: 00f3f350
这样有一个地址,就是一个栈针,这个栈针就是 CLR 里面的部分,这个栈针地址就会调用 LoadLibrary方法,加载【Kernel32.dll】,如果加载了这个dll,就不需要在加载了,如果没有加载才加载。加载了 dll 找到 Beep 方法的方发表,调用执行就可以了。

我们可以使用【dp】命令查看一下这个指针。我执行了两次,大家不用这样执行。选择自己喜欢的。

1 0:000>dp 00f3f3502 00f3f350  7474fd74 00f3f530 0000000800f3f3443 00f3f360  02db092d 00f3f3a4 02d24d58 01045e604 00f3f370  00f3f310 00f3f3d0 776c0660 ffffffff5 00f3f380  747ff800 000003e8 000003e8 00000000
6 00f3f390  000003e8 000003e8 00f3f460 00000000
7 00f3f3a0  00f3f3d0 00f3f3b8 02db087a 00000000
8 00f3f3b0  0000000002f524c8 00f3f3c4 7474f0369 00f3f3c0  01045e60 00f3f418 747522da 00f3f46010 0:000>dp 00f3f350 L111 00f3f350  7474fd74

然后,我们在使用【ln 7474fd74】命令,查看具体详情。

1 0:000>ln 7474fd742 Browse module3 Set bu breakpoint4 
5 (7474fd74)   clr!InlinedCallFrame::`vftable'|  (7474fdc0)   clr!HelperMethodFrame_1OBJ::`vftable'
6 Exact matches:

当然,我们也可以使用【u】命令,查看 clr!InlinedCallFrame 方法的源码。当然,这个源码是汇编源码。

1 0:000>u 7474fd742 clr!InlinedCallFrame::`vftable':
3 7474fd74 30a1757490ba    xor     byte ptr [ecx-456F8B8Bh],ah4 7474fd7a 7574            jne     clr!HelperMethodFrame_1OBJ::`vftable'+0x30 (7474fdf0)
5 7474fd7c b019            mov     al,19h6 7474fd7e 7574            jne     clr!HelperMethodFrame_1OBJ::`vftable'+0x34 (7474fdf4)
7 7474fd80 1061a0          adc     byte ptr [ecx-60h],ah8 7474fd83 7460            je      clr!HelperMethodFrame_1OBJ::`vftable'+0x25 (7474fde5)
9 7474fd85 f9              stc10 7474fd86 7f74            jg      clr!HelperMethodFrame_1OBJ::`vftable'+0x3c (7474fdfc)


2.2、调用协定造成的崩溃。
调试源码:Example_16_1_2 和 Example_16_1_3(C++)
我们【Example_16_1_2】项目的 Program 类声明了一个Alloc方法,是C++ 的。这个方法的调用协定就是【CallingConvention = CallingConvention.Cdecl、CallingConvention.StdCall、CallingConvention.ThisCall】这个3中协定都是正常执行的,
说明一下:和视频中使用【CallingConvention.ThisCall】协定程序会崩溃是不一致的,本人亲测
,传递字符的规格是【CharSet = CharSet.Unicode】,也就是双字节。
我们的C++项目【Example_16_1_3】的【Example_16_1_3.cpp】类就定义了 Alloc 方法。我们为了传递和接受双字节的字符,在C++ 里面需要使用【wchar_t】类型,这个函数导出的时候格式是以【extern "C"】C语言的格式为标准的。
到现在,我们可以直接运行【Example_16_1_2】项目的 exe 程序,(说明:调用协定是CallingConvention.Cdecl,才可以调用成功,CallingConvention.ThisCall是举例调用协定不一致出现问题,大家要熟悉),我们看看运行结果,效果如图:

现在,我们把调用协定修改为【CallingConvention.FastCall】,在我测测试中,这些调用协定【CallingConvention.StdCall、CallingConvention.ThisCall、CallingConvention.Cdecl、CallingConvention.Winapi】都是正常执行的,所以,我只能换【CallingConvention.FastCall】,通过 Windbg 调试器查看一些运行结果。
当把我们的项目加载到 Windebug 调试中直接运行,会抛出异常,和视频中抛出的【访问违例:Access violation】异常是不一样的。

1 0:000>g2 ModLoad: 00007ffd`15bf0000 00007ffd`15c9a000   C:\Windows\System32\ADVAPI32.dll3 ModLoad: 00007ffd`166f0000 00007ffd`1678e000   C:\Windows\System32\msvcrt.dll4 ModLoad: 00007ffd`168c0000 00007ffd`1695b000   C:\Windows\System32\sechost.dll5 ModLoad: 00007ffd`17550000 00007ffd`17673000C:\Windows\System32\RPCRT4.dll6 ModLoad: 00007ffc`fd320000 00007ffc`fd3ca000   C:\Windows\Microsoft.NET\Framework64\v4.0.30319\mscoreei.dll7 ModLoad: 00007ffd`1696000000007ffd`169b5000   C:\Windows\System32\SHLWAPI.dll8 ModLoad: 00007ffd`152c0000 00007ffd`152d3000   C:\Windows\System32\kernel.appcore.dll9 ModLoad: 00007ffd`14c80000 00007ffd`14c8a000   C:\Windows\SYSTEM32\VERSION.dll10 ModLoad: 00007ffc`fbfa0000 00007ffc`fca62000   C:\Windows\Microsoft.NET\Framework64\v4.0.30319\clr.dll11 ModLoad: 00007ffd`1732000000007ffd`174c0000   C:\Windows\System32\USER32.dll12 ModLoad: 00007ffd`15240000 00007ffd`15262000C:\Windows\System32\win32u.dll13 ModLoad: 00007ffc`fba00000 00007ffc`fbabd000   C:\Windows\SYSTEM32\ucrtbase_clr0400.dll14 ModLoad: 00007ffc`fcd00000 00007ffc`fcd16000   C:\Windows\SYSTEM32\VCRUNTIME140_CLR0400.dll15 ModLoad: 00007ffd`15bb0000 00007ffd`15bda000   C:\Windows\System32\GDI32.dll16 ModLoad: 00007ffd`153b0000 00007ffd`154ba000   C:\Windows\System32\gdi32full.dll17 ModLoad: 00007ffd`1531000000007ffd`153ad000   C:\Windows\System32\msvcp_win.dll18 ModLoad: 00007ffd`154c0000 00007ffd`155c0000   C:\Windows\System32\ucrtbase.dll19 ModLoad: 00007ffd`16650000 00007ffd`16680000C:\Windows\System32\IMM32.DLL20 ModLoad: 00007ffd`1797000000007ffd`17cc4000   C:\Windows\System32\combase.dll21 (3cf8.225c): Unknown exception - code 04242420(first chance)22 ModLoad: 00007ffc`f3650000 00007ffc`f4c50000   C:\Windows\assembly\NativeImages_v4.0.30319_64\mscorlib\....\mscorlib.ni.dll23 ModLoad: 00007ffd`1679000000007ffd`168b9000   C:\Windows\System32\ole32.dll24 ModLoad: 00007ffd`1797000000007ffd`17cc4000   C:\Windows\System32\combase.dll25 ModLoad: 00007ffd`15b30000 00007ffd`15baf000   C:\Windows\System32\bcryptPrimitives.dll26 ModLoad: 00007ffc`f2c50000 00007ffc`f2d9f000   C:\Windows\Microsoft.NET\Framework64\v4.0.30319\clrjit.dll27 (3cf8.225c): C++ EH exception -code e06d7363 (first chance)28 ModLoad: 0000017d`c7a10000 0000017d`c7b0a000   image0000017d`c7a1000029 ModLoad: 0000017d`c7b10000 0000017d`c7c0a000   image0000017d`c7b1000030 (3cf8.225c): CLR exception -code e0434352 (first chance)31 ModLoad: 00007ffc`a83f0000 00007ffc`a855a000   C:\Windows\Microsoft.NET\Framework64\v4.0.30319\diasymreader.dll32 ModLoad: 00007ffc`f1fe0000 00007ffc`f2c50000   C:\Windows\assembly\NativeImages_v4.0.30319_64\System\...\System.ni.dll33 ModLoad: 00007ffc`f14b0000 00007ffc`f1f25000   C:\Windows\assembly\NativeImages_v4.0.30319_64\System.Core\...\System.Core.ni.dll34 ModLoad: 00007ffd`14a40000 00007ffd`14a58000   C:\Windows\SYSTEM32\CRYPTSP.dll35 ModLoad: 00007ffd`141e0000 00007ffd`14214000C:\Windows\system32\rsaenh.dll36 ModLoad: 00007ffd`152e0000 00007ffd`15307000C:\Windows\System32\bcrypt.dll37 ModLoad: 00007ffd`14a60000 00007ffd`14a6c000   C:\Windows\SYSTEM32\CRYPTBASE.dll38 (3cf8.225c): CLR exception - code e0434352 (!!! second chance !!!)39 KERNELBASE!RaiseException+0x69:40 00007ffd`156d3e49 0f1f440000      nop     dword ptr [rax+rax]

当然,我们直接运行程序,抛出的异常会更加直接。效果如图:

所以说,我们可以直接看程序抛出的异常,更能说明直接的问题,使用 Windebug 有点多此一举。再次强调一下:我的结果和视频的结果是不一样的,原因未知。

当然,虽然出错了,我们也可以看看当前的调用栈。

1 0:000> !clrstack2 OS Thread Id: 0x225c (0)3 Child SP               IP Call Site4 00000034903fe910 00007ffd156d3e49 [PrestubMethodFrame: 00000034903fe910] Example_16_1_2.Program.Alloc(System.String)5 00000034903febd0 00007ffc9ca708d1 Example_16_1_2.Program.Main(System.String[]) [E:\Visual Studio 2022\...\Example_16_1_2\Program.cs @ 17]6 00000034903fedf8 00007ffcfbfa6913 [GCFrame: 00000034903fedf8]7 
8 0:000>dp 00000034903fe910 l19 00000034`903fe910  00007ffc`fc7711c010 0:000>ln 00007ffc`fc7711c011 Browse module12 Set bu breakpoint13 
14 (00007ffc`fc7711c0)   clr!PrestubMethodFrame::`vftable'|  (00007ffc`fc771260)   clr!ExternalMethodFrame::`vftable'
15 Exact matches:16 
17 0:000>u 00007ffc`fc7711c018 clr!PrestubMethodFrame::`vftable':
19 00007ffc`fc7711c0 70b6            jo      clr!FaultingExceptionFrame::`vftable'+0x50 (00007ffc`fc771178)
20 00007ffc`fc7711c2 0ffcfc          paddb   mm7,mm421 00007ffc`fc7711c5 7f00            jg      clr!PrestubMethodFrame::`vftable'+0x7 (00007ffc`fc7711c7)
22 00007ffc`fc7711c7 004007          add     byte ptr [rax+7],al23 00007ffc`fc7711ca fb              sti24 00007ffc`fc7711cb fb              sti25 00007ffc`fc7711cc fc              cld26 00007ffc`fc7711cd 7f00            jg      clr!PrestubMethodFrame::`vftable'+0xf (00007ffc`fc7711cf)


2.3、委托异步引发的崩溃。
调试源码:Example_16_1_4 和 Example_16_1_5(C++)
我们编译我们的两个项目,直接 ctrol+f5 运行 Example_16_1_4 项目,我们先看运行正常的情况,如果项正常运行,这个行代码【GC.Collect();】需要注释掉。运行结果如图:

这是正常的情况,接下来,我们取消对【GC.Collect();】这行代码的注释,就是可以执行垃圾回收。我们重新编译项目,ctrol+f5运行项目,执行效果如图:

在这里,我需要说明一下,我的演示结果和【一线码农】的视频演示的结果是不一样的,他的系统也崩溃了,提示的错误消息是【未经处理的异常:System.AccessviolationException:尝试读取或者写入受保护的内存,这通常指示其他内存已损坏】。这个问题我还没搞清楚,如果有知道的可以告诉我。

上面是运行程序出现的问题,接下来,我们使用 Windbg 查找一下问题。
我们编译项目 Example_16_1_4,打开 Windbg,点击【文件】----》【launch executable】附加程序,打开调试器的界面,程序已经处于中断状态。我本来想使用【
bp Example_16_1_4!AsyncProcess
】命令给【
AsyncProcess
】方法下断点,但是执行不成功。

1 0:000> bp Example_16_1_4!AsyncProcess2 Couldn't resolve error at'Example_16_1_4!AsyncProcess'

那我们就通过源码的方式直接给 C++ AsyncProcess 方法下断点。我们点击 Windbg 菜单栏,依次选择【Source】--->【Open Source File】,打开选择我们的 C++ 项目中的 Example_16_1_5.cpp 文件。效果如图:

断点设置完成后,我们直接执行【g】命令,继续运行调试器。效果如图:

我们继续执行【dv】命令,可以看到有一个 ptr,那就是我们从托管代码中传递到非托管代码中的委托,就是一个指针。

1 0:000>dv2             ptr = 0x000001cc`459a090c3         hThread = 0x00007ff8`5aa40f58

我们可以使用【
u 1cc459a090c
】命令,查看一下这个 ptr 是什么。

1 0:000>u 1cc459a090c2 000001cc`459a090c 49bae0089a45cc010000 mov r10,1CC459A08E0h3 000001cc`459a0916 48b8c021275af87f0000 mov rax,offset clr!UMThunkStub (00007ff8`5a2721c0)4 000001cc`459a0920 48ffe0          jmp     rax5 000001cc`459a0923 0000            add     byteptr [rax],al6 000001cc`459a0925 0000            add     byteptr [rax],al7 000001cc`459a0927 00ababababab    add     byte ptr [rbx-54545455h],ch8 000001cc`459a092d ab              stos    dword ptr [rdi]9 000001cc`459a092e ab              stos    dword ptr [rdi]

我们在【PCallback callback = (PCallback)lpParameter;】这行代码在下一个断点,也就是2秒后会执行这个回调。效果如图:

断点设置成功后,我们继续执行调试器,使用【g】命令。

1 0:000>g2 Breakpoint 1hit3 Example_16_1_5!ThreadWorkItem+0x3e:4 00007fff`d444172e 488b8500010000  mov     rax,qword ptr [rbp+100h] ss:0000000a`735ffb60=000001cc459a090c

我们继续执行,会在我们设置断点的地方成功断住。效果如图:

到了这里,我们在使用【
u 1cc459a090c
】命令,查看一下这个 ptr 是什么东西。

1 0:007>u 1cc459a090c2 000001cc`459a090c ee              outdx,al3 000001cc`459a090d fe              ???
4 000001cc`459a090e ee              outdx,al5 000001cc`459a090f fe              ???
6 000001cc`459a0910 ee              outdx,al7 000001cc`459a0911 fe              ???
8 000001cc`459a0912 ee              outdx,al9 000001cc`459a0913 fe              ???

都是乱码了,都是 ??? 问号了,就是说 ptr 不存在了。说明已经被我们 GC 回收了。我们也可以使用【dv】命令查看一下变化。

1 0:007>dv2     lpParameter = 0x000001cc`459a090c3        callback = 0x00000000`00000000

callback 是空值了。
如果遇到这样的情况,我们怎么解决呢?其实很简单,在我们的 C# 代码中,声明一个静态的 handle 就可以了,如:static GCHandle handle;在我的代码中,注释的部分就是解决办法。

2.4、非托管内存泄露
调试源码:Example_16_1_6 和 Example_16_1_7(C++)项目
在C++ 项目中,如果我们声明了【数组】,是需要自己释放的,如果忘记释放,内存就会暴涨了。我们直接运行项目【Example_16_1_6】,看一下效果:

大家可以试试,内存涨得很快。
这次我们是通过 dump 文件进行分析的,生成 dump 文件有两种方式,第一种是通过【任务管理器】来生成的。第二种是通过【ProcessExplorer】工具来生成。

第一种:
我们首先运行我们的项目 Example_16_1_6.exe,然后,我们打开【任务管理器】,找到我们的项目进程,我的进程名是【Example_16_1_6】,如果左侧有箭头,点击打开折叠的内容,在项目地址名字上点击右键,选择保存【创建转出文件】,保存成功,会弹出提示框文件的位置,效果如下:

弹出保存数据对话框,保存对话框运行时间的长短是有你保存的数据多少决定的。如图:

这个保存的过程,和你的程序运行时间的长短有关系。保存成功,如图:

我们的 dump 文件如图:

第二种:
我们使用【ProcessExplorer】工具抓 dump 文件,个人感觉这个更好的,抓的文件更好用、更可靠。
首先运行我们的项目 Example_16_1_6.exe,然后打开【ProcessExplorer】工具,然后,在右侧的【Filter by name】过滤进程,输入我们的进程名称,比如:Example_16,不用输入全名,当然输入全名也可以。如图:

我们找到了我们的项目进程,在项目上点击右键,依次选择【Create Dump】----》【Create MiniDump】或者【Create Full Dump】,我选择的是【Create Full Dump】创建完整的 dump 文件,选择保存的文件路径就可以了。
在开始之前,我们需要做一些准备工作,否则,调试结果有些数据是看不到的,我第一次就是这样的,原来是漏了步骤了,切记,切记。我们必须打开【栈追踪】。我已经安装了 【Windows Kits】,如果没有安装的,就请去微软官网下载安装一下,毕竟 gflags.exe 包含在这个集合中。
Windows Kits 官网下载地址:
https://learn.microsoft.com/zh-cn/windows-hardware/drivers/download-the-wdk

我的安装目录在:D:\Windows Kits\10\Debuggers ,大家根据自己的情况去查找。为了避免每次都进入安装目录,最好把 gflags.exe 的安装目录配置到【环境变量】里面,使用就方便了。针对我们的项目执行一下命令:gflags /i Example_16_1_6.exe +ust 。效果如图:


有了  Dump 文件就容易了,我们就可以使用 Windbg 调试了。我们打开 Windbg,点击【文件】----》【Open dump file】打开我们的 Dump 文件,打开调试器的界面,程序已经处于中断状态。我们先看看托管堆的情况,执行命令【!heap -s】。

1 0:000> !heap -s2 
3 
4 ************************************************************************************************************************
5 NT HEAP STATS BELOW6 ************************************************************************************************************************
7 NtGlobalFlag enables following debugging aids for newheaps:8 stack back traces(必须开启栈跟踪,否则后面的操作有些不能输出)9 LFH Key                   : 0xb1c3e0529717db20
10 Termination on corruption : ENABLED11 Heap     Flags   Reserv  Commit  Virt   Free  List   UCR  Virt  Lock  Fast12 (k)     (k)    (k)     (k) length      blocks cont. heap13 -------------------------------------------------------------------------------------
14 000001f3651e0000 08000002 3869212 3843092 3869108  58051   283   243    1      3LFH15 000001f363950000 08008000      64      4     64      2     1     1    0      0      
16 000001f3655b0000 08001002     164     36     60      5     2     1    0      0LFH17 000001f365420000 08001002     164     36     60      4     2     1    0      0LFH18 000001f366df0000 08001002      60      8     60      2     1     1    0      0      
19 000001f366f70000 08041002      60      8     60      5     1     1    0      0      
20 000001f37f8b0000 08041002      60      8     60      2     1     1    0      0      
21 -------------------------------------------------------------------------------------

我们使用【
!heap -h 000001f3651e0000
】命令查看一下句柄,发现内容太多了,我就不一一展示了。

1 0:000> !heap -h 000001f3651e00002 HEAPEXT: Unable to get address of ntdll!RtlpHeapInvalidBadAddress.3 Index   Address  Name      Debugging options enabled4   1:   1f3651e00005 Segment at 000001f3651e0000 to 000001f3652df000 (000ff000 bytes committed)6 Segment at 000001f37f300000 to 000001f37f3ff000 (000e7000 bytes committed)7 Segment at 000001f37f8c0000 to 000001f37fabf000 (001d6000 bytes committed)8 Segment at 000001f37fac0000 to 000001f37febf000 (003ee000 bytes committed)9 Segment at 000001f300000000 to 000001f3007ff000 (007db000 bytes committed)10 Segment at 000001f300800000 to 000001f3017cf000 (00fb5000 bytes committed)11 Segment at 000001f3017d0000 to 000001f30279f000 (00fb5000 bytes committed)12 Segment at 000001f3027a0000 to 000001f30376f000 (00fb5000 bytes committed)13 Segment at 000001f303770000 to 000001f30473f000 (00fb5000 bytes committed)14 Segment at 000001f304740000 to 000001f30570f000 (00fb5000 bytes committed)15 Segment at 000001f305710000 to 000001f3066df000 (00fb5000 bytes committed)16 Segment at 000001f3066e0000 to 000001f3076af000 (00fb5000 bytes committed)17 Segment at 000001f3076b0000 to 000001f30867f000 (00fb5000 bytes committed)18 Segment at 000001f308680000 to 000001f30964f000 (00fb5000 bytes committed)19 Segment at 000001f309650000 to 000001f30a61f000 (00fb5000 bytes committed)20 Segment at 000001f30a620000 to 000001f30b5ef000 (00fb5000 bytes committed)21 Segment at 000001f30b5f0000 to 000001f30c5bf000 (00fb5000 bytes committed)22 Segment at 000001f30c5c0000 to 000001f30d58f000 (00fb5000 bytes committed)23 Segment at 000001f30d590000 to 000001f30e55f000 (00fb5000 bytes committed)24 Segment at 000001f30e560000 to 000001f30f52f000 (00fb5000 bytes committed)25 Segment at 000001f30f530000 to 000001f3104ff000 (00fb5000 bytes committed)26 Segment at 000001f310500000 to 000001f3114cf000 (00fb5000 bytes committed)27 Segment at 000001f3114d0000 to 000001f31249f000 (00fb5000 bytes committed)28 Segment at 000001f3124a0000 to 000001f31346f000 (00fb5000 bytes committed)29 Segment at 000001f313470000 to 000001f31443f000 (00fb5000 bytes committed)30 Segment at 000001f314440000 to 000001f31540f000 (00fb5000 bytes committed)31 Segment at 000001f315410000 to 000001f3163df000 (00fb5000 bytes committed)32 Segment at 000001f3163e0000 to 000001f3173af000 (00fb5000 bytes committed)33 Segment at 000001f3173b0000 to 000001f31837f000 (00fb5000 bytes committed)34 Segment at 000001f318380000 to 000001f31934f000 (00fb5000 bytes committed)35 Segment at 000001f319350000 to 000001f31a31f000 (00fb5000 bytes committed)36 Segment at 000001f31a320000 to 000001f31b2ef000 (00fb5000 bytes committed)37 Segment at 000001f31b2f0000 to 000001f31c2bf000 (00fb5000 bytes committed)38 Segment at 000001f31c2c0000 to 000001f31d28f000 (00fb5000 bytes committed)39 Segment at 000001f31d290000 to 000001f31e25f000 (00fb5000 bytes committed)40 Segment at 000001f31e260000 to 000001f31f22f000 (00fb5000 bytes committed)41 Segment at 000001f31f230000 to 000001f3201ff000 (00fb5000 bytes committed)42 Segment at 000001f320200000 to 000001f3211cf000 (00fb5000 bytes committed)43 Segment at 000001f3211d0000 to 000001f32219f000 (00fb5000 bytes committed)44 Segment at 000001f3221a0000 to 000001f32316f000 (00fb5000 bytes committed)45 Segment at 000001f323170000 to 000001f32413f000 (00fb5000 bytes committed)46 Segment at 000001f324140000 to 000001f32510f000 (00fb5000 bytes committed)47 Segment at 000001f325110000 to 000001f3260df000 (00fb5000 bytes committed)48 Segment at 000001f3260e0000 to 000001f3270af000 (00fb5000 bytes committed)49 Segment at 000001f3270b0000 to 000001f32807f000 (00fb5000 bytes committed)50 Segment at 000001f328080000 to 000001f32904f000 (00fb5000 bytes committed)51 Segment at 000001f329050000 to 000001f32a01f000 (00fb5000 bytes committed)52 Segment at 000001f32a020000 to 000001f32afef000 (00fb5000 bytes committed)53 Segment at 000001f32aff0000 to 000001f32bfbf000 (00fb5000 bytes committed)54 Segment at 000001f32bfc0000 to 000001f32cf8f000 (00fb5000 bytes committed)55 Segment at 000001f32cf90000 to 000001f32df5f000 (00fb5000 bytes committed)56 Segment at 000001f32df60000 to 000001f32ef2f000 (00fb5000 bytes committed)57 Segment at 000001f32ef30000 to 000001f32feff000 (00fb5000 bytes committed)58 Segment at 000001f32ff00000 to 000001f330ecf000 (00fb5000 bytes committed)59 Segment at 000001f330ed0000 to 000001f331e9f000 (00fb5000 bytes committed)60 Segment at 000001f331ea0000 to 000001f332e6f000 (00fb5000 bytes committed)61 Segment at 000001f332e70000 to 000001f333e3f000 (00fb5000 bytes committed)62 Segment at 000001f333e40000 to 000001f334e0f000 (00fb5000 bytes committed)63 Segment at 000001f334e10000 to 000001f335ddf000 (00fb5000 bytes committed)64 Segment at 000001f335de0000 to 000001f336daf000 (00fb5000 bytes committed)65 Segment at 000001f336db0000 to 000001f337d7f000 (00fb5000 bytes committed)66 Segment at 000001f337d80000 to 000001f338d4f000 (00fb5000 bytes committed)67 Segment at 000001f338d50000 to 000001f339d1f000 (00fb5000 bytes committed)68 Segment at 000001f339d20000 to 000001f33acef000 (00fb5000 bytes committed)69 Segment at 000001f33acf0000 to 000001f33bcbf000 (00fb5000 bytes committed)70 Segment at 000001f33bcc0000 to 000001f33cc8f000 (00fb5000 bytes committed)71 Segment at 000001f33cc90000 to 000001f33dc5f000 (00fb5000 bytes committed)72 Segment at 000001f33dc60000 to 000001f33ec2f000 (00fb5000 bytes committed)73 Segment at 000001f33ec30000 to 000001f33fbff000 (00fb5000 bytes committed)74 Segment at 000001f33fc00000 to 000001f340bcf000 (00fb5000 bytes committed)75 Segment at 000001f340bd0000 to 000001f341b9f000 (00fb5000 bytes committed)76 Segment at 000001f341ba0000 to 000001f342b6f000 (00fb5000 bytes committed)77 Segment at 000001f342b70000 to 000001f343b3f000 (00fb5000 bytes committed)78 Segment at 000001f343b40000 to 000001f344b0f000 (00fb5000 bytes committed)79 Segment at 000001f344b10000 to 000001f345adf000 (00fb5000 bytes committed)80 Segment at 000001f345ae0000 to 000001f346aaf000 (00fb5000 bytes committed)81 Segment at 000001f346ab0000 to 000001f347a7f000 (00fb5000 bytes committed)82 Segment at 000001f347a80000 to 000001f348a4f000 (00fb5000 bytes committed)83 Segment at 000001f348a50000 to 000001f349a1f000 (00fb5000 bytes committed)84 Segment at 000001f349a20000 to 000001f34a9ef000 (00fb5000 bytes committed)85 Segment at 000001f34a9f0000 to 000001f34b9bf000 (00fb5000 bytes committed)86 Segment at 000001f34b9c0000 to 000001f34c98f000 (00fb5000 bytes committed)87 Segment at 000001f34c990000 to 000001f34d95f000 (00fb5000 bytes committed)88 Segment at 000001f34d960000 to 000001f34e92f000 (00fb5000 bytes committed)89 Segment at 000001f34e930000 to 000001f34f8ff000 (00fb5000 bytes committed)90 Segment at 000001f34f900000 to 000001f3508cf000 (00fb5000 bytes committed)91 Segment at 000001f3508d0000 to 000001f35189f000 (00fb5000 bytes committed)92 Segment at 000001f3518a0000 to 000001f35286f000 (00fb5000 bytes committed)93 Segment at 000001f352870000 to 000001f35383f000 (00fb5000 bytes committed)94 Segment at 000001f353840000 to 000001f35480f000 (00fb5000 bytes committed)95 Segment at 000001f354810000 to 000001f3557df000 (00fb5000 bytes committed)96 Segment at 000001f3557e0000 to 000001f3567af000 (00fb5000 bytes committed)97 Segment at 000001f3567b0000 to 000001f35777f000 (00fb5000 bytes committed)98 Segment at 000001f357780000 to 000001f35874f000 (00fb5000 bytes committed)99 Segment at 000001f358750000 to 000001f35971f000 (00fb5000 bytes committed)100 Segment at 000001f359720000 to 000001f35a6ef000 (00fb5000 bytes committed)101 Segment at 000001f35a6f0000 to 000001f35b6bf000 (00fb5000 bytes committed)102 Segment at 000001f35b6c0000 to 000001f35c68f000 (00fb5000 bytes committed)103 Segment at 000001f35c690000 to 000001f35d65f000 (00fb5000 bytes committed)104 Segment at 000001f35d660000 to 000001f35e62f000 (00fb5000 bytes committed)105 Segment at 000001f35e630000 to 000001f35f5ff000 (00fb5000 bytes committed)106 Segment at 000001f35f600000 to 000001f3605cf000 (00fb5000 bytes committed)107 Segment at 000001f3605d0000 to 000001f36159f000 (00fb5000 bytes committed)108 Segment at 000001f3615a0000 to 000001f36256f000 (00fb5000 bytes committed)109 Segment at 000001f362570000 to 000001f36353f000 (00fb5000 bytes committed)110 Segment at 000001f37fec0000 to 000001f380e8f000 (00fb5000 bytes committed)666666 Segment at 000001f380e90000 to 000001f381e5f000 (00fb5000 bytes committed)112 Segment at 000001f381e60000 to 000001f382e2f000 (00fb5000 bytes committed)113 Segment at 000001f382e30000 to 000001f383dff000 (00fb5000 bytes committed)114 Segment at 000001f383e00000 to 000001f384dcf000 (00fb5000 bytes committed)115 Segment at 000001f384dd0000 to 000001f385d9f000 (00fb5000 bytes committed)116 Segment at 000001f385da0000 to 000001f386d6f000 (00fb5000 bytes committed)117 Segment at 000001f386d70000 to 000001f387d3f000 (00fb5000 bytes committed)118 Segment at 000001f387d40000 to 000001f388d0f000 (00fb5000 bytes committed)119 Segment at 000001f388d10000 to 000001f389cdf000 (00fb5000 bytes committed)120 Segment at 000001f389ce0000 to 000001f38acaf000 (00fb5000 bytes committed)121 Segment at 000001f38acb0000 to 000001f38bc7f000 (00fb5000 bytes committed)122 Segment at 000001f38bc80000 to 000001f38cc4f000 (00fb5000 bytes committed)123 Segment at 000001f38cc50000 to 000001f38dc1f000 (00fb5000 bytes committed)124 Segment at 000001f38dc20000 to 000001f38ebef000 (00fb5000 bytes committed)125 Segment at 000001f38ebf0000 to 000001f38fbbf000 (00fb5000 bytes committed)126 Segment at 000001f38fbc0000 to 000001f390b8f000 (00fb5000 bytes committed)127 Segment at 000001f390b90000 to 000001f391b5f000 (00fb5000 bytes committed)128 Segment at 000001f391b60000 to 000001f392b2f000 (00fb5000 bytes committed)129 Segment at 000001f392b30000 to 000001f393aff000 (00fb5000 bytes committed)130 Segment at 000001f393b00000 to 000001f394acf000 (00fb5000 bytes committed)131 Segment at 000001f394ad0000 to 000001f395a9f000 (00fb5000 bytes committed)132 Segment at 000001f395aa0000 to 000001f396a6f000 (00fb5000 bytes committed)133 Segment at 000001f396a70000 to 000001f397a3f000 (00fb5000 bytes committed)134 Segment at 000001f397a40000 to 000001f398a0f000 (00fb5000 bytes committed)135 Segment at 000001f398a10000 to 000001f3999df000 (00fb5000 bytes committed)136 Segment at 000001f3999e0000 to 000001f39a9af000 (00fb5000 bytes committed)137 Segment at 000001f39a9b0000 to 000001f39b97f000 (00fb5000 bytes committed)138 Segment at 000001f39b980000 to 000001f39c94f000 (00fb5000 bytes committed)139 Segment at 000001f39c950000 to 000001f39d91f000 (00fb5000 bytes committed)140 Segment at 000001f39d920000 to 000001f39e8ef000 (00fb5000 bytes committed)141 Segment at 000001f39e8f0000 to 000001f39f8bf000 (00fb5000 bytes committed)142 Segment at 000001f39f8c0000 to 000001f3a088f000 (00fb5000 bytes committed)143 Segment at 000001f3a0890000 to 000001f3a185f000 (00fb5000 bytes committed)144 Segment at 000001f3a1860000 to 000001f3a282f000 (00fb5000 bytes committed)145 Segment at 000001f3a2830000 to 000001f3a37ff000 (00fb5000 bytes committed)146 Segment at 000001f3a3800000 to 000001f3a47cf000 (00fb5000 bytes committed)147 Segment at 000001f3a47d0000 to 000001f3a579f000 (00fb5000 bytes committed)148 Segment at 000001f3a57a0000 to 000001f3a676f000 (00fb5000 bytes committed)149 Segment at 000001f3a6770000 to 000001f3a773f000 (00fb5000 bytes committed)150 Segment at 000001f3a7740000 to 000001f3a870f000 (00fb5000 bytes committed)151 Segment at 000001f3a8710000 to 000001f3a96df000 (00fb5000 bytes committed)152 Segment at 000001f3a96e0000 to 000001f3aa6af000 (00fb5000 bytes committed)153 Segment at 000001f3aa6b0000 to 000001f3ab67f000 (00fb5000 bytes committed)154 Segment at 000001f3ab680000 to 000001f3ac64f000 (00fb5000 bytes committed)155 Segment at 000001f3ac650000 to 000001f3ad61f000 (00fb5000 bytes committed)156 Segment at 000001f3ad620000 to 000001f3ae5ef000 (00fb5000 bytes committed)157 Segment at 000001f3ae5f0000 to 000001f3af5bf000 (00fb5000 bytes committed)158 Segment at 000001f3af5c0000 to 000001f3b058f000 (00fb5000 bytes committed)159 Segment at 000001f3b0590000 to 000001f3b155f000 (00fb5000 bytes committed)160 Segment at 000001f3b1560000 to 000001f3b252f000 (00fb5000 bytes committed)161 Segment at 000001f3b2530000 to 000001f3b34ff000 (00fb5000 bytes committed)162 Segment at 000001f3b3500000 to 000001f3b44cf000 (00fb5000 bytes committed)163 Segment at 000001f3b44d0000 to 000001f3b549f000 (00fb5000 bytes committed)164 Segment at 000001f3b54a0000 to 000001f3b646f000 (00fb5000 bytes committed)165 Segment at 000001f3b6470000 to 000001f3b743f000 (00fb5000 bytes committed)166 Segment at 000001f3b7440000 to 000001f3b840f000 (00fb5000 bytes committed)167 Segment at 000001f3b8410000 to 000001f3b93df000 (00fb5000 bytes committed)168 Segment at 000001f3b93e0000 to 000001f3ba3af000 (00fb5000 bytes committed)169 Segment at 000001f3ba3b0000 to 000001f3bb37f000 (00fb5000 bytes committed)170 Segment at 000001f3bb380000 to 000001f3bc34f000 (00fb5000 bytes committed)171 Segment at 000001f3bc350000 to 000001f3bd31f000 (00fb5000 bytes committed)172 Segment at 000001f3bd320000 to 000001f3be2ef000 (00fb5000 bytes committed)173 Segment at 000001f3be2f0000 to 000001f3bf2bf000 (00fb5000 bytes committed)174 Segment at 000001f3bf2c0000 to 000001f3c028f000 (00fb5000 bytes committed)175 Segment at 000001f3c0290000 to 000001f3c125f000 (00fb5000 bytes committed)176 Segment at 000001f3c1260000 to 000001f3c222f000 (00fb5000 bytes committed)177 Segment at 000001f3c2230000 to 000001f3c31ff000 (00fb5000 bytes committed)178 Segment at 000001f3c3200000 to 000001f3c41cf000 (00fb5000 bytes committed)179 Segment at 000001f3c41d0000 to 000001f3c519f000 (00fb5000 bytes committed)180 Segment at 000001f3c51a0000 to 000001f3c616f000 (00fb5000 bytes committed)181 Segment at 000001f3c6170000 to 000001f3c713f000 (00fb5000 bytes committed)182 Segment at 000001f3c7140000 to 000001f3c810f000 (00fb5000 bytes committed)183 Segment at 000001f3c8110000 to 000001f3c90df000 (00fb5000 bytes committed)184 Segment at 000001f3c90e0000 to 000001f3ca0af000 (00fb5000 bytes committed)185 Segment at 000001f3ca0b0000 to 000001f3cb07f000 (00fb5000 bytes committed)186 Segment at 000001f3cb080000 to 000001f3cc04f000 (00fb5000 bytes committed)187 Segment at 000001f3cc050000 to 000001f3cd01f000 (00fb5000 bytes committed)188 Segment at 000001f3cd020000 to 000001f3cdfef000 (00fb5000 bytes committed)189 Segment at 000001f3cdff0000 to 000001f3cefbf000 (00fb5000 bytes committed)190 Segment at 000001f3cefc0000 to 000001f3cff8f000 (00fb5000 bytes committed)191 Segment at 000001f3cff90000 to 000001f3d0f5f000 (00fb5000 bytes committed)192 Segment at 000001f3d0f60000 to 000001f3d1f2f000 (00fb5000 bytes committed)193 Segment at 000001f3d1f30000 to 000001f3d2eff000 (00fb5000 bytes committed)194 Segment at 000001f3d2f00000 to 000001f3d3ecf000 (00fb5000 bytes committed)195 Segment at 000001f3d3ed0000 to 000001f3d4e9f000 (00fb5000 bytes committed)196 Segment at 000001f3d4ea0000 to 000001f3d5e6f000 (00fb5000 bytes committed)197 Segment at 000001f3d5e70000 to 000001f3d6e3f000 (00fb5000 bytes committed)198 Segment at 000001f3d6e40000 to 000001f3d7e0f000 (00fb5000 bytes committed)199 Segment at 000001f3d7e10000 to 000001f3d8ddf000 (00fb5000 bytes committed)200 Segment at 000001f3d8de0000 to 000001f3d9daf000 (00fb5000 bytes committed)201 Segment at 000001f3d9db0000 to 000001f3dad7f000 (00fb5000 bytes committed)202 Segment at 000001f3dad80000 to 000001f3dbd4f000 (00fb5000 bytes committed)203 Segment at 000001f3dbd50000 to 000001f3dcd1f000 (00fb5000 bytes committed)204 Segment at 000001f3dcd20000 to 000001f3ddcef000 (00fb5000 bytes committed)205 Segment at 000001f3ddcf0000 to 000001f3decbf000 (00fb5000 bytes committed)206 Segment at 000001f3decc0000 to 000001f3dfc8f000 (00fb5000 bytes committed)207 Segment at 000001f3dfc90000 to 000001f3e0c5f000 (00fb5000 bytes committed)208 Segment at 000001f3e0c60000 to 000001f3e1c2f000 (00fb5000 bytes committed)209 Segment at 000001f3e1c30000 to 000001f3e2bff000 (00fb5000 bytes committed)210 Segment at 000001f3e2c00000 to 000001f3e3bcf000 (00fb5000 bytes committed)211 Segment at 000001f3e3bd0000 to 000001f3e4b9f000 (00fb5000 bytes committed)212 Segment at 000001f3e4ba0000 to 000001f3e5b6f000 (00fb5000 bytes committed)213 Segment at 000001f3e5b70000 to 000001f3e6b3f000 (00fb5000 bytes committed)214 Segment at 000001f3e6b40000 to 000001f3e7b0f000 (00fb5000 bytes committed)215 Segment at 000001f3e7b10000 to 000001f3e8adf000 (00fb5000 bytes committed)216 Segment at 000001f3e8ae0000 to 000001f3e9aaf000 (00fb5000 bytes committed)217 Segment at 000001f3e9ab0000 to 000001f3eaa7f000 (00fb5000 bytes committed)218 Segment at 000001f3eaa80000 to 000001f3eba4f000 (00fb5000 bytes committed)219 Segment at 000001f3eba50000 to 000001f3eca1f000 (00fb5000 bytes committed)220 Segment at 000001f3eca20000 to 000001f3ed9ef000 (00fb5000 bytes committed)221 Segment at 000001f3ed9f0000 to 000001f3ee9bf000 (00fb5000 bytes committed)222 Segment at 000001f3ee9c0000 to 000001f3ef98f000 (00fb5000 bytes committed)223 Segment at 000001f3ef990000 to 000001f3f095f000 (00fb5000 bytes committed)224 Segment at 000001f3f0960000 to 000001f3f192f000 (00fb5000 bytes committed)225 Segment at 000001f3f1930000 to 000001f3f28ff000 (00fb5000 bytes committed)226 Segment at 000001f3f2900000 to 000001f3f38cf000 (00fb5000 bytes committed)227 Segment at 000001f3f38d0000 to 000001f3f489f000 (00fb5000 bytes committed)228 Segment at 000001f3f48a0000 to 000001f3f586f000 (00fb5000 bytes committed)229 Segment at 000001f3f5870000 to 000001f3f683f000 (00fb5000 bytes committed)230 Segment at 000001f3f6840000 to 000001f3f780f000 (00fb5000 bytes committed)231 Segment at 000001f3f7810000 to 000001f3f87df000 (00fb5000 bytes committed)232 Segment at 000001f3f87e0000 to 000001f3f97af000 (00fb5000 bytes committed)233 Segment at 000001f3f97b0000 to 000001f3fa77f000 (00fb5000 bytes committed)234 Segment at 000001f3fa780000 to 000001f3fb74f000 (00fb5000 bytes committed)235 Segment at 000001f3fb750000 to 000001f3fc71f000 (00fb5000 bytes committed)236 Segment at 000001f3fc720000 to 000001f3fd6ef000 (00fb5000 bytes committed)237 Segment at 000001f3fd6f0000 to 000001f3fe6bf000 (00fb5000 bytes committed)238 Segment at 000001f3fe6c0000 to 000001f3ff68f000 (00fb5000 bytes committed)239 Segment at 000001f3ff690000 to 000001f40065f000 (00fb5000 bytes committed)240 Segment at 000001f400660000 to 000001f40162f000 (00fb5000 bytes committed)241 Segment at 000001f401630000 to 000001f4025ff000 (00fb5000 bytes committed)242 Segment at 000001f402600000 to 000001f4035cf000 (00fb5000 bytes committed)243 Segment at 000001f4035d0000 to 000001f40459f000 (00fb5000 bytes committed)244 Segment at 000001f4045a0000 to 000001f40556f000 (00fb5000 bytes committed)245 Segment at 000001f405570000 to 000001f40653f000 (00fb5000 bytes committed)246 Segment at 000001f406540000 to 000001f40750f000 (00fb5000 bytes committed)247 Segment at 000001f407510000 to 000001f4084df000 (00eec000 bytes committed)248     Flags:                08000002
249     ForceFlags:           00000000
250     Granularity:          16bytes251 Segment Reserve:      ec360000252     Segment Commit:       00002000
253     DeCommit Block Thres: 00000400
254     DeCommit Total Thres: 00001000
255 Total Free Size:      0038b0df256 Max. Allocation Size: 00007ffffffdefff257 Lock Variable at:     000001f3651e02c0258     Next TagIndex:        0000
259     Maximum TagIndex:     0000
260     Tag Entries:          00000000
261     PsuedoTag Entries:    00000000
262 Virtual Alloc List:   1f3651e0110263         000001f366e09000: 00100000 [commited 101000, unused 1000] -busy (b)264 Uncommitted ranges:   1f3651e00f0265     FreeList[ 00 ] at 000001f3651e0150: 000001f301778010 . 000001f37f33fe80   (283blocks)266 
267     Heap entries for Segment00 inHeap 000001f3651e0000268 address: psize . size  flags   state (requested size)269         000001f3651e0000: 00000 . 00740 [101] -busy (73f)270         000001f3651e0740: 00740 . 00080 [101] - busy (50)271         000001f3651e07c0: 00080 . 00060 [101] - busy (30)272         000001f3651e0820: 00060 . 00030 [101] - busy (4)273         000001f3651e0850: 00030 . 00130 [101] - busy (100)274         000001f3651e0980: 00130 . 00200 [101] -busy (1d8)275         000001f3651e0b80: 00200 . 00200 [101] -busy (1d8)276         000001f3651e0d80: 00200 . 00070 [101] - busy (48)277         000001f3651e0df0: 00070 . 00030 [101] - busy (4)278         000001f3651e0e20: 00030 . 00040 [101] - busy (10)279         000001f3651e0e60: 00040 . 00130 [101] - busy (100)280         000001f3651e0f90: 00130 . 00130 [101] - busy (100)281         000001f3651e10c0: 00130 . 01510 [101] -busy (14e8)282         000001f3651e25d0: 01510 . 00950 [101] -busy (91c)283         000001f3651e2f20: 00950 . 00070 [101] -busy (3c)284         000001f3651e2f90: 00070 . 00060 [101] - busy (30)285         000001f3651e2ff0: 00060 . 00090 [101] - busy (62)286         000001f3651e3080: 00090 . 00150 [101] - busy (120)287         000001f3651e31d0: 00150 . 00080 [101] - busy (50)288         000001f3651e3250: 00080 . 00150 [101] - busy (120)289         000001f3651e33a0: 00150 . 00080 [101] - busy (50)290         000001f3651e3420: 00080 . 00260 [101] - busy (238)291         000001f3651e3680: 00260 . 00060 [101] - busy (30)292         000001f3651e36e0: 00060 . 00090 [101] - busy (68)293         000001f3651e3770: 00090 . 00040 [101] - busy (10)294         000001f3651e37b0: 00040 . 00150 [101] - busy (120)295         000001f3651e3900: 00150 . 00080 [101] - busy (50)296         000001f3651e3980: 00080 . 00070 [101] - busy (40)297         000001f3651e39f0: 00070 . 00030 [101] - busy (8)298         000001f3651e3a20: 00030 . 00050 [101] - busy (20)299         000001f3651e3a70: 00050 . 00080 [101] - busy (50)300         000001f3651e3af0: 00080 . 00090 [101] - busy (68)301         000001f3651e3b80: 00090 . 00150 [101] - busy (120)302         000001f3651e3cd0: 00150 . 00080 [101] - busy (50)303         000001f3651e3d50: 00080 . 00070 [101] - busy (42)304         000001f3651e3dc0: 00070 . 00130 [101] - busy (100)305         000001f3651e3ef0: 00130 . 00130 [101] - busy (100)306         000001f3651e4020: 00130 . 00060 [101] - busy (30)307         000001f3651e4080: 00060 . 00070 [101] - busy (30)308         000001f3651e40f0: 00070 . 00050 [101] - busy (20)309         000001f3651e4140: 00050 . 00070 [101] - busy (42)310         000001f3651e41b0: 00070 . 000a0 [101] - busy (75)311         000001f3651e4250: 000a0 . 00150 [101] - busy (120)312         000001f3651e43a0: 00150 . 00080 [101] - busy (50)313         000001f3651e4420: 00080 . 00070 [101] - busy (46)314         000001f3651e4490: 00070 . 00430 [101] - busy (400)315         000001f3651e48c0: 00430 . 00430 [101] - busy (400)316         000001f3651e4cf0: 00430 . 00130 [101] - busy (100)317         000001f3651e4e20: 00130 . 00130 [101] - busy (100)318         000001f3651e4f50: 00130 . 00060 [101] - busy (30)319         000001f3651e4fb0: 00060 . 00060 [101] - busy (30)320         000001f3651e5010: 00060 . 00060 [101] - busy (30)321         000001f3651e5070: 00060 . 00060 [101] - busy (30)322         000001f3651e50d0: 00060 . 00060 [101] - busy (30)323         000001f3651e5130: 00060 . 00060 [101] - busy (30)324         000001f3651e5190: 00060 . 00060 [101] - busy (30)325         000001f3651e51f0: 00060 . 00060 [101] - busy (30)326         000001f3651e5250: 00060 . 00060 [101] - busy (30)327         000001f3651e52b0: 00060 . 00060 [101] - busy (30)328         000001f3651e5310: 00060 . 00060 [101] - busy (30)329         000001f3651e5370: 00060 . 00060 [101] - busy (30)330         000001f3651e53d0: 00060 . 00060 [101] - busy (30)331         000001f3651e5430: 00060 . 00810 [101] -busy (80f) Internal332         000001f3651e5c40: 00810 . 01cb0 [101] -busy (1caf) Internal333         000001f3651e78f0: 01cb0 . 00130 [101] - busy (108)334         000001f3651e7a20: 00130 . 000b0 [101] - busy (88)335         000001f3651e7ad0: 000b0 . 00830 [101] - busy (800) Internal336         000001f3651e8300: 00830 . 00420 [101] -busy (3f0) Internal337         000001f3651e8720: 00420 . 00050 [101] - busy (20)338         000001f3651e8770: 00050 . 00120 [101] -busy (f0)339         000001f3651e8890: 00120 . 00050 [101] -busy (1a)340         000001f3651e88e0: 00050 . 00200 [101] -busy (1d8)341         000001f3651e8ae0: 00200 . 00070 [101] - busy (48)342         000001f3651e8b50: 00070 . 00120 [101] - busy (f0)


我们继续执行【
!heap -x 0000022b076de000
】看看,

1         0000022b0769c010: 42010 . 41ff0 [101] -busy (41fe0) Internal2         0000022b076de000: 41ff0 . 00400 [101] -busy (3f0) Internal (我选的这个地址3         0000022b076de400: 00400 . 41c00 [101] -busy (41bf0) Internal4         0000022b07720000: 41c00 . 10fc0 [100]5         0000022b07730fc0: 10fc0 . 00040 [666666] -busy (3d)6         0000022b07731000:      00b9e000      -uncommitted bytes.7 0:000> !heap -x 0000022b076de000(这个地址我是随便选的8 Entry             User              Heap              Segment               Size  PrevSize  Unused    Flags9 -------------------------------------------------------------------------------------------------------------
10 0000022b076de000  0000022b076de010  0000022a779a0000  0000022b07300000       400     41ff0        10  busy  internal

说明,这里必须使用【gflags】注册跟踪数据库,否则这里是没有输出的,第一次,可把我搞蒙了。

我测试到这里,没有测试到我需要的结果,不知道原因为什么,和【一线码农】视频有差距。当我执行【!heap -x】 命令,没有得到我想要的结果,所以后面执行【!heap -p -a】命令就没有办法执行了。

四、总结
终于写完了,这个系列也终于写完了,我说的这个系列是基于视频的这个系列,因为我打算基于《Net 高级调试》这个本书,再出一个系列。底层的东西,一次肯定是理解不透的,需要深入、多次的操作和调试。学习过程真的没那么轻松,还好是自己比较喜欢这一行,否则真不知道自己能不能坚持下来。
准备收拾心情,重新在写一个系列,完全是基于书本的,把每个章节都写出来,调试一下,感受一下,肯定收货更多
。好了,不说了,不忘初心,继续努力,希望老天不要辜负努力的人。

1. Kubernetes的普及和重要性

随着云计算的迅速发展,容器化技术已成为构建和运行分布式应用程序的关键。而Kubernetes作为容器编排领域的佼佼者,已经成为了云原生应用的标准。它不仅简化了应用程序的部署和管理,而且为开发者和运维人员提供了一套全面的工具集,从容器编排、自动扩缩容、服务发现到自修复等,满足了各种复杂的生产需求。无论你是开发人员、运维人员还是企业决策者,理解Kubernetes的重要性并掌握其技术,都将为项目和业务带来巨大的竞争优势。

2. Kubernetes的挑战

Kubernetes创建、更新、删除资源等操作,均是使用json或yaml文件进行管理,更新和删除可以依赖之前的文件进行更改,但是创建具有多变性,往往编辑起来比较复杂,容易出错。而且K8s的配置项实在太多,稍微不注意就会犯错。要写好一个yaml文件,你需要了解yaml的语法,需要掌握K8s的各种配置,对于一个k8s的初学者而言,这将是一件很难的事情。所以Kubernetes YAML文件的编写与维护是一项繁琐且容易出错的工作。

每个应用程序、服务或配置都需要精确的YAML语法,一旦出错,可能会导致资源无法正常创建或运行。此外,随着应用程序的复杂性和规模的增长,所需的YAML文件数量和复杂度也会急剧的增加。如果单靠人力去对文件做增删改查,这不仅增加了出错的可能性,而且管理和维护变得异常的困难。因此,使用一些自动化工具来生成和管理Kubernetes YAML文件成为了迫切的需求,它不仅可以大大提高工作效率,而且可以减少出错的可能性,让管理Kubernetes工作变得更加轻松和高效。

3. Kubernetes YAML文件图形化生成

当我们面临Kubernetes YAML文件编写的困难时,一个自动化的Kubernetes YAML生成工具的出现,就如同云原生时代的一场及时雨。它不仅解放了我们的双手,更提高了工作效率,减少了出错的可能性。

这个工具,就像一位贴心的助手,能够快速、准确地生成我们所需的YAML文件。不论是简单的部署还是复杂的微服务架构,它都能游刃有余地处理。

所以,为什么需要一个自动化的Kubernetes YAML生成工具?答案很简单,为了更高效的工作,更少的错误,以及更多的时间去做真正重要的事情。让我们告别手写Kubernetes YAML的时代,迈向运维效率提升500%的新篇章!

4.Kubernetes YAML在线生成工具KRM

今天给大家介绍一款可以无需安装就可以生成K8s yaml文件的工具————
KRM

KRM是一个Kubernetes多集群资源管理平台,基于管理Kubernetes的资源开发,可以管理Kubernetes的Namespace、Deployment、DaemonSet、StatefulSet、Service、Ingress、Pods、Nodes、CronJob等,当然也可以无需安装生成自己想要的yaml文件。

KRM主要实现的是使用图形化界面管理所有的Kubernetes的资源,降低Kubernetes的复杂度。 同时具备了一些常用的功能,比如跨集群资源复制、一键项目迁移、图形化资源编辑、资源一键回滚及更新、多集群资源统计等。

KRM在线演示地址:
http://demo.kubeasy.com/#/
登录后即可查看到KRM的首页————集群资源统计,可以所有集群的资源统计,比如节点总数量、Pod总数量等
image.png

5. KRM功能介绍

5.1 集群管理

image.png
在集群管理页面可以看到被KRM管理的集群列表、集群版本、集群状态及集群配置等,当点击集群ID时,可以查看当前集群资源统计信息,比如当前集群节点总数量、Pod总数量、Namespace总数量等
image.png

5.2 节点管理

image.png
节点管理页面可以看到每个集群的节点列表,并且可以展示每个节点的信息,比如主机名、IP地址、角色、节点状态等,同时可以对节点进行一键式操作,比如开启禁止调度和驱逐节点上的Pod等,另外点击操作的编辑可以对节点的标签和污点进行管理,点击操作的Pod按钮,可以查看当前节点运行了哪些Pod
image.png
当点击节点的主机名时,可以看到节点的详细信息
image.png

5.3 命名空间管理

image.png
命名空间管理可以查看每个集群的Namespace的列表,同时可以对命名空间进行简单的管理,比如删除、编辑和资源复制等
点击资源复制可以把某个集群的Namespace里面的资源复制到另外一个集群
image.png
image.png

点击Namespace的名称可以获取当前namespace的资源统计信息,比如Pod数量、Deployment数量等
image.png

5.4 调度资源管理

在调度资源管理页面可以管理Kubernetes常见的调度资源,比如Pod、Deployment、StatefulSet、DaemonSet、CronJob等
image.png
image.png
image.png

5.5 服务发布资源管理

服务发布管理页面可以管理集群中的Service和Ingress资源
image.png
image.png
image.png

5.6 配置管理和存储管理

配置管理和存储管理页面可以管理ConfigMap、Secret、PV、PVC等
image.png
image.png
更多功能可以打开体验网站进行体验:
http://demo.kubeasy.com/#/

6.使用KRM图形化生成YAML文件

KRM不仅可以直接生成YAML文件,还可以自行安装进行集群的管理,安装文档:
https://github.com/dotbalo/krm/blob/main/deploy.md

如果不安装也可以使用
http://demo.kubeasy.com/
在线生成YAML文件

如果想要生产Deployment的YAML文件,可以点击调度资源-Deployment-创建
image.png
快速生成只需要输入Deployment名称及容器的镜像地址点击YAML即可生成YAML文件
image.png
image.png
image.png
之后生成的YAML文件即可去使用。
如果想要更加详细的配置,可以自行添加配置

6.1 存储配置

image.png
image.png
在存储配置中,可以添加一些常用的存储资源,比如EmptyDir、NFS、ConfigMap、Secret、PVC等

6.2 容器配置

image.png
容器配置中可以添加或者删除Pod中的容器,同时可以对容器的端口、健康检查、环境变量、生命周期及存储挂载配置等
image.png
image.png
image.png
image.png
image.png

7. 总结

KRM不仅可以在线生成YAML,还可以安装到自己的集群里面去管理自己的K8s集群,免去手动处理YAML的难度,不仅可以提升管理效率,还可以降低出错率,大家可以自行尝试~

更多功能正在不断完善中,大家可以关注:
https://github.com/dotbalo/krm/
如果大家想要深度学习云原生、K8s、容器、DevOps、服务网格、Go、Vue知识可以关注:
https://edu.51cto.com/lecturer/11062970.html