0%

TLS 解决什么问题

全局变量是所有线程共享的,多线程访问要么加锁,要么用原子操作。但有一类数据天生不该共享:错误码、当前用户上下文、日志缓冲区。为它们加锁纯属浪费——线程之间根本不想共享。

TLS(Thread Local Storage,线程局部存储)就是答案:同一个变量名下,每个线程持有独立副本。写法像全局变量,行为是线程私有。

最经典的例子是错误码:线程 A 调用失败设了错误码,线程 B 同时失败——如果错误码是普通全局变量,A 还没读就被 B 覆盖了。所以 errno 和 GetLastError() 的值都存在 TLS 里,每个线程读到的都是自己那次失败。

阅读全文 »

使用 MATLAB 图像处理工具箱做程序设计相对简单,本文通过几个可运行的小例子,梳理图像处理的常见技术:图像读写、颜色空间、直方图及均衡化、平滑滤波、边缘检测、二值化、降噪与形态学操作,帮助建立这方面的技能体系。原文写于 2018 年,首发于博客园,现迁移到本博客。

阅读全文 »

一个容易误读的讲法

读王端明《深入浅出 Windows API 程序设计》核心编程篇的 DLL 章,书里先讲显式加载的好处是”DLL 不存在,exe 也能跑起来”,接着讲延迟加载,又说它有”目录里没有 DLL 也能把程序运行起来”的优势。两段话放一起看容易犯迷糊:延迟加载写法上明明还是隐式的(链 .lib、直接调函数),怎么也有显式加载的好处?这是不是讲错了?

结论:书上没错,但要把两件事拆开看——写法上的链接方式和加载发生的时机。延迟加载是”写法上隐式、时机上独立”的第三种方式,不等于隐式加载。

阅读全文 »

为什么先讲这两个

最近开始读《C++并发编程实战》。前四章讲了不少东西,但真正绕不开的基础模型就两个:线程创建之后怎么收尾(join/detach),以及线程的结果怎么拿回来(future/promise)。书里的完整例子偏复杂,我把概念剥到最简,再从随书源码里挑了几个简洁的实例补上,用最小代码把这两个模型讲清楚。

阅读全文 »

这一篇解决什么问题

多继承再叠一层就会出现菱形:A、B 都继承 V,C 同时继承 A 和 B。这时 V 在 C 里有几份?怎么解决?这一篇回答:

  1. 普通继承的菱形为什么会带两份基类子对象,有什么问题?
  2. 虚继承怎么做到只留一份,代价是什么?
  3. vbptr 和 vbtable(虚基类偏移表)是怎么工作的?
阅读全文 »

这一篇解决什么问题

上一篇用几个结构体搞清楚了对象内部的布局。接下来我想弄清楚两件事:

  1. Point a(1); 和 Point* b = new Point(2); 这两种写法,对象的内存到底在哪,生命周期差在哪。
  2. 成员函数里随手就用的 this,它到底是个什么东西,从哪来的。

还是一个最小工程,打印地址看现象。

阅读全文 »

为什么从这个话题开始

最近开始系统补 C++ 对象模型,这是面试高频内容,也是后面学虚函数、继承、用调试器看内存的基础。第一步先搞清楚最基本的问题:一个对象在内存里到底长什么样。

我写了几个结构体做实验,总结下来核心就是三条规则,sizeof 计算题基本都能从这三条推出来。

阅读全文 »

为什么学 Claude Code

把 Claude Code 作为最重要的 AI Agent 工具来学习,原因有二:一是它是不同于 ChatGPT 的 Agent 模式的集大成者,二是它拥有最好的模型。

这篇笔记整理了 Claude Code 的核心用法:会话内的斜杠命令、命令行下的深度用法(参数与管道)、实用插件,以及我自己和 Agent 分工的一些体会。

阅读全文 »

工具链是分水岭

前面四篇讲的都是”代码层面的崩溃原理”。但真正到了线上环境,你需要的是一套工具链:在崩溃发生时保存现场,事后把内存地址还原成源代码位置,定位根因。

这一篇介绍 Windows C++ 崩溃治理中最实用的几条工具链:

  • WinDbg:分析 MiniDump,还原调用栈。
  • AddressSanitizer:编译期插桩,抓越界和 use-after-free。
  • gflags + Page Heap:系统级严格堆检查。
  • Application Verifier:更全面的运行时验证。
  • Crashpad / Breakpad:生产级崩溃采集与上报。
  • PDB 符号服务器:让线上 dump 能还原符号。
阅读全文 »

小问题,大后果

上一篇讲的是单线程场景下的常见崩溃。这一篇进入更”工程”的领域:多线程竞争、DLL 加载、断言、静态初始化顺序(SIOF)、跨模块内存分配。

这些问题在小项目里几乎不会出现,但在大型 C++ 工程中,它们是导致”启动就崩””客户环境崩””换编译器就崩”的典型原因。而且它们的共同特点是:崩溃点往往不是根因,真正的破坏发生在更早的某个时刻。

阅读全文 »

崩溃类型比想象中更多

上一篇讲了 Windows 的异常处理链路。这一篇进入实战层面,看看客户端程序中最常见的几类崩溃:空指针、堆破坏、栈溢出、未初始化、内存耗尽、纯虚调用。

这些崩溃的共同点是什么?它们大多在 Release 模式下更隐蔽,dump 中的崩溃点往往不是真正的破坏现场。 理解每类崩溃的根因和 Debug/Release 差异,是快速定位问题的关键。

阅读全文 »

异常处理不是只有一个入口

很多 Windows C++ 开发者对异常处理的印象停留在 try/catch 和 “程序崩溃弹错误框”。但实际上,Windows 提供了一整套分层异常处理机制,从最先被调用的 VEH,到最后兜底的 UEF,每层职责不同、适用场景也不同。

理解这条链路,是做好崩溃捕获和 dump 分析的前提。

阅读全文 »

为什么写这个系列

Windows C++ 程序的崩溃治理,是客户端开发和系统编程里绕不开的话题。一个线上 crash 通常不会乖乖在开发环境复现,它更常见的形态是:用户机器上偶发、dump 文件发回来、调用栈看起来 unrelated、本地怎么跑都没事。

这个系列源于我对 Windows C++ 崩溃治理的系统性梳理。核心目标是把零散的知识点串成一条可执行的链路:

1
异常如何被捕获 → 崩溃如何分类 → 如何预防 → 如何用工具定位 → 如何工程化上报
阅读全文 »

文档背景

一次技术沟通中,发现与我做不同项目的同行,在C++的机制和操作系统 API 上特别有心得,而这是我近两年的工作和学习中用不上,也没有深入学的内容,交流后对我有很大启发,很过瘾。

这些内容解释了很多原理,填补了我的认知空白,也间接指导了我后续的实践,非常开心有这样的交流,后面我拉了个微信群,只拉取了 C++ 开发在里面,把靠谱的 C++ 都拉进群。

阅读全文 »

1 选择要保留的文件

保留_config.yml, themes/, source/, scaffolds/,package.jsona,.gitignore 这些文件夹,其它可以删除。

阅读全文 »

1 一些教训

非必要不升级系统,导致很多经典软件不能用,最后重新安装系统解决这些问题的.

阅读全文 »

1
2
3
4
5
6
7
8
9
10
11
┌──────────────────────────────────────────────────┐
│ H.264 码流 │
├──────────────────────────────────────────────────┤
│ NAL 网络抽象层:负责适配网络传输 │
│ NALU = NAL Header + RBSP(编码数据) │
│ 传输打包交给 RTP 等协议(有专门的 RFC 文档和开源库) │
├──────────────────────────────────────────────────┤
│ VCL 视频编码层:负责视频内容的压缩表示 │
│ GOP: I 帧(帧内预测) → P 帧(前向预测) → B 帧(双向预测) │
│ 编码流程: 预测 → 变换 → 量化 → 熵编码 │
└──────────────────────────────────────────────────┘

这个图片是经过概念梳理后做的信息提取说明图,但是理清了 H.264 的内部关系,并且对 H.264 的结构和网络传输的概念予以说明,H.264 的传输说明应该关注的是 RTP 等协议,这些都有专门的 RFC 文档和对应的开源库。

  1. 单例模式的目的是确保唯一实例,确切的说是为了在应用程序的进程空间中确保唯一实例,刚刚在视频处理器的使用中被这种设计小小震撼一下:

阅读全文 »

1 引言

之前写过 vim 的教程,还写过 emacs 使用教程,自己整理了一份 emacs.d 文件,每次装机了就拿出来。

这一次是配置共享文件,这个不仅可以用于虚拟机,也可以用于 Windows 系统与远程开发机同步文件,并且方便在本地使用一些编码工具。

阅读全文 »

环境配置

库编译

从官网下载的版本是 5.1.4 ,配合《lua设计与实现》在 Linux/Windows 编译,在 Windows 上编译的过程中

阅读全文 »

引言

背景

文章记录一些开发时候遇到的问题和解决方法。

参考资料

  1. Qt Assistant(安装 Qt 时候选择安装,用于文档查询)
阅读全文 »

1 引言

1.1 写作背景

我看的设计模式资料使用 C# 和 Java 实现,这两种语言不需要处理内存泄漏问题。后续发现按照资料仿写的 C++ 代码有内存泄漏的情况,于是尝试解决这个问题,对 C++ 有新的理解,故记录之。

阅读全文 »

引言

写作目的

记录 OpenGL 学习的环境准备工作,为了下一步学习扫清障碍。

阅读全文 »

在命令行中运行程序的过程,是命令行会对程序进行复制,然后创建一个进程运行这个程序。因此,程序的内存结构所涉及的操作系统术语应该是 Linux 内存管理。

阅读全文 »

本文是对前段时间学习自然语言处理(NLP)的总结。本文先介绍自然语言处理的内容,及其基于统计学的处理方式,在这个过程,逐渐矩阵化数据,看到矩阵化即可以想到机器学习方法的引入,预见到深度学习技术广泛应用的必然性。本文结尾我提供两个自己学习过程中建立的仓库,一个是对学习内容的总结,另一个是个对话机器人。

阅读全文 »

最新:更新一些 GitHub 使用异常的故障排查

  1. 问题1: Connection reset by 20.205.243.166 port 22

​ 解决方法:C://User/ 中编辑 /.ssh/config 给文件加上以下内容后再,重启git bash。

1
2
3
Host github.com
User git
ProxyCommand connect -H 127.0.0.1:7890 %h %p

1 本地 repo

  • 设置姓名和邮箱

    git config --global user.name "xxxx"

    git config --global user.email "xxxx@yyy.zzz"

  • 创建并初始化本地空仓库

    git init <repo_name>

  • 查看提交的状态

    git status

  • 暂存区中添加更改

    git add <file_name>

  • 记录一行提交信息

    git commit -m "commit info"

  • 提交记录

    git log

  • 忽略特定格式文件格式

    touch .gitignore && vim .gitigonre

    *.out *.py

    原有创建的格式用 git rm —cached 忽略
    常用工程的 ignore文件。

  • 回滚操作

    1
    2
    git reset --hard <commit ID>   # <commit ID> 有两种,一种很长,一种截取前一种的若干字符表示
    git push -f -u origin main # 好坑,参考资料写 master
  • 解决push冲突

    假设用户1修改了 xxx文件,并且 push 了,我这边再修改后 push 会提示拒绝,有冲突,查看冲突:

    git diff master origin/master

    建议将该文件备份,然后执行以下操作(备份,先拉取再合并:

1
2
3
4
5
git pull
vim xxx PS 对其进行更改
git add xxx
git commit "my work"
git push
  • GitHub 创建本地仓库缓存,在本地构建 GitHub 云端方法

    (1) 在机器 a 上执行以下语句,可在该机建立了一个暂存区。

​ git init --bare /home/hanxinle/xdisk.git

(2)在机器 b 执行

git clone hanxinle@xx.mm.yy.zz:/home/hanxinle/xdisk.git

则将 repo 拉取到本地,在本地创建文件等更改后,在本地可执行 add,commit,push 操作。

(3)其它机器执行

git clone hanxinle@xx.mm.yy.zz:/home/hanxinle/xdisk.git

则可以在得到与机器b一致的 repo。


2 远程 repo

  • 查看分支

    git branch

  • 创建分支

    git branch <branch_name

  • 切换到分支

    git checkout <branch_name>

  • 创建并且切换

    git checkout -b <branch_name>

  • 分支合并(位于 master )

    git merge <sub_branch_name>

    同步后可以删除这个子分支

    git branch -d <sub_branch_name>

  • 分支同步

    git push origin <loacl_branch_name> (将本地分支同步到服务器)

  • 分支删除与重命名

    git brach -D/-d PS 删除 see git -h

    远端分支重命名(创建本地分支—>同步到远端—>删除远端同名分支—>原本地分支重命名—>推送到远端)

    git checkout -b <local_branch>

    git push origin <local_branch>

    git push --delete origin <local_name>

    git commit -m <local_name> <new_branch_name>

    git push origin <new_branch_name>

  • tag 管理

    网页端 release 中管理,和 commit 的哈希值相关。


3 免密操作

执行命令 ssh-keygen,一路回车,在 .ssh 文件夹中, id_rsa 为私有, id_rsa.pub 为公有,在 Github 中点击右上角自己的头像,选择 setting ,在 ssh 相关设置中,点击 NEW SSH KEY ,将 id_rsa.pub 的内容复制进来,此时 push 还是需要用户名密码,有两种方式可以免输入,一种是编辑.git/config 文件,将 url=https:xxxxx 更改,它的值在网页端打开 github repo 的时候,选择 clone or download 按钮,会有 use ssh 一项,点击这一项,复制 url 链接到.git/config 文件替换 url= 这一项.

另一种方式是在 clone 命令时,不要通过 https 命令操作,直接通过上面这个 ssh 的 url 方式操作.


4 fork 后用 upstream 同步原始 repo 最新情况

  • 首先 git clone 到本地

  • 查看远端分支

    git remote -v

  • 添加upstream分支

    git remote add upstream git@xxxx.git

  • 将upstream版本拉到本地

    git fetch upstream

  • 再合并upstream master

    git merge upstream/master

  • 最后push到远端

    git push origin master


5 其它 repo 选项

  • Issue

    bug提交

  • Projects

    项目进度管理

  • Wiki

    项目的介绍,可以制作网页,补充其它必要的文档,背景

  • Gist

    代码\文档的片段

引言

文章背景

对于Windows程序设计抓住主线进行总结,包括 Win32 和少量MFC和Qt的内容。

参考资料

阅读全文 »