访客统计Inject:Vercount替代Busuanzi
这周发现进入网站,刷新状态竟然持续了一分多钟,以为是新做完的Music页的特效显示太花里胡哨拖垮了加载,打开后台查看pending情况发现原来是不蒜子资源请求失败了,触发了一分钟的超时。
不蒜子那么多年来作为访客统计的利器,在近年缺点也渐渐显露,尤其是在网络方面,例如不能统计科学上网环境访问、高频的502失败等,而恰巧本站访客基本来自谷歌收录(某度、某狗引擎实在过度拉跨,在本站上线的三个月就被谷歌收录,对比向某度主动推送url后一个月后才收录,某度起大早赶晚集的行事作风的确声名在外,也籍着这个机会,不得不作出一些新尝试了。
查阅了一些博客,恰好有一个名为vercount比较新的项目对标不蒜子,而且兼容相同的span标签、支持全球CDN、ip访客计数实测比不蒜子还要精确,唯一不足的是这是个为爱发电的公益项目,可能不知道未来哪天就挂了。因此记录下这篇文章,希望更多的博客自建者考虑使用vercount替代busuanzi。
其目前支持span标签或者React框架:
项目地址:https://github.com/EvanNotFound/vercount
官方地址:https ...
读书笔记:Effective Modern C++
在读了大半本Effective
C++时,受益于其中许多代码规则,虽说不能让coding能力突飞猛进,至少你会开始对代码安全性有所思考,对任何开始接触C++具体项目的人,这都是一本首推的书。但对2025年的今天来说,仍然使用boost库的智能指针举例的00年代的书还是略显落后。庆幸的是,同作者Scott
Meyers也意识到这个问题,在10年前出版了包含C++ 11/14特性的《Effetive
Modern C++》,虽然C++
17/20甚至26已经开始进入快车道,但对大多数场景C++11和14的影响绝不能称为老旧。
译文项目来自EffectiveModernCpp_CN,持续更新。
第一章 类型推导
条款01:理解模板类型推导
决定读Effective Modern
C++的另外一个原因也来自条款一,大半年前我看了几篇模板编程和类型萃取的资料,写下了一篇文章:C++
Generic
Programming:SFINAF与类型萃取,其中有不少当时也不敢肯定的结论,完全是通过一些零碎的demo总结出来的,但竟然在这本书的第一章的第一节得到印证,缘分也好,伏笔也罢 ...
深入理解计算机系统CMU-15213 CSAPP(四):AttackLab
很多人经过BombLab后对汇编有一丁点暂时性阴影,从而看到其他博客的AttackLab汇编分析有点望而却步,但其实AttackLab并不涉及太大规模的汇编理解,只要对函数栈帧有一些理解,前面的题还是容易理解和解决的。
x86-64函数栈、调用与返回
x86-64函数栈的栈帧分布应该类似: 12345678910111213141516高地址(栈底)+----------------------------+ | 参数N(从右到左) | ← push 时先推入最后一个参数| ... || 参数2 || 参数1 |+----------------------------+| 返回地址(由 call 指令压栈) | ← call func 把返回地址放在这里 +----------------------------+| 上一帧的 %rbp(调用者的) | ← 被 push %ebp 保存+------ ...
深入理解计算机系统CMU-15213 CSAPP(三):BombLab暨GDB调试
拆弹实验是csapp中比较巧妙的一个实验设计之一,在这个实验中我们会阅读一系列Linux64代码和掌握软件调试的基本工具gdb以及方法,以达成实验目的,总而言之在这个实验中,你的两方面能力会得到基本的培养:
阅读x64_86汇编代码的能力,了解代码意图是解题的前提;
使用gdb的能力,帮助验证你的猜想和获取信息;
在进入BombLab前我们会记录一些必须的x86_64汇编基础和gdb指令基础。
x86_64 Linux寄存器
x86_64架构是比较常用的64位Linux系统指令集,大部分Linux系统的x86_64架构遵循System
V ABI规范,其提供了16个64位的通用寄存器,其用处如下:
rax:函数返回值;
rdi、rsi、rdx、rcx、r8、r9:一般用作六个函数参数寄存器,对应1-6个参数,若有更多的参数会保存于函数栈中;
rsp、rbp:栈指针(指向栈顶)和栈帧基址指针,栈是从高地址向低地址延申;
其余通用寄存器:r10-r15、rbx(常作基址),用作临时变量存储等;
其中rbx、rbp及r12-r15共六个寄存器是Calle ...
SQLite数据库基础与C++方法
SQLite是最常用的一种轻量级的数据库,占用资源极低,广泛用于嵌入式设备的数据存储,本文介绍了SQLite的编译安装和C++接口基本方法。
环境安装
以MinGW gcc编译为例:在SQLite官网下载合并版本的sqlite源码(如sqlite-amalgamation-3510000.zip),或者直接点击此处下载和解压。
编译C系动态库: 1gcc -shared -O2 -DSQLITE_ENABLE_FTS4 -DSQLITE_ENABLE_JSON1 sqlite3.c -o sqlite3.dll
编译sqlite数据库命令行工具: 1gcc sqlite3.c shell.c -o sqlite3 -ldl -lpthread
基于可执行的sqlite3可以运行cmd环境执行sql命令:
通过.exit和.quit命令退出该环境。
数据类型
SQLite大致支持五种存储类型,分别是:
存储类型
特点
NULL
NULL值存储
INTEGER
带符号整数,根据大小分1、2、3、4、6或8字节 ...
深入理解计算机系统CMU-15213 CSAPP(二):DataLab
在国庆假期最后一天拾起一下一年前没做完的事情,尝试继续完成CSAPP的Lab,同时每个lab中都会结合原书补充一些细节知识。
实验目的
DataLab主要围绕数据表示设计,涉及到数据的按位运算和浮点数转化等知识,设计者希望我们修改bits.c文件中的函数,使得函数实现相应的目的。此外,每个函数会限制要用的运算符和数量,根据要求完成即可。当完成此节,你会对位运算刮目相看。尤其推荐通过其中的浮点数实验和本文描述了解浮点数存储细节,我相信这是没有之一的最详细和科学的描述。如有不当,欢迎指正。
具体实现
与和非实现异或
根据异或的卡诺图,可知:A^B = (A & ~B) | (~A & B)
而根据与或关系的转换:C | D = ~(~C & ~D)
所以有:A^B = ~(~(A & ~B) & \~(~A & B))
故有: 1234567891011//1/* * bitXor - x^y using only ~ and & * Example: bitXor(4, 5) = 1 * Legal op ...
OpenGL C++记录(二):基本渲染与着色器
根据LearnOpenGL记录了OpenGL的基本入门,初衷只是想接触一些计算机图形学内容,该系列估计最多只会到坐标变换一节,完整学习可移步原教程。
基本程序
OpenGL的入门打印不再是Hello
World了,其牵扯到比较多的概念,完整的一个基本程序如下,做了很多事情,但是效果上仅仅输出一个空白灰绿框以及打印了OpenGL版本信息。
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374#include<glad/glad.h>#include<GLFW/glfw3.h> #include<iostream> // settingsconst unsigned int SCR_WIDTH = 800;const unsigned int SCR_HEIGHT = 600; const unsigned int VIEW ...
OpenGL C++记录(一):基于MinGw的环境搭建
OpenGL环境搭建
OpenGL(Open Graphics
Library)是一个2D、3D图形渲染库,它实际上并不是一种API,而是一种标准规范,规定了每个接口应该提供什么样的功能,也就是说它不关心内部实际实现,因为不同平台、不同设备上的接口实现总是不一样的,不同的系统、显卡、显卡驱动,都要求按照不同的系统API实现开发所需的对象创建和管理、音视频处理等,对编程者要求较高,因此OpenGL引入了各种库,例如GLUT,SDL,SFML和GLFW等,用于抽象和屏蔽底层的实现差异,实现使用统一的接口调用不同平台API的方法。
也由于OpenGL实现随平台变化的特点,显卡、驱动版本、系统版本都可能导致一些函数失效,或者通过宏支持新的函数功能,因此大多数函数的运行地址是运行期才真正确定,导致OpenGL的函数逻辑需要经过寻找函数指针-绑定对象-创建/操作对象的过程,例如在windows上,需要通过wglGetProcAddress获取函数指针再使用:
1234567// 定义函数原型typedef void (*GL_GENBUFFERS) (GLsizei, GLuint*);/ ...
设计模式(四):组合模式、责任链模式、策略模式
组合模式(Composite Pattern)
当集体对象和单一对象有功能上的相似时,使用组合模式可以为集体和单一对象提供统一的操作接口,例如文件系统,对文件夹和文件的操作,删除文件夹实际上是对文件夹中的文件进行删除;这种情况下使用组合模式有若干优点:
提供统一的操作,减少代码量;
树形的管理架构,除了文件系统,很多系统的组织与此类似,例如公司、军队等组织的管理系统;
易于扩展(开闭原则,对扩展开放,对修改封闭),一是能够容下多个层级关系,而无需每层独立一个类管理;二是添加层级和操作对象,都只要增加非叶子层级或者叶子、非叶子的操作接口即可。
组织模式将类结构组织成树形的架构,单一的对象称为叶子对象,由单一对象组成的集体对象称为组件或者容器,单一对象之下没有对象,组件对象之下可以是更细分的组件对象,也可以是某单一对象,其中抽象类定义了叶子对象和组件的类似特性,将组织架构中最大的组件定义为根,模拟一个组件模式的军队架构组织如下:
12345678910111213141516171819202122232425262728293031323334353637383940 ...
矩阵求导
函数与变元(自变量)
标量函数f
标量函数的自变量可以是标量、向量和矩阵。常见的函数形式以标量形式给出:
但仅使用标量方程不足以方便描述各种数学关系,所以拓展成向量和矩阵方程的形式:
向量形式:假设(列向量),由二次型分解知
矩阵形式:假设,有:
向量函数
向量函数的自变量同样可以分成标量、向量和矩阵。
标量作自变量:
向量作自变量:
矩阵作自变量:
矩阵函数F
矩阵函数的自变量同样可以分成标量、向量和矩阵。
标量自变量:
向量自变量:
矩阵自变量:
分子布局与分母布局
向量、矩阵这种多维变量互相求导,元素的个数实际上是确定的,关键是如何进行元素排列,主要是讨论分子布局和分母布局。
总结了几个结论:
分母和分子布局的本质就是由谁的维度来决定行数。分母布局下,假如分母是m维向量,那么结果就是m行,假如分母是m×n矩阵,那么结果就是mn行,分子布局同理;
标量函数求导,使用的是分母布局(分母可能是向量、矩阵,维度较高);
向量、矩阵函数对标量求导,使用的是分子布局(分子为向量、矩阵,维度较高);
向量对向量求导,没有断论 ...

