善意提醒

如果您打开本站很慢,布局排版混乱,并且看不到图片,那么可能是因为您还没有掌握用科学的方法上网的本领。

2025-08-28

编程随想:密码粘贴的安全问题

图片由Google Gemini生成

就「密码输入控件是否应该允许粘贴功能」这件事情,跟同事发生了一点小的争执。

其实也没多大事。
同事觉得,既然要「安全」,那就彻底拿掉「粘贴」功能,不让进也不让出。
而我觉得,不能把控件内的文本复制出去,那是常识。但外面的文本能不能粘贴进来?这个问题还可以商量商量。

看吧,我其实是个表面上很温和的人。
实际上我想说的是:为了安全,反倒是应该允许向密码输入控件内粘贴内容才对。


同事的想法恐怕很朴素:功能尽量少,越少越安全。这个原则,我非常能够理解。

但是,他可能不用1password或者lastpass之类的密码管理工具,自己生活中也只在使用少量强度不够的密码。如果他像我这样一个账号独用一个密码,而且都是密码生成器生成的32甚至64字节长度的密码的话,大概就不会觉得有没有「粘贴」功能是无所谓的事情了。

若是阻止了用户进行「粘贴」,用户很大概率就只能采用比较简单的密码,而且很可能会重复使用自己别的地方也在用着的一个简单密码。那么这到底是更安全了还是更不安全了?


全世界可能没有哪一个国家像中国这样,醉心于所谓的「密码安全控件」。防键盘钩子,防内核驱动,私有的闭源加密算法,随机乱序软键盘,自己发明的输入法……

正常人的想法很简单:如果你的主机已经被攻破,那么谈什么安全性都是扯蛋。安全取决于最短的那块木板,所以没有必要去加码到这种程度。
但中国这边的想法更简单:我不管,我就是要「安全」。哪怕做到匪夷所思的程度。

回头想想,哪桩事情不是这样?地铁安检不也是同样的情况么?
曾经过了三年在防毒面具下的生活。然而,现今谁又不是呢?心中的防毒面具,生活在洼地的人,谁又曾拿下过?

2025-08-26

搜索习惯的这些变化感觉不是个好事情

图片来自网络

长期以来,我习惯在搜索引擎上搜东西。主要用Google,偶尔也会去用DuckDuckGo。Baidu那是「取材」的时候才会去用的。

现在很多人喜欢在SNS上搜东西了:微信、微博、小红书、抖音……

我拒绝这样的用法。正常人在SNS上写的那点碎片,搜出来也没有意义。如果能搜到大段的「有意义」的东西,那就是有人精心准备的喂给别人看的。利益驱动明显,正确性和中立性相当值得怀疑。不再会有Web上Wiki、Document、非商业性官方网站那种出于非利益性目的的分享了。即使有,质量也不高。这样的话,能搜到什么东西,可想而知。

当然,以上论调,仅限于中国大陆的简体中文「互联网」环境。


另外一种变化,就是很多人开始喜欢直接在AI上搜东西了,直接问。所以我觉得Google搞Gemini是必须走的一步,而且时间也不能再晚了。很高兴Google勉强算是搭上了车,目前还没被甩下去。

AI能帮人过滤、汇总和组织信息,所以貌似效率更高。我也很能理解为什么会这样。有时候我急着想要一个答案,特别是想要给别人看的答案时,也会直接问AI。不过如果时间允许,我还是愿意自己来做这些分析、整理的事情。

每当我选择去做或者不去做这些事情的时候,脑海中浮现出的就是《蠢蛋进化论》里面的各种蒙太奇。


最糟糕的是,有的人开始不搜东西了。

他们只习惯点开某个App,然后等着被投喂到他面前的东西。在我看来,这比什么都糟糕。这的确让我想起了那栋大楼里面的那些动物。

人类,也就到此为止了吧?

2025-08-19

这外包实在是太垃圾了

图片由Google Gemini生成

老板之前找某个外包团队做的一个项目,今天把阿里云RDS搞爆了,找我来看。

看了一下,是下午两点半左右爆掉的。空间撑爆了被「锁定」了。看了下监控,把空间撑爆的是temp_file,临时文件。
那个时间段有不少慢查询,找了SQL来看。一看到我就开始骂娘了:

select DISTINCT * from
        (select
        t.business_id id,
        any_value(t.type) type,
        t.`user` `user`,
        any_value((case
        when t.type='1' then '文章'
        when t.type='2' then '公告'
        when t.type='3' then '问答'
        end))  typeName,
        any_value((case when (select a.clone_num from tb_article a where t.business_id = a.id) is null then 0 else (select a.clone_num from tb_article a where t.business_id = a.id) end)) cloneNum,
        any_value((select a.title from tb_article a where a.id = t.business_id)) title,
        any_value((select a.content from tb_article a where a.id = t.business_id)) content,
        any_value((select a.publish_time from tb_article a where a.id = t.business_id)) publishTime,
        any_value((select a.essence from tb_article a where a.id = t.business_id)) essence,
        any_value((select a.`status` from tb_article a where a.id = t.business_id)) `status`,
        any_value((select a.top from tb_article a where a.id = t.business_id)) top,
        any_value((select count(c.content) from tb_comment c where c.business_id = t.business_id)) comments,
        any_value((select count(l.id) from tb_like l where l.business_id = t.business_id)) likes,
        any_value((select count(f.id) from tb_focus f where f.business_id = t.business_id)) focus,
        any_value((select a.pageview_num from tb_article a where a.id = t.business_id)) viewCount,
        any_value((select tba.auther from tb_article tba where tba.id = t.business_id)) userId,
        any_value((select m.auth_user_id nickName from tb_member m
        where m.id = (select a.auther from tb_article a where a.id = t.business_id))) nickName,
        any_value(t.browsed_date) browsedDate
        from tb_browsed_records t group by t.`user`, t.business_id ) temp
         WHERE  temp.user = 494 
        order by temp.browsedDate desc,temp.top desc limit 0,1

已经不想浪费我的时间了,找了AI来帮忙吐槽。以下是Google Gemini的输出

这个SQL看起来像是初学者写的,槽点确实不少。下面我们来一起“欣赏”一下。


槽点一:子查询泛滥成灾,性能杀手! 🔪

这个查询里,几乎每一个字段都用了一个独立的子查询来获取数据,像这样:

any_value((select a.title from tb_article a where a.id = t.business_id)) title,

这简直是性能灾难!数据库每查询一个字段,都要重新去 tb_article 表里查一次,而且还不是一次查所有需要的字段,是查一次 title,再查一次 content,再查一次 publish_time……这就好像你想买菜,不是一次把所有菜买齐,而是买完一个土豆跑回家,再回去买一根黄瓜,再跑回家……

正确的做法是使用 JOIN!将 tb_browsed_records 表和 tb_article 表连接起来,所有字段一次性查出来,效率高得多。

SELECT
  t.business_id AS id,
  t.type,
  t.`user`,
  a.title,
  a.content,
  a.publish_time,
  -- ...其他字段
FROM
  tb_browsed_records AS t
JOIN
  tb_article AS a ON t.business_id = a.id
-- ...其他连接

槽点二:DISTINCT + GROUP BY,多此一举

你看这个查询,外面有个 DISTINCT *,里面又有 GROUP BY t.user, t.business_id

DISTINCT 的作用是去重,GROUP BY 的作用是分组并聚合。GROUP BY 本身就会对分组字段进行去重。所以,在外层加 DISTINCT * 是完全没有必要的,反而可能会增加额外的计算开销。这就像你把一堆苹果已经按品种分好类了,然后又再来一遍“去重”操作,完全是重复劳动。

槽点三:any_value 的滥用

这个查询里大量使用了 any_valueany_value 的作用是在 GROUP BY 聚合时,从一个组中任意取一个值。对于 t.type, t.user, t.business_id 这种已经在 GROUP BY 里的字段,直接写就行了,不需要加 any_value

any_value((select a.title from tb_article a where a.id = t.business_id)) title

像这种对子查询结果使用 any_value 更是让人费解。它不仅没有解决任何问题,反而让代码看起来更复杂。

槽点四:重复的子查询,浪费资源

any_value((select a.auther from tb_article a where a.id = t.business_id))

any_value((select m.auth_user_id nickName from tb_member m where m.id = (select a.auther from tb_article a where a.id = t.business_id)))

这两个子查询都重复查询了 a.auther。完全可以在第一次查询到 a.auther 后,直接用这个值去查 tb_member 表,而不是再查一次。这就像你去问一个人的名字,问完后又回到原点,再问一次这个人是谁,然后再去找他朋友……

Google Gemini还帮我重写了SQL。写得挺好,执行速度至少快两个数量级。原来那个用了太多的子查询,就算逻辑上不该慢这么多,实际上就得慢这么多,而且还时间空间双杀。

这种写法,我也不认为是甲方逐步追加需求导致的。这就是不合格的程序员导致的,没有任何借口!

最后感慨一句:外包跟AI一样,你得要能驾驭。

2025-08-18

DeapSick二三事

图片由Google Gemini根据文章内容生成,与本人无关

上周,有同事遇到自己用代码导出的网页内的图片在Firefox上显示不出来的问题。他觉得是因为图片是BMP的缘故,带着这个问题去问DeapSeek,结果这个DeapSick就回答说:是的,Firefox不支持BMP格式的图片。
信以为真的同事,继续往下走的每一步都是错的。

我听说了这事就纳闷。不推荐BMP当然是真的,但要说不支持,最原始的位图为啥不支持?去问了Google Gemini和ChatGPT,都说没这个说法。不知道DeapSick是从哪里听说的,百度贴吧吗?

当然,一切以事实为准绳。我自己亲自去下载了Firefox,亲自试了一下,搞清楚了事情的原委。这位同事把BMP在网页img标签中的src写成了绝对路径,而且还是Windows风格的「\」反斜杠,能出来才有鬼了。

他问我为啥Edge和Chrome可以这样写。我也只能说以前靠IE,现在靠这两货给惯的。「file:///C:/a.bmp」这种写法他居然完全没听说过,看来还是从前论坛混太少。硬盘贴图党对这个应该是不陌生的。

当然,正确的写法应该是用相对路径。否则用户导出的网页换一个目录存放就看不到图片了。前面加不加「./」都不重要,重要的是不能用绝对路径。这个事情我一提他倒是想起来了,还有救。


DeapSick在这件事情里面有没有锅?当然有。感觉被调教得过于谄媚,顺着问的人说,完全罔顾事实。拿不准就拿不准吧,还说得斩钉截铁,这就是很大的问题了。
更大的问题当然是人,驾驭不住AI,必然被带走。然而同事也只是受害者,DeapSick背后的团队和社会环境,才是更大问题的根源。

我从来不用DeapSick,有Gemini和ChatGPT可以用,为什么要去找Sick呢?不过有朋友两个都在用,也给到我一些反馈。说跟ChatGPT相比,DeapSick就像个智障,明显感觉更「傻」。慢就不说了,输出内容也是不行。可能乍一看还行,但一对比就高下立判。

这方面我没有具体案例,但她的这种感觉显然是对的。ChatGPT我最近用得也越来越少,因为我想多「培养」一下Google Gemini,而且Google Gemini的Quota感觉更多一些,速度也更快一点。但有的时候我还是会两者对比一下,以防被骗。这种时候就会有感觉,以为Gemini的回答已经足够出色,但ChatGPT还能再「更上一层楼」。不由得感叹:AI比AI,气死AI。

不过这些AI也有集体犯傻的时候,傻得就很可爱了。


有一次,我让AI帮我分析一篇研报,但研报的来源那天偷了懒,直接放了一张图片上去。当时我的代码并没有适配图片,连下载都没有下载下来,更别提什么OCR的事情了。可以说我就只是丢了一个标题给AI,然后让它去分析。

当时用的是阿里的通义千问的API,做摘要用的是turbo版。qwen-turbo给到我的摘要,洋洋洒洒,像模像样的一大篇,涵盖了四五个品种。如果我不是事先知道会有问题,可能就被骗过了。

我们当时很奇怪,AI会做梦我们是知道的,但做得这么有内容,有点意外。于是有同事把相同的prompt给到了DeapSick一试,发现出来的内容也是一样的。感觉两者在考试前背了同一篇范文。

然后,那位同事把同样的prompt给到ChatGPT,发现回答的内容也是同样的。现在真相大白了,原来都是抄的班上的学霸的作业,被老师集体抓包。只不过现在可以美其名曰「语料污染」。至于社会主义温室里的花朵是怎么会被资本主义的毒草给污染的,可能要去问茅台师傅,我就不清楚了。

不过,我还是推荐所有同事「能用到什么AI就用什么AI,有得用总比没有强」。他们都去问AI,也就不用老来烦我了。

2025-08-16

Debian升级trixie踩坑记

图片来自网络

Debian前不久刚刚发布了Debian 13,也就是代号为trixie的版本。本周一上班后,从Repo的变更看到了这个消息,我就进行了升级。

之前已经把我的所有Debian环境统一到bookworm了,也是不久前的事情。当时Stretch和Buster已经停止维护了,Bulleyes还是oldstable状态。我只有两个环境是bookworm,于是一咬牙把所有的环境都升级到了bookworm,也踩了一些坑,下面合在一起说。这次确实没想到来trixie得这么快,也这么巧,趁上次坑里的屎还是热乎的,也就再咬一回牙了,反正我的牙也不是自己的。

简化的正常升级流程

首先强调一点,升级不要跳版本,从低往高一级一级地升。每次升级解决这一次的问题,然后再往下走。我这次是从bookworm往trixie升,只需要升级一次。如果是jessie,那么就要stretch->buster->bulleyes->bookworm->trixie,以此类推。
历史版本代码参见官方说法,最好是看英文版,更新最及时。

升级过程完整的指引,最好参见Debian官方文档(有中文版,但翻译得很不好,很多没翻。还是看英文版吧,Google翻译或喂AI都行。拜托了,都2025年了)。但如果要简单说的话,要点只有以下这些:

  1. 先把当前版本升级到没法再升。
  2. apt update
    apt upgrade
    
  3. 去/etc/apt/sources.list里面,把版本代号改掉。去/etc/apt/sources.list.d下面,把文件里面的版本代号都改掉。
    这一步原则上可以用shell命令来做,但其实还有non-free-firmware之类的小点,依赖别人的脚本并不是好事情,所以我也就不贴了。我觉得还是讲个原则,手动操作吧。必要的时候去参考已有的新版OS。
  4. 正式开始升级:
  5. apt update
    apt full-upgrade
    
  6. 对选项作出反应:
    1. 升级过程中要不要重启服务,可以选yes。
    2. 要不要覆盖旧版配置文件,自己看吧。如果不记得以前改了哪些就建议选N了(特别是针对sshd),建议还是自己「合并」看看。
  7. 如果升级顺利,重启。
  8. reboot
    
  9. 清掉不再需要的包。
  10. apt autoremove
    

坑一:升级过程中ssh连接中断了

是我自己的锅。正在升级的时候,来了同事问我问题,作了一番长篇演说以后,忘记了这事,去忙别的了。回头想起来时,发现ssh已经断了。

ssh断之前应该是在apt full-upgrade的过程中,等我回答某个配置文件如何处置。赶紧再连上,apt full-upgrade继续,发现被锁。
遵照提示:

dpkg --configure -a

得以继续。
随后提醒自己下次记得集中注意力。

坑二:sysctl

升级完后发现有些不对,检查了一下,发现/etc/sysctl.conf配置文件被dpkg给备份起来了,后缀是dpkg-bak。

改名回来后sysctl -p,以为解决问题。重启之后发现BBR还是没能启用。翻找资料,发现是机制改了。现在得把这些配置写到/etc/sysctl.d/下面去,自己建conf文件。

当然,这样也有好处。现在可以把不同的内容分别写在不同的配置文件里面,不用像以前那样全部放在sysctl.conf里面,找起来比较麻烦了。

坑三:haproxy启动不起来

算是一个小坑,因为报错信息在日志中写明白了。
我的haproxy是早期版本安装的,需要在haproxy.service中[Service]节内增加LimitNOFILE=524288的设定,不然ulimit -n有问题。

对Linux不太熟的朋友多说一句:haproxy.service一般在/etc/systemd/system/multi-user.target.wants目录下。当然也可能在别处,端看你之前是怎么安装的。实在找不到的话,去问问AI吧,或者装个mlocate。

[Unit]
Description=HAProxy Load Balancer
Documentation=man:haproxy(1)
Documentation=file:/usr/share/doc/haproxy/configuration.txt.gz
After=network-online.target rsyslog.service
Wants=network-online.target

[Service]
EnvironmentFile=-/etc/default/haproxy
EnvironmentFile=-/etc/sysconfig/haproxy
BindReadOnlyPaths=/dev/log:/var/lib/haproxy/dev/log
Environment="CONFIG=/etc/haproxy/haproxy.cfg" "PIDFILE=/run/haproxy.pid" "EXTRAOPTS=-S /run/haproxy-master.sock"
ExecStart=/usr/sbin/haproxy -Ws -f $CONFIG -p $PIDFILE $EXTRAOPTS
ExecReload=/usr/sbin/haproxy -Ws -f $CONFIG -c $EXTRAOPTS
ExecReload=/bin/kill -USR2 $MAINPID
KillMode=mixed
Restart=always
SuccessExitStatus=143
Type=notify
LimitNOFILE=524288

# The following lines leverage SystemD's sandboxing options to provide
# defense in depth protection at the expense of restricting some flexibility
# in your setup (e.g. placement of your configuration files) or possibly
# reduced performance. See systemd.service(5) and systemd.exec(5) for further
# information.

# NoNewPrivileges=true
# ProtectHome=true
# If you want to use 'ProtectSystem=strict' you should whitelist the PIDFILE,
# any state files and any other files written using 'ReadWritePaths' or
# 'RuntimeDirectory'.
# ProtectSystem=true
# ProtectKernelTunables=true
# ProtectKernelModules=true
# ProtectControlGroups=true
# If your SystemD version supports them, you can add: @reboot, @swap, @sync
# SystemCallFilter=~@cpu-emulation @keyring @module @obsolete @raw-io

[Install]
WantedBy=multi-user.target

坑四:其它软件还没提供trixie源

我周一把Debian升级到trixie的时候,顺手把Nginx/PHP/Redis在/etc/apt/sources.list.d下面的Repo也给改了。然后就发现PHP已经有了trixie源,但Nginx还是404,Redis是403。

截止本文刊发的时候,Nginx已经OK了 ,Redis还没好。如果后续有变化,我就来把这一段编辑掉。

还有一个问题是simple-obfs在trixie官方源中没有提供,而bookworm是提供的。git然后源代码编译是一个解决方法。如果还是想从apt直接安装省些事情,请在bookworm的时期先完成simple-obfs的安装。

坑五:GFW捣什么乱

这个就坑我大发了,几乎可以专门写一篇。不过我还没完全弄明白,以后搞清楚了再说吧。

我家里的网络访问Debian官方源不算快(应该说很慢),我又不想改源,于是用了SS代理来「加速」。
apt update的时候发现,Debian源没问题,但Nginx和PHP一直连接超时。区别就在于,Debian源是http,后二者是https。
用curl -x -I简单试了一下,https还真是走不了SS代理。http就可以。

如果答案是「GFW检测并干扰了TLS over SS」,那我没话说。我知道它有这能力,TLS的确特征明显,尤其是握手时。这可能也是最合理的一种解释了。
但我HTPC上有一台VM使用自己的ss-local是OK的。如何解释?同样的OS版本,同样的SS版本,同样的网络环境、节点、线路、协议、密钥、插件,同样的payload和访问特征,连TTL和MTU我都看了,实在是想不明白。

有问题的VM只是说TLS握手出问题的概率很高,但并非100%。我开了Verbose猫在两端看了一下,发现有问题的时候貌似有replay attack。我拿不准,但看起来像。两端的节点都换过,没有什么差别,该replay还replay。

在公司没问题,在家里有两台都有问题,可见应该跟家里接入的上海电信宽带有关。然而家里HTPC上从Windows去用那两台上的ss-local/privoxy作代理都没有问题,在我遇到问题的时候,儿子还在欢看YouTube呢,线路没被封。SS是AEAD版本,cipher不对时的反应是No Data Transfer,GFW肯定拿不准。

那台没问题的VM就是不会引发,100%地OK,让我始终想不通的终归还是这一点。在SS上面再叠一层tor,也是OK的。最后不得已,我让apt走了tor。没去试SS over FRP的方式。先这样吧,也没慢多少就是了。

2025-08-15

能用的东西就别动!

一直以来,以为只有程序员需要在意这句话,然而今天我也遇上了。

图片来自网络

用「夸克云盘」下电视剧的时候,一直弹框提示我升级。升级了以后发现,超过云盘容量的内容,即使是第一次也无法保存了。回退到3.20.0版本,又可以做到了,看来这个逻辑是客户端在控制,而新版已经把这个「Bug」给堵上了。

曾经也吃过这种亏,只能说我「好了伤疤忘了疼」。以前用「阿里云盘」,也是一直提示升级。有一天升级完以后直接进不去了,应该是那个版本的EXE跟我的OS之间出了些问题。但进不去也就意味着再没机会修正,而且官网上也只能下载到这个有问题的版本,于是我只好又去找了旧版的安装包。还好网上还能找到,存起来当「传家宝」,现在也还能用,但再也骗不到我升级了。

而且这个4.x版的「夸克云盘」客户端,还把我的默认浏览器给改了。我一开始还纳闷,你个网盘客户端,动我WebBrowser干什么?后来进去后发现它其实就是一个浏览器了。好吧,中国人还真是好收拾。

我以后什么客户端都不敢升级了,起码国产软件得是如此。我已经给它们「最惠国待遇」了,单独放在一个虚拟机里面跑,没想到还是不够。当然,说起来它们也是可以搞「强制升级」的,希望架构师忘记了这一出。但它们也可以搞一个「以旧换新」,等旧客户端市占率低了以后就把服务掐了。没办法,谁叫我有求于人呢?只希望这一天晚些到来,而我动作要加快了。

这次下载到的3.20.0版的「夸克云盘」客户端,我也会当作「传家宝」存起来。有需要的可以从这里来拿。我找到的地方本身也是一个「夸克云盘」的资源网页分享,没有安装客户端就无法下载。搞墨比乌斯没意思,我就直接放Dropbox共享链接了。

再强调一遍:能用的东西就别动!


五天后记:现在夸克云盘大概已经把这个漏洞从服务端给堵上了。看来我还是太乐观。好吧,Life will find a way。

2025-08-08

惊闻Pocket关站

今天用Pocket的Chrome插件把两篇文章收藏了起来。收藏过程比较慢,引起了我的一点点注意。想起已经很久没去整理过里面的文章,于是打开了网站,才惊讶地发现一个月前它已经宣布要关闭了。

图片来自网络

还好留了三个月给用户导出数据,10月8日截止。赶紧去申请,收到邮件一看,一个不到700行的csv,压缩了还没有50KB。说我数据少吧,600多篇文章也不算少了。但下载附件的时候我就心里一惊:估计只有标题和URL,那些爬下来的内容,怕是都没了。

我当初用Pocket不用Delicious(顺便说一句,Maciej Cegłowski现在连更新Let's Encrypt的SSL证书的acme.sh脚本也懒得去放一个了)的原因,其实就是因为Delicious只保存链接,不存内容。「社交」是我并不需要的功能,「推荐」也是。Pocket后来渐渐地也很多页面都爬不下来内容了,所以我也渐渐远离了它,只是通过Chrome插件往里面扔那种「将来可能会有用」的东西,但再也不去看。一个网站若是用户都是我这种样子,关闭也是必然的,我应该早有心理准备才对。

当今「互联网」的一个很大的问题,就是许多网页已经消失了,不见了。有伏地魔的原因,有赵公明的原因,也有乔布斯的原因。不管怎么说,事实就是如此。我试了我导出的数据里面比较古早的几个URL,都打不开了。有的虽然页面没了,网站还在,还有的甚至连网站都没有了。我现在甚至开始有点怀念Evernote,但它其实也没有多好用。Web不管几点零的时代,好像都已经过去了。

我现在转到了Instapaper下面,刚开始用,还没什么心得。尝试导入Pocket的数据,Instapaper告诉我还要等几个小时。从早上到现在也还没动静,我觉得这是好事。花的时间多,意味着它真的会去爬内容,否则只是URL应该几个毫秒就结束了。

Instapaper的Premium会员不便宜($5.99/Mo,$59.99/Yr),比Pinboard的含永久存档和全文检索功能的会员($39/Yr)还要贵。总之对于我而言都有点肉疼,因为我还买了Medium和Dropbox,而且普通中国人都比较穷。

让AI对比了一下,我最后如果要成为付费用户,可能还是会去考虑Pinboard吧。我的核心需求是永久存档,全文检索也是羡慕的,笔记并不是必须的。毕竟Instapaper免费也不是不能用。

而且,见鬼,我对Maciej Cegłowski的不少理念还挺认同的。

2025-08-05

是谁动了我的HDC?

最近工作上倒是查了不少问题,然而到了末尾都发现只是一些低级错误,完全不好意思拿出来说。但今天遇到一个,还算有一些意思,可以讲讲。


问题的表现是我们的软件上某些部位偶尔会「花」掉,显示的是之前覆盖在上面的内容。有经验的程序员一看就知道是GDI的问题,但到底是什么问题呢?

图片由Google Gemini生成

刚开始的时候,以为是GDI泄漏了。曾经有过一个例子,漏到了好几千,后来到了1万,触发了CEF的CollectGDIUsageAndDie被Dump了。还没到1万的时候,界面上的表现就是开始花,其实就是有部分GDI函数已经开始调用失败了。

然而这次并不是,GDI对象数很正常。开发人员远程调试跟了一下,发现是HDC拿不到。CreateCompatibleDC()得到了一个NULL,因此MemDC创建不出来。


什么情况下CreateCompatibleDC()会调用失败呢?GDI对象数不多,内存也很充足。软件中其它部位的MemDC是能正常创建的,因此全局性的因素都可以排除。什么光栅设备、显卡驱动之类也就不可能是原因了。
除此之外,就只剩下了一个可能性:CreateCompatibleDC()传进去的HDC参数有问题。

试了一下,乱传一个不存在HDC,的确会导致CreateCompatibleDC()返回NULL。如果传的是个NULL进去,倒是还好一点。看来是窗口上的HDC有问题,当然也有可能是窗口本身就有问题。然而其它地方也在用同一个HWND创建MemDC,一切正常。所以还是某些HDC有问题。

HDC的值看起来并不奇怪,也没有什么好办法确认它到底有什么问题。HWND还能用Spy++来看,HDC我是一筹莫展。还好可以OutputDebugString。日志打出来,有意思的地方来了。

我看出问题了:当某个HDC失效的时候,它一定是被连续拿到过两次,中间没有ReleaseDC()过。这两次GetDC(),都得到了同一个HDC,肯定不正常。
我把this指针和HWND的值也加到了日志里面,这下看得更清楚了。两次GetDC()分别是不同的HWND。而HDC失效之时,就是当它被最终ReleaseDC()的时候。只不过这次ReleaseDC()的HWND是一个旧的窗口,那个窗口此时应该已经被销毁了。


窗口OnDestroy()的时候,没能把它的HDC一并归还,这当然是我们软件中的代码错误,也是我们遇到的问题的直接原因。但故障现象的根本原因是什么呢?我们确实没有按照规范「一借一还」,至少窗口还「在世」的时候没有。不过ReleaseDC()难道不管三七二十一,只要有人拿着某个HDC来释放,它就答应吗?都不用看看HWND对不对得上吗?

微软关于ReleaseDC()的API函数说明在这一点上就有点语焉不详了。大概它没想到有人会这样去实践?的确也没人问这种问题,完全找不到资料,只好自己动手做了个实验:

HDC hDC = ::GetDC(hWnd);
int nRet = ::ReleaseDC(hWnd + 0x1000, hDC);

随后再在这个DC上用GDI函数画东西,确实画不出来。nRet也的确是1,按照微软的说法,返回值1表示DC被释放,这倒是没有骗人。我把hDC也加了个数字,然后再跑一遍,这次nRet变成0了。

所以说,微软是在ReleaseDC()的时候搞了个「容错」逻辑?只要HDC对得上,就给释放,不管HWND对不对得上号?我一开始跟Google Gemini探讨这个问题的时候,它还不相信,直到我告诉它测试结果。


回过头来看,为什么两次GetDC()能得到同一个HDC呢?
我们的主窗口,经历了销毁后重建的过程。在OnDestroy()的时候,没有及时执行ReleaseDC()。但Windows可能认为,窗口不在了,DC也就没了。于是另一个新建起来的窗口又通过GetDC()拿到了同一个HDC。等到主窗口的C++对象开始析构,调用ReleaseDC()的时候,新窗口拿到的HDC就被背刺了。系统的DC应该是在放一个池子里面,所以是有可能被重用的。这当然需要「运气」,也正因为如此,故障现象不是很稳定。

会遇到这种问题的人,应该不多。现在还在用GDI做开发的项目本来也就不多了。我在网上没能找到什么可以参考的信息,还好勉强算能够重现,就抓住机会解决了问题。经验值又+1了。

最后说明一下:我这个实验是用VS2013在Win10下面做的。不同的OS以及VS版本可能会有不一样的情况。毕竟是所谓的「未定义」行为。

2025-07-26

一路向西

为期一周的自驾游,又接了下一个任务,如今终于缓过劲来,开始整理游记。

婺源

婺源在我的印象中,是因为油菜花而出名,大约得有二十年了。我们这次去的时间不是看油菜花的时间,没办法,孩子只有暑假寒假有空。但现在婺源也不只有油菜花了。

订了一间民宿。没有重蹈去年日照的覆辙,至少在干净、卫生方面,太太这边算是「过关」了。离婺女洲度假区只有一个街区,不过我们还是开车过去的。天气实在是太热了。

婺源民宿

两个房间,中间并没有门。主卧的阳台部分还是挺不错的,视野很好,只可惜朝向一般。
老板是个设计师,风格还算简单明了,没有我们不喜欢的地方。室内储物空间少了一些,更适合年轻人。卫生间相当吵,但其它房间意外地隔音还不错。

闷骚老板整了个大厅吧台,可以提供一些鸡尾酒。第一天Check In的时候,有两个女生在吧台抱着哭。第二天凌晨一点多,有年轻人在房间摔门数次,太太不得不出门干涉。现在的年轻人到底怎么回事啊?

婺女洲度假区

没能拍到合意的照片,勉强用这个来代表吧。

婺女洲度假区

大致是一个人造的网红景点,面积倒是不小。有不少刻意的摆设,适合年轻人拍照片。景点里面也有酒店,不知道住起来感觉怎么样,价格肯定比我们的民宿贵。话说我们刚订的第二天,民宿在携程上就涨价了近100元间/夜。

这个景区也有一个水上乐园,有不少游客其实是冲着这个来的,特别是夜里。我们没带泳具,也无意把自己整成大虾,就免了。

为了看「打铁花」,在高温下等了四十分钟,基本上到了大家的极限了。然而整场表演波澜不惊,离得还元。比起我二十多年前在铜梁看的打铁花表演都要差上不少,也难怪我近来各种「今不如昔」的长吁短叹。

停车费10元。在停车场目睹了有大神开车推着「雪糕桶」到处跑,保安边追边骂也不管用。只能说还好「推」的不是小朋友。

卧龙谷

本来第二天是想去篁岭的,但一来嫌价格贵,二来天气也太热,最后换成民宿老板推荐的这个「卧龙谷」景区。据说还比较凉快,毕竟是去山里玩水。

卧龙谷

我们也没有去玩水,直接索道上了半山腰,然后一路玩下来。
风景不错,拍了不少照片,不少都具备做成Wallpaper的资格。图上这座索桥上很凉快,风不小。再往上就到顶了,最后一个景点大龙瀑就在前面不远处。可惜太太爬不动了,在中途停了下来歇脚,拒绝继续。最后这一段是我和儿子「攻克」的。

弦高古城

上午去过卧龙谷,下午稍事休息,也是避开夏日的锋芒,然后傍晚去了民宿老板推荐的另外这个景点。

弦高古城

老板建议我们把车停在县政府停车场,走过去两分钟就到了。去的时候还好,回来的时候发现停车场门前的路上已经堵得水泄不通。不管是汽车还是电瓶车或行人都很多,被迫走了另外一个方向绕回去。

这个景点还是有一些意思。虽然也是人造的,但相比起其它「古城」,它多了一些「立体感」,有一些高低错落。在长三角就很难见到这样的地形。

傍晚还能好好拍照,入夜了人变得很多,行走更像是推搡,大概之前都在躲太阳。
年轻人还是很多,感觉婺源各个景点现在面向的游客就是年轻人为主。在当下这个时代,不确定这对它是不是好事,我也要想一想。

景德镇

「瓷都」名声在外,既然顺路经过,也就进去看了一眼。
没有留下任何值得放出来的图片。太太本来想找几个免费的景点玩玩,打发掉大半天的时间。然而这里的景点大多都要钱,而且不是一百多就是大几十。好不容易找到了一个「抚州弄」,发现只是一个售卖地摊货和开苍蝇馆子的地方,十分钟就「逛」完了。
停车费也付了10元,相比起来,弦高古城昨晚只有3元的停车费简直良心。吃了午饭我们就头也不回地走了。

KFC里面,也有外地游客在抱怨景德镇「哪里都要钱」。话说这种「自来熟」的Guest我们这趟在路上已经遇到过不止一次了。
感觉景德镇整个城市就是一个中国不同时期的混杂物。有荒废的厂房(是真的荒废了,不是景点),有老旧的小区,《钢的琴》里面那种。然而对面可能就是一个新修的商场,却特意修成红砖风格,只是从系统窗上看得出来端倪。

走马观花,匆匆一瞥留下的印象,不一定对。
我不是太喜欢这种风格,但它是事实,是现在正在发生且存在的事实。这就足够了。起码它是真实的。

瑞昌

九江下面的一个县级市,主要不是来玩的。

瑞昌老小区

这种老小区,外观都很破旧。其实好好装修一下,房间里面还可以不错。
底商是餐饮,因此卫生状况不好,时不时污水横流。不过我在重庆的老房子也差不多,每个城市都会有自己不那么光鲜亮丽的一面。

瑞昌城隍庙附近

因为不是来游玩的,没怎么拍照片。勉强拿出这一张。
过去的位置上是什么,我已经忘却了。总之图上的这些东西是新修建的,看起来还像模像样。据说是改建了一座「城隍庙」。

另外,市中心也搞了一个「柳湖公园」,晚饭后去遛达了一圈,单从游人数量上,也可以说是不少,但明显都是当地居民,年轻人不多。
也遇到有人在直播,以及大批的老年广场舞团体。这个时代就是如此。

月亮湾

安徽宣城下的泾县辖区内的一个景区。太太从「移动互联网」上看到「皖南川藏线」,有点神往,于是回程的时候安排了这样一个行程。

月亮湾

皖南跟川藏线搭什么界?我对此是一脸问号。其实也就是山路窄风景好适合自驾游的意思,有点「蹭」的感觉。

主要也是玩水,所以我们又是当「看客」了。太太光着脚到小河里走了走,水量是上游控制的,白天大一些,夜里不大。有一些浅滩用来让汽车过河,直接开过去,两边还有游客泼水。

我们在河边的民宿住了一宿,第二天准备继续去六道弯,但看了一下回程的路线太耽搁时间,于是改去了桃花潭。

桃花潭

没错,就是那个桃花潭。「桃花潭水深千尺,不及汪伦送我情」。
只是不知道为什么是在这个角落里?古时候这里很繁华吗?

桃花潭

风光还是不错的,特别是在据说是李白当年喝小酒的小阁楼上。小小的,是我喜欢的风格。视野挺好,看得到下面的渡口有船在来回摆渡。

我们一开始本来是导航到的景区入口,门票又是要大几十。太太从「小红书」上看别人的攻略,说好看的景点都在西岸,汪伦墓什么的。收费的景区是东岸,于是我们上车过河,其他的游客也纷纷拔营。

这个景区感觉有点乱,几股势力把各个景点瓜分了,各自为政。听别的游客说,渡船摆渡一次60元,从东岸到西岸要70元。我在想这个生意真好做,我也可以做,只要一半价钱就好。

2025-07-25

编程随想:文档很重要

公司的文档水平一向不好,习惯也很不好。在代码中能写个注释,已经算是有好习惯了。在我看来最低限度的ReleaseNotes,都是有人去推动后才建立起来的制度。大言不惭一下:看起来正式一点的文档,大多出自我的手笔。

前段日子,下了狠心,盯着同事们整理了一篇文档。大约三、四个月的开发内容,最后写了82页。我觉得不算多,但可能已经多得让不少人懒得去看了。也正常,文档不是小说,不是让你没事从头翻到尾的。有需要的时候去查上一查,还能有所收获,这就已经算是有价值的文档了。尽管离我认为的「先写文档后编码」还有不少差距,但要是能事后真真正正地补上,也是功德一件。


现在流行AI,公司上上下下都在搞自己部门的RAG。这推动了一波文档热潮。AI没有东西吃,吐出来的东西也就质量不咋地。这样一来,文档就愈发的重要了。

对我而言,这是好事。我倒是喜欢写文档。比起写代码,写文档更接近我的舒适区。何况偶尔我也会塞点「私货」进去,甚至把文档写得像小说一样。反正是内部文档,调皮一下也无妨。将来万一有人看到,也许会有会心一笑。

而且,为了能安心退休,我倒是也愿意把自己的「毕生所学」给「贡献」出来。知识这种东西,有的人会藏私,但我觉得藏着掖着没意思。真正的能力,并不在于别人学不到的东西,而是别人学不会的东西。


有的时候,有些文档会让人觉得很没意思。完全是形式主义,没有什么有价值的内容。对这种文档,我个人是并不喜欢的,但偶尔也必须得去做一做,还好不是太多。

在现在的公司,基本碰不到这种事情。就算有,可能也不是我的事情。但在以前的公司,就会有不少。看起来厚厚的一叠文档,比词典还厚。有没有人看?没有。有没有用?有。你得有它。有就行。

曾经向当时的主管抱怨过,得到的回答是:这些文档的确没有意义,但规定要求必须得有它们。可能是因为如果能沉住气把这些都完成了,那这个项目的总体质量应该也不会差到哪里去。

也就是说,这是甲方的一个测试,一个考验,或者说是一个保证下限的东西。肯把这些无聊的事情搞完的,大概率也就不那么草台班子了。

或许有几分道理,也或许其实是歪理。但不管怎么说,总之当时的我是被说服了,埋下头继续写。


又有的时候,有些文档,真的是必不可少的。

记得以前说过这个观点,可能是在Google+上。我认为如果要自杀,一定要写遗书。悄咪咪地去死也就算了,别给后人留悬案。如果有遗书,家人或许还可以帮你讨个公道,没有遗书的话,很多时候就白死了。反正都是要死了,干嘛不把后事办好一点呢?

图片来自网络

反正车费你都拿不回来。

2025-07-23

编程随想:可以delete this吗?

在C++中能不能delete this,去问AI,它能给你一个基本上算是标准答案的回答。面面俱到,滴水不漏。

在C++中,从技术上讲,你可以在类的成员函数中调用 delete this。然而,强烈不推荐这样做,因为它非常危险,并且会带来很多潜在的问题。……

看起来是不太好的,至少是不推荐。
但是如果你改一个问法,去问可不可以「对堆上new出来的非模态对话框在PostNcDestroy中做delete this操作」,那它又会改口了。

在MFC中,当你在堆上new了一个窗口类,并且它是一个非模态对话框,那么PostNcDestroy中调用delete this是完全安全且合理的。这是一种标准的MFC编程模式,专门用于解决你所描述的生命周期管理问题。……

所以,事情都得分场合来看。有些情况下「坏事」也可以变成「好事」,至少会是合理的。反过来也一样。大多数情况下,对具有某个「标签」的事物并不应该有唯一的判断结论,因为它可能还有别的标签(不知道3D人士看不看得懂)。


上述资讯,其实算是C++开发的基本功。MFC开发如果入了门,也不应该有此疑惑。不过呢,世间的事情很多都比较复杂,并不像示例或教科书上那样简单、清晰、明了。夹杂了别的东西之后,情况就又发生了变化。

最近在查一个问题,就遇到了一个案例。
有个小弟,在PostNcDestroy里面,去上了一把锁。std::mutex,成员变量,用std::unique_lock辅助管理。
然后程序就Crash了。调试起来倒也容易,因为这个虽然看起来跟多线程有关,但也并不是真正的多线程问题,还是很容易复现的。

我也不多啰嗦。到了这把年纪,很多抖擞精神去查的问题,结论出来以后都失望无比,最后写都懒得去写,何况世上还有AI。有经验的程序员应该一眼就看出问题了:std::unique_lock在PostNcDestroy函数退出时,才会把自己管理的std::mutex给解锁,但那个时候这把锁的主人已经把自己给毙了。这就相当于访问了无主内存。

所以,「自毙」这种事情,虽然不是不可以,但后事还是要先安排好。


图片由Google Gemini生成

比如,「禁诉令」这件事就做得很好。否则法院可能哪天就得直接关门了。

2025-07-04

「伟大」的独立日

收到美股基金定投失败的消息,咕哝着「狗日的美国佬又放假了」,看了日历才想起来是「独立日」到了。

还没看过同名电影,据说是科幻片。我的阅片量,说低不低,说高也不高。但是拜最近的bttt11.com和cunpian.cc被404所赐,将来估计是会持续走低了。

在这「伟大」的独立日,美国国会通过了一项同样「伟大」并且还「美丽」的法案。具体内容我也不清楚,不评论。反正川普和MAGA是想它通过的,对了还有万斯,就是让泽连斯基去穿西服的大聪明。然后马斯克是反对的,态度还挺激烈,以至于川普说要把他遣送回南非去。

美国就是美国,还是挺文明的,要收拾人讲起来也就是「遣送」。你看像人家赫斯还得自己开飞机,林副主席不知道是不是自己开的三叉戟,当然也不能排除马斯克最后是不是也还会落得一个只能自己开星舰的下场。

图片由Google Gemini生成

美国从英国独立,说起来自然是个大事件。但英国其实也没有那么「坏」,至少后来也成功地把权力关进笼子里了。相对而言,制宪在我看来对于今天的影响其实要更大一些。然而美国的宪法日并不是一个法定节假日。我对此的理解是公民与政府的权力斗争是一个长期持续的过程,并且现在仍然在继续,宪法修正案都二十几条了,所以也没有什么值得纪念和庆祝的。

Blog上黑白色的祭奠,已经持续了一个月。这一个月以来,我作为一个色觉正常的人士,也体验了一把色觉障碍者的感觉。去感受,去理解,然后去思考,我觉得是自己人生路上的一种应该要去践行的方式。在这方面肯定有人比我做得更好,无意追赶或比较,也无意标榜什么,只是希望自己还来得及。

刚好那位总理讳莫如深的冥寿也过完了。因此把网站的配色恢复正常吧。明年见。

2025-07-01

我的电脑史(三)——80486DX2-80

已经忘了是初三还是中考结束后的假期里面。我的电脑升级成了486。

初三的学业还是很紧张的。我在初一和初二的时候,成绩并不是很好。数学当然还是班里第一,物理和化学也没有问题。尤其初三加上的化学,因为只涉及到一些常识性的东西,我小学就通过科普读物了解过了,基本没费什么力气。但语文和英语这些文科并不突出,特别是语文,因为是班主任教的科目,一个老头子,跟班里绝大部分男生都不对付,所以成绩很一般。初一的时候历史还不及格过,还好只有那一次而已。

所以我现在回想起来,觉得父母真的是有魄力,敢在那个时候给我换电脑。升级以后的电脑,具备了彩显、声卡、光驱,可以被称为「多媒体」了,娱乐性大大增强,不亚于如今的手机。对于当时还是个初中生的我,无疑具有莫大的诱惑,很容易走上「邪路」。

转折点来了,初三我们班换了班主任。

图片由Google Gemini生成

老头子本来就有劣迹(私下有传言他以前有跟女生不清不楚过,按我外婆的说法是「犯过错误」),带的班级成绩也不好,在年级里面的评价是学生都比较顽劣,有时候还有老师和学生拳打脚踢的事情发生。于是到了初三的时候,年级组把我们的班主任换成了一位三十来岁年富力强的青年女老师。

女老师的作风很是强横,个性鲜明突出,很快把整个班级收拾得服服贴贴,不再敢乱来。当然她也不只是强硬而已,在提升考试成绩上的确有真才实学。通过一些完全是针对应试教育的突击工作,学生们的成绩提升明显,家长们也服气。我直到现在都还会在梦中时不时梦到又去参加考试,然后心里暗自发愁背过的东西过了这么久怎么可能还记得。


升级是去的电脑城,那个时候重庆的整机DIY行业才刚刚开始起步,一切都很原始。商家自己也没货,带着我们四处找零配件。印象中很深刻的是,主板是去一家专卖店里面选的,门店在电脑城之外,嘉陵江索道那边。当时在选Hippo 10还是12这件事情上纠结了蛮长的时间,最后还是选了12。

图片来自网络,但确是当年的模样

CPU用的是TI的486DX2-80。内存则升级到了4MB,用上了72线的SIMM,印象中是两根,2×2MB。386SX的机箱已经太过窄小,放不下HIPPO 12主板,所以也一起换掉了。新的机箱其实很简陋,盖子的铁皮挺薄,打开的时候还会变形。当时不太在意,也无从对比,后来我大学时DIY接触到了其它机箱以后,才知道它的品质相当不行。

这次升级的时候,准备加一部光驱。商家给到我两种选择:1x或2x,也就是单倍速和倍速光驱。当然当时也有4倍速光驱,不过价格明显偏高。我们选了2x倍速光驱,但商家死活装不上,换了1x光驱就可以。
之前还在用386主机的时候,硬盘已经升级成了一块三星420MB。最后的诊断结果说是这块硬盘跟光驱冲突。偏偏1倍速和2倍速的差距在某些场合又非常明显(比如看VCD),最后不得已把硬盘换成了Maxtor的420MB。旧硬盘抵了一部分金额,但还是额外出了一笔钱。

光驱已经忘了是什么品牌,好像是Acer。当时坚持不用1倍速光驱的原因,有一部分也是因为那个可以兼容三星硬盘的单倍速光驱的品牌我没听过。后来这部光驱用了蛮长时间。面板上有外接3.5mm耳机的接口,也有按键可以直接播放CD,不过音频是从这个外接接口出去的。后来的光驱就都有一根音频线,可以接到主板或声卡上,走声卡输出了。

图片来自Reddit

既然是「多媒体」电脑,声卡也是必不可少的。声卡是OPTi 82C929A MAD16 Pro,兼容性倒是还不错,大致相当于Sound Blaster Pro/16的程度。Driver在一张1.44MB软盘上,其中测试MIDI的Demo音乐我听了不知道多少遍,随口就能哼。后来进大学看了NBA才知道原来是美国国歌。这块声卡一直用了五六年,到我大学中期才淘汰掉。

声卡接了一对塑料音箱,一直用到我大学毕业。另外还配置了鼠标。键盘已经有点失灵,于是顺便也换掉了。因此,说起来留下的只有显卡和显示器,以及两个软驱。其余的配件都换掉了,相当于新买了一台电脑。因此老的80386主机我就收了起来,加上之前换下来的双频单显,怀旧的时候可以装起来玩玩。


说起怀旧,那个年代我就已经开始了。我偶尔会把一台「大屁股」电视搬到我家里睡的「上铺」去,接上FC开始玩「魂斗罗」。那台电视据说是我大舅年轻时玩过的,整个像一个小柜子。透过木质外壳的缝隙,看得到里面有电子管,开机后的确需要预热一段时间才有图像。屏幕是黑白的,都不知道有没有十寸,不说的话我还以为是个示波器。当时不知道DPI为何物,反正我觉得它清晰度还不错,比家里18寸彩电要高。

图片来自网络,大致长这样

有了光驱作为输入设备,电脑的可玩性骤然高了起来。装机的时候,店员用了一张游戏光碟作为试机碟,我看到里面游戏挺多也挺不错,死乞白赖地找人家要了过来。这张光碟我现在还留着。
第一个玩的游戏是《悲恋湖杀人事件》,因为目录的名字「SADLAKE」是我第一眼看到并且能看得懂的。
第二个学会的单词则是「KOEI」。我很幸运,玩的第二个游戏的目录名字是「KOUKAI2」。它让我知道了,即使是在那个年代,那种硬件条件下,一个好游戏也能做到什么程度。

图片来自网络

此后,我也时常往电脑城跑,自己去淘光碟了。到上大学为止,大概攒了两个光盘包,40张碟片左右。一开始光碟要40至50元一张,后来慢慢降到10元左右,说起来也是花了接近一千块钱。看来,90年代中后期,不仅我们家,大家的收入水平都在慢慢往上走了。

高一的时候,我去买过我上大学以前唯一的一件正版游戏,就是96年发售的《金庸群侠传》,79元。当时是从《大众软件》杂志上看到,于是刚一上市我就去买了。还记得是在文化宫中门对面的那个大厦里面买的,从天桥进二楼,有一些卖IT软硬件的商店。国内正版软件市场那个时候刚刚开始起步,国人的意识也是一样。我妈把我痛骂了一顿,说我乱花钱。然而我也不花什么别的钱,连零食都不吃,她也拿我没什么好办法。

不过这并不是我买的第一款正版软件。第一次换硬盘的时候,我当时提出来要把他们的一些软件目录上的内容给拷贝到硬盘上带走,后来放不下,又买了一些软盘。作为交换条件,对方则提出来,要我们把他们的一套正版软件给买下带走。

图片来自网络,我的是5.25'磁盘的载体

那套软件放在他们玻璃橱窗的最顶层,看上去包装很正规,很高大上。后来拿回家拆开一看,的确也是。里面至少有10张5.25寸软盘,以及好几本手册。手册有厚有薄,软件看起来是全英文的,我后来安装过。说明书里面有部分具备中文,也有一些是全英文的。

软件名字叫做——Visual C++ 1.0。可惜现在肯定已经随着老房子的清空和出售而毁损了,不然还可以跟大舅的小黑白电视机一样当作收藏品。


初三的我,跟小学六年级一样地幸运。奥数竞赛再一次得奖,这次是省二等奖。复赛的时候一共就三道题。按照同学的说法,我上来就把第一道题做了,看看第二道题有点难,翻过来把第三道题也做了,剩下的时间研究了一下第二道题,然后把它也给解决了。

物理竞赛我也捞了个三等奖。最后顺利晋升本校高中部,并且在高中两个重点班的「选秀」环节被第一顺位选走。我只记得中考数学150分拿了143.5,其它科目都忘记了,想来也不会差。

我们班也成功逆袭。原来的「重点班」,不少学生都「跳槽」去了所谓更好的「一三八」。我们班的成绩紧随其后,原来班上那帮顽劣之徒,成了本校高中一年级的骨干力量,后来高中各个班的「尖子生」,都是从我们这个初中班级开枝散叶出去的。

高中的时候,我的成绩开始「泯然众人」,班主任一直有点遗憾。她总觉得是我高一的时候一次体育课后的意外导致的,被「摔傻了」。
当时是一次下午的体育课后,体育老师让我们把一些体育用品搬进仓库。我们几个学生干完活以后,看到仓库中有跳高用的垫子,于是就自己在那边跳着玩。我大概是一次脚勾到了什么东西,摔到了垫子外面,接下来的记忆就是被人扶着坐起来,中间的一段已经失忆了。

现在看来应该还只是轻微的脑震荡。送去了急救中心,班主任的老公是那里的医生,看过之后判断无大碍,于是叫了出租车让同学把我背回了家。同学虎背熊腰,我瘦瘦小小。他家里也有电脑,到了家以后他看到我的「玩具」,心里有了数,后来三年我们就成为了玩伴。
我用了一大叠软盘把《仙剑奇侠传》给了他,他也给了我《风尘三侠之金箭使者》和《妖魔道》。不过他后来热衷于玩格斗类游戏,大学以后我们就分道扬镳了。

图片来自网络,我好不容易才想起游戏名字

游戏多了,自然不需要自己来写。因此程序开发的事情,算是渐渐撂下了。


高一的时候,学校开了电脑课。电教老师找我恢复过两次误删的文件,他居然连undelete都不会用,我有点惊讶。剩下的时间,我就在他电脑上玩《FIFA94》和《波斯王子》。

其实初一的时候,开过电脑兴趣班。当时我有参加。这位电教老师发了一份考卷让大家做,当作入门测试。我一看,这不就是我上学期刚考过的奥数之类的东西吗?卷子是油印的,不是很清楚,老师边念题,就要学生马上做,没给什么思考时间。大多数学生都跟不上,但我发现自己做起来比之前六年级时又简单了许多,时间还真是够用。旁边一个家伙在抄我的答案,后来他大学期间去创业开了个网站卖旗袍,卖了很多年。

初一时候学校的机器,好像都还不是x86。有一台CEC-I,数量是不少,机器感觉还没我小学好。到了高中时候,机器换过一批了。有80286出现,那些非x86的机器已经看不到了。我不知道他们上课学了些啥,反正我都在老师办公室里面呆着,没怎么上过课。

后来期末考试,电教老师来发完考卷之后,班主任直接让我上台带着大家把题目做掉了。还冲我挤眼睛,问我说感觉好哇?搞得我很尴尬。题目的确是简单,对我而言是很基础的IT知识,里面我只有「五笔输入法」的那道题不会做,其余都有把握拿满分。

图片由Google Gemini生成

高一下半学期,电教老师让我去参加一个比赛。编程相关的,一开始说还有一个高二的学长也要参加。老师为我俩指点了一些要复习的内容。那个学长据说只是自己在家瞎玩玩,估计期末考试题目还是会做的,竞赛就不行了。后来他知难而退,竞赛最后就只有我一个人去。

比赛记得是去的三中,老师带我去。难度不小,跟小学那次不可同日而语,四道题我可能只做出来一道半,拿了个三等奖。碰上初中那帮从我们学校「跳槽」过去的「尖子生」在三中玩Novell网,我这种自学成才的也只能干瞪眼,不知道他们在干什么。


这台电脑后来加了两根内存,组了一个四槽8MB内存。过了几年,内存突然便宜了不少,有一次我跟我爸去逛电脑城,发现已经是这个价钱了,随手就买回来了。
再后来,硬件也没有升级过了。不过我在高中最后冲刺的时期,踏上了一块全新的领域。
我们买了一台Modem,外猫,33.6k。当时已经有了56k的Modem,但我机器UART不行,波特率有限,权衡了一下之后没有买。

图片来自网络,外观有点像,大差不差

再次佩服我爸妈胆子大,竟然让一个高三学生去上网。尽管一开始是FIDO网,但那也是很容易就陷进去的东西。现在哪个家长敢在学生高三的时候突然把手机给他让他随便玩?
话又说回来,可能我那个时候的成绩也比较能让人放心,以至于他们相信我能hold得住。可能我从高中开始成绩一直比较「稳」吧。

虽然一开始去了城市的FIDO里面逛了一阵子,不过后来我其实更多地是固定呆在一个BBS「GAMEBOY」上玩,相当于在泡一个论坛。站长Xiang Tao是一个公司里面的运维,用自己家的电话线路开了个拨号BBS,后来又加了一条线路。高中的时候,城市里面家用固定电话开始普及了,资费也算还好,一小时还不到10块钱。于是每天用Telix拨上去收数据,然后用BlueWave慢慢看慢慢回,就成了我回家以后做的第一件事情。当然,睡觉之前还会再做一次。这样做,电话费其实要不了多少,后来拨号上Internet就不一样了。

这个BBS比较有特色,是当时国内唯一的一个具有模拟股指期货的BBS。开发者Huang Hui是个程序员,写了个插件让BBS有了这个功能。站长也在玩,还有几个成年人。我们这种小屁孩就在里面瞎胡闹,灌水什么的。

感谢PCem,感谢WinImage

不过我也贡献了一些资源到站内, 有一些科幻小说,还因此混了个科幻区的版主当当。在学校里面我是从来不想担任任何职务的,但班主任强迫我当「数学课代表」,结果导致我的数学成绩在高中阶段并不出色,我也开始讨厌数学。高考时勉强考了个110多,不算出色。

高考完了以后,GAMEBOY站长从报纸上看到了录取信息,向我祝贺。川大(当时还叫四川联合大学)计算机系软件专业,录取名单第一个。随后我也收到了录取通知书。

去上大学,也就意味着我与GAMEBOY告别了。不过在学校有更大的BBS「蓝色星空」。去上大学前的那个暑假的一个夜晚,我在WPS上敲下了一篇长文,祭奠我的青春。那可能是我最后一次密集使用双拼双音了。后来我把密码忘了,加密的文档再也解不开。传说有万能密码,可我再也未能找回。

2025-06-30

Win11不能访问匿名SMB了?

要跟同事交换大量的数据,还涉及到手机。Samba还是比较靠谱的选择。无论是Android还是iPhone都可以访问,用我一位手机开发组的同事的话来讲:「这比网盘好用多了」。

然而有一位同事说SMB目录打不开,过去一看,发现他电脑已经升级到Win11了,自己还浑然不觉,有点惊奇这种神经是怎么炼成的。

Win11默认不准匿名SMB了,大概是出于某些「安全性」方面的考虑。但是我又不想去加上用户名/密码,于是琢磨了一下怎么把他的电脑给「降级」。这帮家伙Windows更新都停掉不装的,一个匿名SMB又怎么了?

组策略中改一改

先运行gpedit.msc,然后「计算机配置」->「管理模板」->「网络」->「Lanman工作站」,把「启用不安全的来宾登录」从「未配置」改为「启用」,就可以了。
有的人说还要改另外一处地方。反正我只改这一处就OK了。

2025-06-27

不明白的变化快

图片由Google Gemini生成

在我看来,所谓「盲盒」,其实是我们当年玩剩下的东西。

我小学低年级的时候,比较喜欢「糖关刀」。看别人的手艺是一回事,但更「刺激」的是不知道自己这一把能转到什么。偶尔看见有人转到龙、花篮,甚至大龙,附近的小孩都会围过来「开眼界」,羡慕的目光都能把龙头融化掉。

大龙,3D立体的,后来我没见过有这种手艺的艺人,大概已经失传了吧。
我转到过一次大龙,刚好是早上上学的时候。我妈和我一起蹲在路边吃,吃不过来,拦住其他同学要他们帮忙吃,闹得全校都知道了。

大约到了高一点的年纪,路边摊有开始卖一种零食。贵得出奇,要一块钱一盒。里面除了一颗糖,还有一个小玩具。最值钱的是一把小的左轮手枪,花一块钱买一把,还算是赚到。另外的就是纯亏。但大家都想着能赌一把,于是送了不少钱给老板。
我也跟风买过一次,当然,没什么好运气。我也心疼钱,于是此事到此作罢。一套整个包下来可以稳「中奖」,一共十六盒,老板开价15元。在我看来那就是冤大头了。

再后来,有了游戏机摊,然后是游戏机厅,就没那些东西什么事了。

昨天在Lawson门口等人,看到两个女青年在柜台前指指点点,店员上前询问,才知道想买福彩,刮刮乐。
公司年会的时候,也发过一张。「玩法」很复杂,然而终究还是一早就印好的。我在心里暗自嘀咕:有没有奖,不是早就知道么?看来红十字会也还是有新韭菜的。

应该怎么说当今这种现象呢?
可能是因为年轻人太有钱了吧。难怪无论银行还是京东都在怂恿客户把积分拿去抽奖。这其实是一种回收货币的方式嘛,与萝格营地基德先生的生意是一回事啊。

但他们其实也没钱,至少没什么钱,不够多。大概只是单纯地想赌吧?
我有个同事,曾经说过:赚钱的生意,不外乎「吃喝嫖赌毒」。说得或许也有三分道理。如果能激发人类的原始欲望,自己又能跳出五毒之外,兴许就能发财吧。
不过他到底还是没有能发财。说到底,还是普通人。普通人,啥好事不用排队呢?

世界变了吗?也许变了许多,也许其实也没变。

愿天下普通人都能抢到心仪的Labubu。

2025-06-21

昨天会更好

看标题就知道,是老生常谈的怀旧节目。

太太单位刚刚通过了一次「监管部门」的突击检查,安排集体散心游。儿子刚好也考完了试,不知道分数多少,反正回家就抄起了手机,还约了三五「狐朋狗友」假期来家里玩游戏。太太怕儿子宅出味来,给儿子也报了名,于是今天同去,剩我一个闲散人员赋闲在家。

把猫和自己关在儿子房间,开了空调,清理了他的写字台,摆上笔记本。放在Dropbox里面打算周末加班完成的工作不想去做,去买了打二折的《死亡空间》,也不想玩,一个人看着六天的日记大纲发呆。
想起了许久没听过音乐,从厨房找来了太太闲置已久的蓝牙音箱,擦拭干净,试了一下还能开机,于是打开YouTube Music,搜了一个「1980年代华语流行金曲」就开始听了起来。

边听边开始想流泪。我到底是戴了什么滤镜,那些已经早已成为过去的岁月,怎么感觉如此美好?

图片来自维基百科,尺寸方面有所调整

曾经跟着发姐的录像回味过1985版《明天会更好》。不少人我都不确切认识,只听过歌,没见过人,特别是没见过当年的脸,看过字幕才能知道是谁。那个唱腔如此熟悉的人,我都不敢认,但的确是费玉清,小哥。实在没想到年轻时他是那个样子。 
人们的发型现在看来很扎眼,但是又很熟悉。是记忆中爸爸妈妈的发型,是马盖先和李麦克他们的发型,也是那个曾经虽然问题遍地但也朝气蓬勃的年代的影子。

上半年已经给儿子看完了《龙珠》全部剧集,现在开始看《圣斗士星矢》。我现在看了都感觉有点尴尬,他倒是没觉得,可能因为刚好到了接近中二的年龄。《天空战记》我当年还没看完过,至少没有看完的印象,晚些时候打算借机补上。
现在的小孩,除了垃圾短视频,还能看什么?《斗罗大陆》?现在就算是《Doraemon》都没有当年的好看了。尽管画质和技术改进得不是一星半点,但如果要我去看,还不如半途杀了我。

或许,这就是前浪为什么需要死在沙滩上。像我这样的人死光了,就不会有人觉得今不如昔了。「厚古薄今的老顽固」将成为我的注脚,本文的标题也就完全可以改上一改。尽管我觉得经典是永不磨灭的,但是人类是在越变越蠢。过不了多久,无论是我还是经典,都会形神俱灭,历史和属于我的记忆也都将被改写。

这是人类的不幸,也将是大幸。

2025-06-20

只是冒个泡

最近一两个星期,非常忙,也非常不开心。主要是工作上的事情,顺带自己的个人生活也受到了影响。

「一系列的意外事件,引爆了一些潜伏已久的矛盾。」

至少在我看来,工作上的事情,可以作出如上的陈述。在这些事件中,我都不是当事人,但是也不可避免地受到了影响。加上我在公司的风评,和展现给众人看到的那些「性格」特质,又使得我被当作倒苦水的对象、潜在的调停者,最后收下了不少的负面情绪。忙就算了,还要闹得不开心,以至于数度在脑海中模拟过G力扑面而来的感觉。

事关公司,很多事情没法细说。但是大环境的恶化,在我看来是决定性的推动因素。坏掉的零件当然是可以看得到的东西,但是越来越大的压力,才是导致整个系统出现问题的关键。不管是气压、血压,还是心理压力,都是这个道理。
在此也郑重提醒各位,高血压一定要按时吃药,定期检查。我的眼压,也应该是如此。

本周还没正常吃过一顿午饭,写日记的事情就更不提了,已经压了一周的份量。每天记录日记,而且动辄数千字,压力确实不小。但是仍然不想随意放弃这个已经坚持了三年多的习惯。或者说,坚持写日记压力大,要放弃它,压力更大。每天都在感慨和反省自己的记忆力越来越差,更加不甘心自己的人生就这样溜走,Fade away在时间的迷雾之中。

图片来自Google Gemini

在此先冒个泡。我的事情,自然会去解决。太太也好,儿子也好,同事们也是,也都有自己的事情需要去解决。或简单或困难,但不往前走也是不行的,不然不知道会被水冲到什么地方,下场可能更惨。且看看我能「扛」到什么时候吧。

2025-06-05

每天都应该是哀悼日

图片来自网络

人还真是的,以前怎么没想到可以用这种方法呢?

这是一种态度。对于我而言,想说的更多,慢慢来吧。如果事情没有得到解决,那么每一天都应该是哀悼日。

黑白色,就这么说定了。没有什么理由去高兴。活在养猪场有什么可高兴的?26层楼,周围的正常人都被臭跑了。猪还可以拉屎,学生连屎都不让拉了。

每天写一点,每天一点改变。如此活着还能干什么呢?从一点一滴做起吧。

2025-06-04

今天不穿黑色什么时候穿

去年这个时候干了什么?不太记得了。但是身上的衣服,也是黑色。
今天不穿黑色,什么时候穿?

图片来自网络

港人已经连纪念都不被允许了。镇压速度之快,令我咋舌。但其实也并不意外。当初的镇压,也不过就是一夜,或者几天而已。

但我不相信数十万人一转眼就已经不见。或许去国怀乡,或许转入地下,但他们还没有死绝。使出的这一招,看似严厉无比,实则打草惊了蛇。并不是看轻它们的智商,确实也只能做到这种地步了。

星星之火,我是已经传下去了。很高兴得知世上没有时光机器,而且所有人终难逃一死。

咱们走着瞧。

2025-05-28

决定跳楼的围棋少年

图片来自网络,与本文基本无关

前些天就听闻有围棋少年跳楼,据说是因为不堪忍受父亲的打骂。心里很不舒服,但近年来跳楼的年轻人很多,隔壁小区不久前也跳了一位,所以也只是忧伤+1,没有Shock。

昨天看到了比较完整的报道(参见中国数字时代《真实故事计划|9岁围棋少年坠亡背后,嗜血的鸡娃》),接触到了更详细的细节以后,更加难过了。作为一个与围棋有一定渊源的人,或许是勾起了心中的一些回忆,也联想到一些杂七杂八的事情,一起说说吧。

跳楼 vs 坠楼

媒体报道都用「坠楼」而非「跳楼」来叙述这件事情,在我看来有点「温情脉脉」。这个词打了引号,在我看来不是个褒义词,简单来说就是有些装13。
媒体或许有它们的考量,去问AI,会给到你一整套的说法,在这里我就不再鹦鹉学舌了。但是,我们平时在线下环境中谈论起这类事件,都会很明确地说「跳楼」。「坠楼」这种文绉绉的用法,老百姓们是不屑于去用的。如果你们这些「主流」媒体还像这样玩弄文字游戏,那只会离人民群众越来越远。
何况,在我们看来,跳了就是跳了,就是主动跳的,当事人就是不想活了。

另外,AI给出的说法,是说如果用「跳」就会让人觉得是死者不够坚强。这一点我必须要反驳一下。
没有人会觉得是死者不够坚强。AI你多虑了,给AI喂出这种语料的人们,你们也多虑了。没有人会因为不够坚强而去死。死者之所以选择去死,是因为另一种选择比死还可怕。如果不想再去面对比死还可怕的事情,也被称作「不够坚强」的话,那当我什么话也没说。

虎爸 / 虎妈

曾经有同事,被我形容为「虎爸」。不过他的自辩还算有意思:「你有没有想过,虎爸之所以成为虎爸,是为了让虎妈不那么焦虑?」。

我承认,我并不太了解他太太。不过从各种听到的传闻看来,他太太的确比他鸡娃鸡得还要厉害。或许这是某种「控辩交易」一类的东西?双方差距太大,于是有「中间人」站出来调停,各让一步?

三角形,是一种比较稳定的形状,此话不假。
相比之下,小男孩的母亲被家暴打得离了婚,注定了后面的悲剧。但这绝非他母亲的错。
某些大国领导人,如果想要废掉三权分立,建议先想想地上的灰是什么味道。

《请回答1988》

在韩剧《请回答1988》里面,也有一位围棋少年,崔泽六段。崔泽的爸爸,一开始反倒是不想他去下棋。在朱宏鑫看来,这样的爸爸只应天上有。

当然,崔泽应该是职业六段,朱宏鑫是刚冲上业余六段。业余棋手和职业棋手之间的实力,天壤之别,判若云泥。硬要比,也没什么好比的。但这并不是重点。

都说韩国卷,比中国还卷,所以生育率世界最低。不过在逼儿子下围棋这件事情上,还是中国赢了。

卷 / 年轻人 / 债

问起周围的人,都觉得,以前自己上学的那个年代,没有现在来得「卷」。

我当年没有感受到卷,这不奇怪。但其他人也都觉得,现在的孩子,太苦了。可见并不是我的问题。
不过话虽这样说,他们仍然让孩子们去上各种补习班,然后对着考试成绩长吁短叹,操心着中考分流的事情,睡不着觉。

我有时候在想,现在的年轻人是不是在还我们那个年代欠的「卷」债?当年我们不够卷,于是现在就要卷在他们身上?

上一封跳楼小女孩的遗书,我还历历在目。而还有的小孩,没有自己跳楼,却居然被打死了。
活该以后小孩越来越少。现在是个什么样的黑暗年代啊?

学围棋

我也学过围棋。起码学了两年,可能有三年或四年。具体开始时间记不太清了,应该是二年级的时候,到了五年级停了。

我印象很深刻的是,停止学围棋之后,有一次我帮棋校的老师带一个什么东西过去,老师非要留我下一盘,完了以后发现我水平也没什么长进,有点叹气。问起我现在的情况,我说我六年级,老师有点气愤,说我妈妈骗他,去年就跟他说我毕业班了学业紧张才要放弃学围棋。

打是没有因为下围棋而挨过的,我挨的打基本都是因为不吃饭。不过刚开始学的时候,容易被人带节奏。别人瞎下,我也跟着瞎下。父亲在旁边观战,知道我下得不行,下课后批评过我。我事后也有点纳闷,明明自己是会下棋的,怎么一开局就跟着低年级的傻小子在天元那边咬起来了呢?

我的棋力有过一次飞跃,大概就是学了一年左右的时候。可能也是因为年龄到了,自己去看了一些棋谱。特别喜欢武宫正树,感觉他的「大模样」可以做到「不战而屈人之兵」,于是学了起来。你来打架,我不理你,围自己的地去。嘿嘿,脱个先。

掌握了这个门道,自然就比那些还没章法的愣头青高了一层。一时间在内部联赛的胜率也稳定了起来,因为总有那么一拨人死活赢不过我嘛。但再过了一阵子,大家都长大了,就又有后起之秀出现,我又没法赢人家,被行业所淘汰,实属情理之中。

我自己也知道自己不是那棵葱。围棋说起来是一种技术活儿,但实际上是与对手这个人之间的争斗。「与人斗」这种事情我天性就不喜欢,可见不是伟大领袖的材料。后来不管是踢足球还是打星际,我的这个弱点都体现得淋漓尽致。对手攻过来,我就让他一步,这还怎么赢棋?遇到棋力相差太多的对手,我还可以靠着高出一级的境界去围地轻松取胜,遇到棋力相当的要跟我绞杀,我最后就会输。父母大概也看出来了,早早止损了事。

与老师下完最后一盘棋,准备离开的时候,我听见老师们在聊天,说最近有个小孩特别厉害,将来会有出息。他不是我们棋校的学生,名字初听上去有点奇怪,好像叫什么「古力」。那一年他可能也就是9岁吧。

真的是以前的年代更好么?

渊源

我跟围棋,也真的算是有一些渊源的。

一开始我是去少年宫学围棋,后来没多久转到棋校。市中区(当年还叫市中区,现在叫渝中区了)棋校位于大田湾那一块地方,那也是以前重庆的体育产业最集中的地方,想必姚夏也有同感。

棋校建在山坡上,希尔顿和文化宫之间。山坡下是一些防空洞,当年都没人,铁门紧锁,现在全是火锅店。去棋校的途中,有一个依山势而建的人行天桥,天桥上常年有人摆FC游戏机摊。因此,在去棋校的来回路上,我必定把多余的时间花在看别人玩游戏上面。

那个时候我真的还小,懂的东西不多,现在还记得的东西也不多了。不过父母带我去入学的时候,跟老师攀谈的一些片段,还有些许印象。

说起来,重庆也是小,至少那个时候还小。同城的围棋圈子就更小了,古力的例子就可见一斑。我记得他们谈着谈着,突然就开始攀起了亲戚。貌似我大伯妈有一位长辈还是兄长来着,之前也是棋校的,感觉也是老师,跟现在的老师们算是旧识。

我的围棋老师们,竟然不知道那位旧识后来的下落。我父母说到这里有点黯然,说他在文革期间「被整死了」。

所谓的「被整死了」,大抵就是跟老舍一样的下场。自我了断,或者被打死。老师们听到这里,也都有些唏嘘。两位俱是如此。
说起两位恩师,我还记得他们的相貌。主事的那位,面相挺和蔼的。另一位偶尔代课,干干瘦瘦,总是戴顶鸭舌帽。和我下告别棋的,就是后者。两位到现在应该都已经与旧识在九泉之下重逢了。

重庆的文革是很激烈的。世人知道的是「武斗」,「815」和「反倒底」打仗。死的人不少,沙坪公园现在都还有一片墓群。我们每次春游秋游经过,老师都有点神神秘秘,路过的时候都轻言轻语。
然而,会死人的原因,不只有打仗而已。

现在回想起来,当时二年级的我,懂的东西也不少。

「以前」的年代,貌似也没有多好。

班禅

这些天还有一个小孩,据说从6岁开始就下落不明。
为什么倒霉的都是小孩?大人的事情,你们大人自己去解决,为什么总是要为难小孩?

2025-05-23

品牌机的问题

图片来自网络,与本文无关

最近在整理《我的电脑史》系列,其它Blog也多涉及到DIY相关的内容,颇有一些感触。

买电脑(特指非笔记本的台式个人电脑),到底是买品牌机,还是组装机,这个问题对于每个来找DIYer咨询买电脑的人,都曾经面对过。

我以前得出了一个心得:如果是不熟的人,不是至亲,那就让对方去买品牌机好了。如果是自己或身边的人,那还是自己动手买配件组装比较好。

这个认识,到现在也没有变过,已经有二十来年了。按理说,时移世易,沧海桑田,这些年品牌机的性价比也提升了不少,配置灵活度也有了,不应该还是这个情况才对。
我也纳闷,但是情况就是这么个情况。那些真正的品牌机厂商(实际上是组装机的不算)提供的机型,我还真没有看得上眼的。


品牌机最大的问题,有两个,然后合在一起产生效果。

第一:配置不合理。

传统的品牌机厂商推出的机型,往往都把CPU人为地堆得很高,不合理的高。我个人的理解是因为大众只认识CPU品牌,也以为CPU档次代表了整机的档次。

但是,CPU高,对应的内存和硬盘却不够好。高端的CPU只配置一个入门级别的内存,比如i7的CPU配个16GB内存,这是要玩啥?我五年前给i3都是32GB起步了。

硬盘也是抠抠搜搜,无论是容量还是性能都不肯给到足够。现在这种年代,2TB的SSD又不是什么多贵的稀罕物,上个4TB也不嫌多,偏偏只给512GB,再配块SMR的HDD,我看了都想骂人。

三大件也就算了,扩展性也不好。为了SIZE订制小机箱小主板,扩展槽给得很少。这些也都不提了。CPU规格是挺高,散热器用个盒装自带的,这又算什么?
水冷有风险,我理解,配个塔式热管风冷有什么不可以吗?觉得RGB很LOW,可以换风扇嘛。这么好的CPU,睿频冲上去就撞墙,有啥意思?

我一直这样认为,现在也还这样认为:这些传统的品牌机厂商把整机配置做得这么恶心,只是为了让你觉得「需要掏更多的钱买更好的电脑」而已。

第二:性价比太低。

品牌机,当然有质量控制、售后服务、品牌附加值等溢价因素在里面,价格相比自己买配件组装,肯定是会高一些的。说实话,我觉得明码标价就行,这些因素能拆开单独买自然好,非要打包在一起,也不是不行。

但是,如果你觉得内存太小,或者硬盘不够大,想要升个级,或者在买机器的时候就想选个好一点的配置,那加上去的价钱,可不是线性的。
苹果在这方面体现得尤其明显。您要更大的存储空间?没问题,但是多出来的钱是一级比一级宰得狠。对于那些存了东西不备份不删的人而言,这就是一种「税」。

说起来,品牌机厂商会说,我的内存是经过了兼容性检测的,有质量保证。
这话放在二十几年前可能在理,但现在主板等配件厂商也会给出内存的兼容性测试报告,很难让人相信品牌机厂商会以及有必要再去作额外的检测。而付了钱后收到的内存条看起来其实还不如自己去买的,无论外观还是参数。价格却要平白贵出不少,让人很难认同。

如果一次性把这些钱都付掉,配置合理一些,以后不用再换再升级,可能也就忍气吞声挨一刀算了。但是这些品牌机的配置又偏偏就不会让你合意。内存小了是吧?加钱换下个等级,你又会觉得CPU性能溢出了。总之就是不会让人舒舒服服地。像当初440BX那样的傻事情,厂商是不会再干第二次了。

这也是为什么说,这两个问题会合在一起产生效果。没好的配置,于是就得多掏钱,掏得比你应该掏的要多不少。用一阵子觉得不爽,却又不能升级,或者升级花钱巨多,于是只好买台新的。

厂商笑嘻嘻。


话说回来,这篇Blog有点像是梦呓。现在还有人用台式机么?拜托!他们连Pad都不用了。

2025-05-13

编程随想:招投标那些事

图片来自网络,与本文无关

说起来,我们公司最近也投了个标,也中了。

这个项目跟了好几年,从疫情期间就开始跟。开头的时候有120万的预算,最后招标的时候砍得只剩45万。然后甲方还提出来要「分期付款」,4:3:3。作为一个开发人员,我参与的招投标项目不算多,有点孤陋寡闻,这回算是头一次听到这种事情,也算是长了见识。

后来到实施的时候又出了问题。甲方提出来服务器能不能不买,用租用公有云服务器的方式来代替。这事也听得我一愣。要知道公有云基本上「三年」是一个大致的盈亏平衡点。只租一年或者两年,一般是比自己买服务器要省钱的。如果租到了第三年,对于租用者而言大概率就不合算了。

不过最后听说甲方还是掏钱买了服务器,据说配置还挺高的。闹得我现在也琢磨不清楚这甲方到底是有钱还是没钱?或许端看花的是谁的钱吧?对了,这个甲方也是个大专院校。

在这个项目里面,我只是顾问身份,基本没怎么参与,个中曲直我也懒得去理清楚,各位权且当个故事听着吧。


然后我还想起一个事。同样地,没有立场,没有观点,只是一个事情,讲出来供大家参考一下。

2019年成立子公司的时候,IT运营和成本核算也是独立进行。总公司那边买办公电脑,都是买Dell品牌机。已经2019年了,买到的还是HDD的配置。我反正是看不上眼,后来都加装/换装了SSD。

到了2023年,我自己的办公电脑要汰换,也是去买了配件自己来组装了一台新的电脑。旧电脑是2015年申请的,8年时间用下来,已经没有升级潜力了。

当时买了一堆东西,CPU/散热器/主板/内存/机箱/电源/SSD。我发单子申请,采购让行政人员负责。全部流程走下来都很顺畅。组装过程也很顺利,毕竟我和另一位IT同事都是二十几年经验的DIYer了。这台电脑现在用得也很趁手,价格不足四千,整体性能远超公司那些同事的所谓13/14代i7的Dell品牌机。花自己的钱,办自己的事,就是这样,又好又省。

后来搬回来,总公司来交接固定资产。我看到资产表上没有我这台电脑,倒是有登记一个CPU,就是我这台电脑用的型号。
资产登记不是我负责的,行政人员是个小姑娘,不是太聪明的样子。我当时让她采购的这一大堆东西,我怀疑她就只看懂了CPU,然后写了上去。

前来交接的人员,也不太聪明的样子。来过至少两拨,可能还不止两拨,每一拨我都费了不少口舌跟他们说明这个事情。看他们眼神,还是没懂的样子,一副「算了我也懒得管了就这样吧」的表情。搞得我一度有点怀疑是不是自己的沟通能力出了问题。

现下愈发觉得各方面都懂的「通才」甚是难得。有幸遇见过几位,不是丁克就是少子,不由得对人类的未来愈发地「看好」。

话说回来,一个CPU,当然也值不了75万,不然发姐的AMD股票肯定得涨到天上去。

2025-05-12

我的电脑史(二)——80386SX-33

最早接触x86的PC,是在小学的电脑兴趣班里面。
校长看第一届电脑夏令营办得很成功,于是又追加了投资。CEC-I的总数增加到了五六台,还有一台有机箱的电脑。显示屏、机箱、键盘各自分离,而且有内置的软驱,看起来很「高大上」,现在想来,应该是一台IBM PC兼容机。
之前负责夏令营的两位女老师,现在已经难堪重任了。取而代之的是学校里另一位老师的儿子,大概是大学生。有空的时候就来带带这个班,讲点「堆栈」之类我们都听不懂的东西。那台PC机,就成了他的专用电脑。

图片来自网络,非当时的照片

开机需要插入软盘,有一天我们趁他不在自己折腾进了OS。印象比较深刻的是,软驱读盘像在弹吉他。还有就是「A>」的提示符是从屏幕下方「升」起来的,带着残影。
当时我还不会DOS,连Apple DOS也没玩过。进了OS,我们这帮小孩就不会了。大学生发现后倒也友善,看到我们对这个有兴趣,还表演了几个游戏给我们玩。TestDrive我第一次就是在这里摸到的,还有打伞兵,以及机器人大战等等。

图片来自网络,这已经是彩显的CGA效果了,当时是绿显

这台机器因为我接触不多,再加上平时它一般都是用一块绸布给盖起来的,在记忆中一直比较神秘。
记得软驱只有一台,估计不是高密度盘,因为我记得载入TestDrive会提示换盘。这样看来应该也没有硬盘。
显示器是绿色的单色显示器,不过应该有灰度。显卡类型起码有CGA,否则这些游戏应该跑不起来。声音就是靠机箱喇叭了,现在想想有点简陋,当时TestDrive那开场音乐还是叫得挺欢的。


初中的时候,爸妈从(另外一个)中学的一位电教老师那边,替我搞了一台组装机。

之前是我大伯先去搞了一台PC/AT兼容机自己放在家里玩,也是找这个老师。有两部5.25英寸高密度软驱,卧式机箱,不过CPU不是80286。东西的来路不是很清楚,肯定不是品牌机。我很新鲜,也很眼馋,经常往他家里跑。爸妈看我这样,就问大伯电脑哪里来的,线就是这样牵上的。

后来想想,这不就是最早的垃圾佬兼二手电脑贩子嘛。不过当时并没有规范的电脑市场,所有的配件基本上要不就是单位采购,要不就是私下流转。对方的中学电脑课教师身份,应该是派了「大用场」。

我爸妈为了这台电脑大概花了三四千,可能更多。现在回想起来,也是一笔不小的数字,恐怕是一个人的年收入。后来我去找那位「卖」电脑给我们的老师,找他hdcopy一些软件的时候,他向我打听过我家的经济情况。当得知我爸妈从事汽车维修行业并且自己开店的时候,他有喃喃自语道「修车的有钱」。

我怀疑他是从这台电脑上狠赚了一笔,心中略微有愧,需要一些事情来让自己良心上过得去。别的不说,给我的那块40MB的硬盘,上面满是坏道。物理坏道,低级格式化也修不好的那种。换成现在的我,是下不去手赚这钱的。
还好坏道都集中在后1/5的位置,刚好FAT16最大也只支持32MB的分区,所以正好分成两个区,D盘就扔在那边不去动它了。


无论如何,我有了自己的第一台真正意义上的个人电脑。

这台电脑的CPU是80386/SX,主频可以在25MHz和33MHz之间切换。前面板有个切换开关,还有一把小锁用来锁住机箱不让开启。

图片来自网络,非原图,只能说大致差不多

2MB的板载内存,64KB一片的集成电路(DIP封装),半节AAA电池大小。在主板上铺了一大片,大家可以自己算算。

相比之下,我大伯的电脑只有1MB内存。因此我可以接触EMS和XMS,能玩HIMEM和EMM386(以及DOS4GW),而他不能。当然他后来也去升级过了。

一台5.25' 1.2MB的软驱,再加一台3.5' 1.44MB的软驱,当时算是比较不错的配置了。
机箱比较窄小。40MB的硬盘分了两个区,坏道都放在了第二个区。硬盘通过IDE线和一块「多功能卡」接入主板。嗯,现在大概没人知道「多功能卡」这个名词了。

显示器是一台「双频单显」,这个名词现在去Google的话得打引号才能看到靠谱的内容。灰色的,不是绿显。支持Mono、CGA和HGA。最后这个大力神的分辨率一度给我带来了一些「惊喜」。当然,显示器得跟显卡配套,后来换彩显的时候都一起换下来了。


当时还没有CD-ROM,所以数据唯一的入口只有靠软盘。我前前后后买了十几盒的5.25' 1.2MB软盘,以及几乎差不多数量的3.5' 1.44MB软盘。有一些是别的品牌,不过大部分都是3M的防霉盘,气味非常特别。
里面的软件,一些来自于那位老师,一些来自我大伯,还有一些是从《电脑报》报社搞到。最后还有一些是来自于邮寄目录,最有名的是《楚汉之争》。

图片来自网络,我买了起码一打

PC上没有固化的中文系统了,需要外挂。现在的UCDOS一开始我并没有,不过有一张自带压缩字库的WPS(话说我觉得那个压缩字库还挺好看的),很省内存和磁盘。后来搞到了CCDOS,再后来有了天汇和中国龙。我还是很喜欢天汇这种小巧的中文系统,很容易就带走了。而中国龙则「贡献」出了自己的字库。

需要用到中文系统的时候不是太多,主要是用WPS写文章。我录入过大约半本书的《伦敦浩劫》,算是用来练习指法和双拼双音的输入。到后期愈发纯熟,输入速度越来越快,只可惜双拼现在已经差不多全忘了。
练习指法的TT更是常客,用的时候PC喇叭挺吵的。不过后来我到了大学也还是时不时练一练。很多同学也在用,大概老师有推荐,这是后话。

那个时候我掌握的一项「核心技术」,就是「腾挪」内存。用HIMEM把640KB常规内存给节省出来,印象中我最多能挤出600零几K的常规内存出来。这是从MSDOS 5.0开始的事情,没多久我就从3.31升级到了5.0,也因此接触到了QBASIC,后来大多也都是用的它。正经的Quick Basic我听说可以编译出EXE,一直很向往,但到了很后面才用上,那个时候我已经不稀罕它了。

由于软件来源不足,到了后期我又开始了自己编程。因为有了BASICA、GWBASIC,后来还有了QBASIC。我开始接触到了结构化编程。相对于小学/初一时期,水平可以说又上了一个台阶,不过现在看来也还是在洼地里面扑腾而已。

有点后悔当时没能学学C。Turbo C 我那个时候是有的,但是一听到「C语言」大家都觉得是大学里面才学的东西。而且听说是两代半的语言,于是我也怕难不敢去碰。
后来那位老师有一次「介绍」我去帮他一位同事(或朋友?)打过半天的工,帮他写代码,用GWBASIC写。大概是一个教学用途的工控项目,用BASIC写也不是不行,有点勉强。那位大叔大概懂硬件,向串口发数据之类的东西他写,UI就让我来写。写了一个下午,给了我10元算辛苦费吧。我也不知道这算啥?我是被卖了吗?


这台电脑后来经历了一些硬件上的升级。回想起来大概是94-95年。

换了彩色显示器,直接上了一块Trident TVGA 9000卡,显存有1MB。我后来找遍资料都只找到512KB显存的TVGA 9000,所以很疑惑这个型号是否正确。但用起来的确没有问题,BIOS里面也是那样写的。问了AI说有,那就有吧。

硬盘也去换了一块420MB的硬盘。40MB那块的坏道实在是多,容量也有限。这两样加起来又是两三千块。回想起来,那些年我父母的确算是「赚得动」。

图片来自网络,这块硬盘后来换掉了

换硬盘的时候有一段小插曲:为了砍价,我最后提出来,要用硬盘把他们那边的「正版」软件给copy一些带走。胃口太大,选了一大堆,硬盘放不下,最后还是用了一些软盘。


有了更大的硬盘之后,我开始接触一些更高档的软件了。中文系统不再局限于压缩字库的WPS(话说我觉得那个压缩字库还挺好看的)。也用上了Windows 3.1,以及稍后的中文版3.2。随后也接触到了Microsoft Word 6.0 for Windows,以及Visual Basic 6.0。

还记得当时安装Windows 3.1要用6张软盘,后来也有5张盘的版本。我最后一次去找那位老师用hdcopy复制Windows 3.1的时候,撞上房间里面有另外一位年轻的女性,鬓发有点散乱。老师言语间颇有些惋惜和责怪的意味。我当时确是有点不识趣,后来才回过味来,此后我就没再去找过他。

我有的时候还挺怀念单色显示器,后来即使用上了彩显,也偶尔把它换回来怀一下旧。其实在双频单显的时候,我就已经用上Windows了。在HGA模式下,Windows虽然只有单色,但分辨率其实算是够用了。「切换显示模式」这个术语对于现在的PC使用者应该已经相当陌生了吧?一些台湾出品的CAI软体很喜欢用HGA这个显示模式,我也因此学习了不少繁体字和台湾的IT用语,以及IT知识。

再后来,它就有点缺乏升级潜力了。内存不足是最大的问题,虽然有SIP的扩展口,但国内那种内存几乎找不到。去升级的时候,电脑商家也表示这种内存已经过时,不建议我继续在上面投入。

CPU也是焊死在主板上的,拔不下来也换不掉。主频比较低,假32位,还没有FPU。如果要去搞一块80387加上去,也觉得是浪费。我大伯倒是后来把他那台电脑升级成了80386DX+80387。

本来我这台电脑就可以算作以过时淘汰的电脑配件组装起来的,所以也没有必要硬为它续命了。上高中前我换「多媒体」电脑的时候,就把它的主要配件一次性都换掉了,那就算是另外新买了台电脑了。所以放在下个故事里面继续说它。

2025-05-06

统计学诚不我欺

图片来自网络,与本文无关

无意中逛到某知名「反贼」论坛,又看到有人在说「订婚强奸案」男方没有强奸。附和者众。
已经就这个没什么必要讨论的话题写过一篇Blog,感觉有点浪费了,所以这次就不多展开了。

然后那个地方还有一个讨论热点,就是所谓中国人在日本厕所「偷电」的事情。风向不太一样,不过跳针的人也不少。

我是有点吃惊。为什么?他们没有作为一个人类而言最基本的判断吗?墙内没见过世面的人是多的,我已见怪不怪。然而这些人能突破重重封锁在此发言,无法归罪于信息闭塞,也绝不是能力不足。

看起来,这个世界上,总有那么一群人(甚至可能是大多数),要么蠢,要么坏。还有一小撮人,又蠢又坏。这不是他们的错,他们本该就是如此。

要说统计学,那是真的灵验。不论到什么地方,总是有成比例的这种人出现。管你墙外还是墙内,粉红还是反贼,概莫能外。
立场并不能代表道德,学历也不能代表智慧,是我肤浅幼稚了。

不过,如此说来,我倒是也捡回了一些信心。数学不会骗我:世界上总是会有另外那一小撮人的存在。无论他们被消声成什么样,无论他们被分隔在什么天涯海角,他们总是存在的。这个世界,或许还没有那么糟糕。

文奇啊,真的会有陆黛拉吗?

2025-04-18

果然,这是他们的世界

最近很少关注所谓「时事」。莫名其妙地看到「订婚强奸案」的公告和评论,真的感到莫名其妙。什么时候这种事情也能吵起来了?
未经同意的性行为,可不就是强奸么?不要说什么订没订婚,就是拿了证结了婚,那也是强奸。而且不管是男人还是女人,都是强奸。都2025年了,这它妈还需要讨论?!

不需要讨论。但是需要「吵」。

图片来自ChatGPT

越来越同意发姐的那个观点:「这个世界不是我们的世界,是他们的世界。」

是的,这个世界是他们的世界。我以前有那种幻觉,只是因为他们没有手机,上不了网。
曾经的我,以为大家的价值观在大方向上大致是趋近的。毕竟这么多的文学和影视作品,起码反映了大家的某种美好的愿望。至少能看得出来大家都想be like什么,以及对于什么是bad,还是有基本的认同的。
直到他们买得起手机了,移动「互联网」也普及了,我才猛然发现,自己错得离谱。

以上是我的猜测。又或许,很多人原本就是坏人,以前还想着be nice一下,装一下好人。后来发现好人没好报,而世界却唾手可得,因此不想再「装」下去了?
我应该对人类如此失望吗?拱手让出这个世界,还给它原本的主人们。天会因此更蓝吗?估计不会。生活会因此更好更轻松吗?短期可能会,长期可能不会。但是人总不能每天都活在抑郁中,想得却不可得,还不如不去想。

其实在发姐说这个话以前,我也想到了这个道理。大概比她早了几天吧。应该是一种巧合,不过这种感悟,大家都是因为看到了某些社会事件才萌发的,多半也算不上什么真正的巧合。
以上可能让人觉得我这是菁英主义。不,我不是菁英。菁英可能还会去想如何来改变这个世界,我才不想。
人生苦短,而我已经行了半程。是时候let it be了。

2025-04-11

我的电脑史(一)——中华学习机

我的第一台PC,也就是「个人电脑」,说起来,是一台「中华学习机」。
是的,就是那台CPU是6502的山寨Apple II机器。

图片来自网络,并非我的CEC-I

第一次接触,是在小学五年级时参加的「电脑夏令营」。

我所在的小学,并不出名,规模不大,也没有什么特色。但校长的确相当的敢创敢干,办学思路前卫。她抓住了90年代初的「微机」热潮,在《电脑报》创刊前一年就买了两台中华学习机,开办了一个电脑夏令营。五、六年级的不少学生都参加了,我也是其中一个。

当时的两位带队老师,也是仅仅被派去少年宫「进修」了几天,就回来赶鸭子上架,面对一大群什么都不知道的小学生,拿着手上的纸片就教我们敲起了程序。我还记得她们说BASIC有17种「语句」。我也不知道这说法对不对,反正「17」这个数字实际上没有任何意义。

我看到的第一个程序是用一个双层循环print出来一个*号组成的三角形。老师们写出程序(包括行号),然后让每个学生都去录入了一遍并运行。当时这两台中华学习机都没有软驱,所以程序关机就清空。

第一天夏令营结束以后,我留下来打扫清洁。偷偷按了一下上下左右方向键,心想这东西肯定可以用来玩游戏。
到了夏令营的最后一天,老师拿出两盘卡带(一看就知道是FC卡带),说是学生家长捐助的,打算最后让大家过过瘾。但她们怎么也插不进去,最后只好作罢。


六年级的时候,学校组织了一个电脑兴趣班。
作为全校IQ担当的我,先被教自然的朱老师捷足先登给「抢」到了他的围棋兴趣班。朱老师二话不说,摆开棋盘就弈上了,随后教导主任带着电脑班的老师过来抢人。
两边一度剑拔弩张,最后朱老师还是认输了。就这样,我和一群女生一起,被送去了电脑兴趣班,接受现在看来目的性挺强的「教育」。

当时学校可能是接到了上级指示,让我们学LOGO。

LOGO的海龟,图片来自网络

LOGO的长处其实是字词处理,以及有真正的函数和过程。这些都挺好,BASIC欠缺这些,所以LOGO的确是当时更好一些的选择。起码嵌套和递归这种东西,BASIC里面不会接触到。

但实际上我们却是从绘图指令学起。在我看来,这种做法看似对培养小朋友的兴趣有好处,但最后其实是害了他们。如果仅仅对绘图指令乐在其中的话,就是太小看了Programming了。这一个兴趣班的学员,最后真正有在编程的,就我一个。其他人甚至都没去读理科。


六年级下半学期,父母不知道是听了老师的劝说,还是自己觉得我在这方面可能有天赋。总之某一天,就带我去重百六楼,买了一台中华学习机,接在家里电视机上让我玩了起来。

好巧不巧,买的时候,刚好被我班主任给撞见了。第二天这消息就在班里宣扬开来,这下子大家都知道了。

现在想想,父母那个时候还真是胆子挺大的。一台中华学习机当时要950元。1992年的950元,即使是在城市居民那里也是不小的一笔金额,起码是好几个月的工资。
我还记得国企改制,我妈的单位被解散的时候。她最后一天去财务那边拿到的遣散费也就是1000元。她脸上的表情让我印象深刻,只是不知道如何形容。那叠「大团结」是旧钞,捏在手里好大一把,起码我以前是没见过这么多钱的。

图片来自网络

小学时候的学费是免的,杂费还得缴。一个学年大概也就是50至70。后来到了高年级的时候,涨到了一两百,最后一个学年大概是两百多。要一下子花接近一千块钱,去买一个不知道将来会不会有用的东西,还真是需要一些魄力。


我已经不太记得我是怎么开始自学编程的了。

可能我父母一开始只是觉得学校的电脑没法天天用,所以买一台给我,看看我在这方面有没有戏。
他们对我应该还是有蛮多期待的。还没上小学就送去学画画,结果毫不成器。上了小学又去学围棋,然而个性不喜与人争斗,学是学到些东西,比赛名次却一直不好。看看没有希望,五年级借口升学压力把围棋班停了。刚消停下来,然后又是学电脑。
只不过这次没让我跟谁去学,全凭我自己高兴,瞎折腾。

但这玩意儿又不是「小霸王学习机」,不自己写程序的话并不好玩。估计一开始我的使用频率并不高,也就是跟着学校教的自己随便玩玩。

图片来自网络,但酷似我当年那本

随机附了两本书,算是产品手册。讲软件那本被我翻得滚瓜烂熟,硬件那本就完全啃不动。一跳到汇编,我就只能随便乱敲键盘刷屏玩,看着满屏的MOV/ADD/SUB好玩,权当学英语。
后期BASIC玩得没劲了,我也想去下功夫去学一下汇编。DOS3.3里面电视机跳舞小人的动画效率让我羡慕不已。但还是不行,学不进去。以至于很多年以后,父亲都觉得我是「软件强,硬件弱」的类型。

还好我平时喜欢自己跑去书店「淘宝」,后来就陆续买了一些计算机相关的书籍。COBOL和Fortran的书我都买过,淘的旧书,能闻到霉味那种。价格很便宜,可惜看不懂,主要也因为没法实践。而谭浩强的《BASIC趣味程序选》,刚好就是我可以上手去试的内容。


在这里,我的记忆貌似开始出现了一些偏差。
我在「小升初」的暑假里面,生了一场「大病」,住院住了大半个月。病友都是成年人,聊的事情都很无聊。(还打算考我「四人帮」是哪四个。这种题能难住我?去公园路上的坦克履带印子我也是见识过的。)
因此那段时间,我经常在病床上捧着书看,在脑子里面跑程序。这段记忆给我的印象很深。

图片来自网络,就是这套,1-3册

不过,我自学BASIC肯定是更早的事情。因为六年级的时候,区教委搞计算机编程竞赛。当学校老师兴冲冲地领着我们电脑兴趣班全体「学员」去参赛的时候,才惊讶地发现考题全是BASIC的。

很自然地,其他人都缴了白卷,只有我还能瞎写上一些。估计那次被这样坑到的学校不会少,所以一个三等奖最后也就不意外地落到了我手上。

当然,这件事情被我后来拿了省奥数一等奖的事件给盖过去了。那一年我可能是鸿运高照,甚至连「地震知识竞赛」都莫名其妙得了个三等奖。母亲之前一度还担心我「小升初」的时候体测会遇到麻烦,但随着这些奖项把「分」一加,保送重点中学的事情也就没有什么好担心的了。
而且后来据说我短跑也还发挥得不错,总之全校师生对此都很服气。校长也就放心地把那个总是找我麻烦的体育老师给请回家休息去了。


六年级的时候,学校订阅了《电脑报》。我自己则从93年就开始买合订本,回家自己看。有一些属于运维或DIY的东西,也有一些是编程的内容。

到了初中,随着我写的程序越来越长,「一关机就没」成了主要的矛盾。没有持久存储,写的程序无法有任何的积累,也就不可能有多复杂。虽然尝试过用磁带进行存储,但不知道是录音机不符合规范,还是磁带质量不好,总之没能成功。换了TDK的原装磁带也一样,估计还是录音机的问题吧。

好在没过多久,大约初一下期的时候,父母从深圳打工归来,带了一台软驱给我。
我简直如获至宝。Floppy Disk Drive!从此我就可以保存自己的程序了。能读写360KB双面双密度5.25英寸软磁盘,不过驱动器是单面读写的,需要手工翻面。以及,我学会了自己给软盘剪口子。
随机还附带一张DOS 3.3的盘,另外他们还买了一张磁头清洁盘。后者我用得特别节省,一直用到软驱时代结束。

图片来自网络

在那个时期,家用游戏机渐渐普及,FC甚至已经开始式微,换MD开始崛起了。只是照着书抄点程序,已经无法满足我的娱乐需求了。书上的什么「模拟城邦」、「导弹打飞机」之类的简单游戏,玩一会儿就没兴趣了。出出数学题之类的程序也很没意思,既没复杂度,也不好玩。程序都是自己写的,里面什么逻辑自己全清楚,写完后自己就不想再玩了。

而且实话实说,当时书上那些程序的Bug也挺多的。我甚至尝试帮忙修正了一些。其中有一个说是用来规划北京地铁交通线路的程序,应该算是书上最复杂的程序。一开始根本跑不起来,后来我也把它修修改改调试通过了。然而连地铁是什么东西我都没见过,计算机算法我也还没真正入门,只能说把阻碍运行的语法错误给修正了,业务逻辑改得对不对,天知道。结果也不知道怎么算是对的,到最后也只能看着好玩而已。

那个年代,没有网络,也没有光盘。获取现成的Apple II游戏的难度也不小。于是接下来,我开始了自己「发明创造」的过程。

记得自己写过一个「拳击」的小游戏,在「低分辨率图形模式」下模仿了掌机上的一个小游戏。效果还不错,在Apple II的架构下居然有了「实时」响应的感觉。上下左右方向键终于派上了正式的用场。不过自己一个人玩有点无聊,加了暗器什么的,也埋了彩蛋和秘技,但总归是自嗨。

还有一个模拟炒股票的中文游戏,算是我那个时候的巅峰之作了。虽然价格涨跌的算法只是简单地交给随机数决定,但持仓、委托、成交什么的已经有了。而且我还加入了RPG元素,有对话,有菜单。最后也就是这个游戏,把这台电脑的机能给榨干了。


标志着这台「中华学习机」应该退役的事件,是有一天,我正在边玩边改进我的炒股游戏,尝试加入不同玩家角色的功能,突然发现屏幕上方开始出现不规律的一排排白点,并且随着程序的运行,开始向下蔓延,「破坏」了我游戏原本的显示内容。

我开始翻找手册,并在《电脑报》合订本上寻找帮助。最后很不情愿地发现并承认,这台电脑的内存不够用了。

图片来自网络

是的,中华学习机的ROM内固化了中文BASIC,其字符串缓冲区放在用于显示中文的内存区域不远处。一旦字符串太多,发生溢出,就有可能破坏屏幕上的中文显示。
偏偏我这个游戏是一个「文字」类型的游戏,而且为了搞菜单和对话那些花里胡哨的效果,堆了不少中文字符串上去。

解决方案有两个:一个是加内存,一个是换电脑。可是这机器的内存扩展板卡似乎很不好找。而且在1994年的时候,《电脑报》上的Apple II内容已经不是很多了。我大伯也买了一台PC/XT,我经常跑去玩,还在中华学习机上自己模仿MS-DOS写了一个命令行shell。在这个时候去给它加内存,听上去有些傻。

于是后来我就有了一台真正的PC,那是另一个故事了。


这台CEC-I的结局,和我那台雅达利几乎如出一辙。

某天我小舅说想把它拿去用用,估计是表妹缠着父母要买电脑。我把束之高阁的它请了出来,通上电打算看看情况。但显示部分总是倾斜且闪烁的,行频和场频无论如何就是调不对。

图片来自网络

表妹家里人一看,就打了退堂鼓。最后应该也是只能把它扔掉了。早知道现在会进博物馆,可能不会如此处理。