Electron项目yarn安装依赖

yarn 淘宝镜像

1
2
3
4
yarn config set registry https://registry.npm.taobao.org

yarn config get registry
https://registry.npm.taobao.org

Electron 淘宝镜像

1
export ELECTRON_MIRROR="https://cdn.npm.taobao.org/dist/electron/"

官方文档传送门

GitHub Actions 搞定Hexo自动部署

第一次尝试 GitHub Actions,很赞👍

  • 语法简单,上手容易,但又足够强大,感觉可以干任何事情
  • 复用性强,很容易通过use复用,市场里有很多常用action
  • 配额给的足够

官方文档传送门

[当前仓库部署用的workflow]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
name: Deploy

on:
[push] # 触发事件

jobs:
build:
runs-on: ubuntu-latest # 运行环境为最新版 Ubuntu
name: A job to deploy blog.
steps:
- name: Checkout # 获取源码
uses: actions/checkout@v1 # 使用官方常用action
with: # 条件
submodules: true

- name: copyCfg # 更新配置
run: cp _config.theme.yml themes/icarus/_config.yml

# Caching dependencies to speed up workflows. (GitHub will remove any cache entries that have not been accessed in over 7 days.)
- name: Cache node modules
uses: actions/cache@v1
id: cache
with:
path: node_modules
key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
restore-keys: |
${{ runner.os }}-node-
- name: Install Dependencies
if: steps.cache.outputs.cache-hit != 'true' # 如果没有cache
run: npm install # 安装 node modules 相关依赖

# 发布
- name: Deploy
id: deploy
uses: sma11black/hexo-action@v1.0.0 # 使用 社区贡献的action
with:
deploy_key: ${{ secrets.DEPLOY_KEY }}
user_name: xuewuli
user_email: 26448247@qq.com

一段应急的C++对象检查代码

一个JNI项目,偶发离奇崩溃,怀疑是野指针类的问题。开address sanitizer本地难复现,测试版开as太卡,大部分测试机还是6、7的系统。

还好大部分都对象都派生自引用计数的基类,于是按fail-fast的思路憋出了以下代码,在加减引用怀疑区域手动插桩检查。

附上代码,无关部分做了简化

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
#include <type_traits>
#include <stdio.h>
#include <assert.h>

#define LOG(...) do { fprintf(stderr, __VA_ARGS__); fflush(stderr); } while (false)

class Object
{
public:
Object()
: _falgs(0xcafecafe)
{
}
virtual ~Object()
{
_falgs = 0xdeaddead;
}
// is not strict but help avoid most of error
bool isValid() const
{
return static_cast<const void *>(this) && (_falgs == 0xcafecafe);
}

private:
int _falgs;
};

class ObjectCheck
{
public:
template <typename T>
static bool Check(T obj)
{
return doCheck<T>(obj);
}

template <typename T>
static bool CheckNullable(T obj)
{
return obj == nullptr || doCheck<T>(obj);
}

private:
template <typename T>
static bool doCheck(typename std::enable_if<std::is_base_of<Object, typename std::remove_pointer<T>::type>::value && !std::is_void<typename std::remove_pointer<T>::type>::value, T>::type obj)
{
LOG("dynamic_cast && isValid %p %p ", dynamic_cast<T>(reinterpret_cast<Object*>(obj)), obj);
return (obj == dynamic_cast<T>(reinterpret_cast<Object*>(obj)) && obj->isValid());
}

template <typename T>
static bool doCheck(typename std::enable_if<!std::is_base_of<Object, typename std::remove_pointer<T>::type>::value && std::is_polymorphic<typename std::remove_pointer<T>::type>::value, T>::type obj)
{
LOG("dynamic_cast %p %p ", dynamic_cast<T>(obj), obj);
return (obj == dynamic_cast<T>(obj));
}

template <typename T>
static bool doCheck(typename std::enable_if<std::is_void<typename std::remove_pointer<T>::type>::value, T>::type obj)
{
LOG("static_cast void* ");
return (obj == static_cast<void *>(obj));
}
};

class Dummy
{
public:
virtual ~Dummy() = default;
int dummy;
};
class SubObject : public Object
{
public:
int dummy;
};

int main()
{
void *t1 = nullptr;
Object *t2 = nullptr;
Dummy *t3 = nullptr;
SubObject *t4 = nullptr;
Object *t5 = new Object();
Dummy *t6 = new Dummy();
SubObject *t7 = new SubObject();
SubObject *t8 = reinterpret_cast<SubObject *>(t6);
SubObject *t9 = reinterpret_cast<SubObject *>(t5);
SubObject *t10 = new SubObject();
delete t10;

LOG("result %d \n", ObjectCheck::CheckNullable(t1));
LOG("result %d \n", ObjectCheck::CheckNullable(t2));
LOG("result %d \n", ObjectCheck::CheckNullable(t3));
LOG("result %d \n", ObjectCheck::CheckNullable(t4));
LOG("result %d \n", ObjectCheck::Check(t5));
LOG("result %d \n", ObjectCheck::Check(t6));
LOG("result %d \n", ObjectCheck::Check(t7));
LOG("result %d \n", ObjectCheck::Check(t8));
LOG("result %d \n", ObjectCheck::Check(t9));
LOG("result %d \n", ObjectCheck::Check(t10));
}

输出

1
2
3
4
5
6
7
8
9
10
result 1 
result 1
result 1
result 1
dynamic_cast && isValid 0x7fca1cc02b40 0x7fca1cc02b40 result 1
dynamic_cast 0x7fca1cc02b50 0x7fca1cc02b50 result 1
dynamic_cast && isValid 0x7fca1cc02b60 0x7fca1cc02b60 result 1
dynamic_cast && isValid 0x0 0x7fca1cc02b50 result 0
dynamic_cast && isValid 0x0 0x7fca1cc02b40 result 0
[1] 30935 segmentation fault ./a.out

Android Studio 3.6.X 不能直接运行老项目的问题

今天升级了Android Studio到 3.6.2,结果项目不能直接run到手机里了,报错如下

ApkProvisionException: No outputs for the main artifact of variant: debug

降级 AS 或 升级 Gradle 成本都颇高

可以通过修改 Installation Options 临时解决
具体修改是 Deploy 设置为 Nothing 并增加一个 Before lanuch 的 gradle task
参考下图:

androidstudio

Vue+three.js

朋友要做个h5 app项目,里面需要显示3D模型,问我这个做游戏的,用什么合适,是不是得用游戏引擎。

想了想觉得 Vue|React+three.js 配合起来应该合适。

做了个demo验证一下。

Demo的GitHub仓库传送门