Loading...
💼 工作记录
std::string origin_response_body = "test_content"; const int body_len = origin_response_body.length(); std::unique_ptr<char[]> response_body(new char[body_len]); memcpy(response_body.get(), origin_response_body.c_str(), body_len); std::string body = response_body.get();
这段代码是有隐患的,但是却比较难发现。因为如果这个数组中最后一位不是\0 结束符,构造string的过程中就会一直按照地址递增访问内存直到找到结束符为止,这个过程会导致内存异常访问等问题
\0
但在真实环境中,可能不一定会导致崩溃,因为当我们new[body_len] 申请一段内存的时候,由于内存对齐以及操作系统的差异性,分配的大小会大于申请的大小,因此在body_len 位置的内存很可能就是结束符。 C++Tips
最近的两个需求尝试以 “面向测试开发”来开发。所谓“面向测试开发”,或者“测试驱动开发”,我理解就是先去写UT,先去在UT里面写好调用的函数和预期的接口。每写一个EXPECT,对应去实现类的功能,这样写完UT,功能也开发完成了,保证了模块的质量。
通过这种方式发现写代码的阻力更小一些。之前写代码脑子里可能混杂多个接口的设计想法,通过UT,每次只增加一个新的case,实现该case,能够“小步快走”,会更不容易出错。
这对项目代码质量是有比较大的要求的,如果是一个新的独立模块,还好一些,可以从零开始写UT,如果这个模块有依赖外部模块,需要mock或者外部模块也具有可测性。
如果是在已有的功能模块里新增新的功能,这就要求已有模块可测性非常强才行。历史的很多代码都没有UT,这也是困难之一吧。
“当你排除一切不可能的情况,剩下的,不管多难以置信,那都是事实。”
工作中排查bug的时候很像是侦探🕵️寻找真相。简单的bug可能很快从代码review就能发现,比如空指针等。这周遇到了一个bug ,简单来说,
线上的问题是在A操作过程中,出现了B操作,导致后续C操作的时候直接崩溃。所以线上会有概率非常小的情况下崩溃。
这里写代码的时候没有考虑到这个异步过程,同时B操作或者C操作中应该增加判断,如果A操作后,就是空操作。
💼 工作记录 对于客户端开发来说,crash是性能/稳定性中最重要的指标之一,因为crash意味着功能不可用。
最近工作上引入了两个功能crash,被折腾了一番,有一个感想:“对任何改动的上线一定要测试”。这里“测试”根据不同情况有不同程度测试,其中最基本的测试是确认功能是否能跑起来,而不仅仅是编译通过即可。
可能你会说,提代码肯定需要测试啊。但是有些场景,可能就会偷懒,比如加一行日志,或者简单增加一个指针判空,或者简单调整了两行代码的位置,就因为“匆忙”,并且过度自信,就没有测试,甚至基本测试都没有!
上述的场景可能是本地的分支开发别的功能,突然反馈过来的一个bugfix,为了本地不切分支,而选择在网页端简单提交bugfix的代码
这些看上去“人畜无害”的代码,其实往往暗藏“玄机”。比如日志打印调用了一个指针的函数,却没有检查指针是否为空,误以为指针一定不为空,尤其是在编写宏的情况,更容易忽视。
除了这些改动极小的代码,一些不是特别大的改动也可能引入意想不到的问题。举个例子,移动了某一个observer 事件发送的位置,在模块owner看来可能没什么关系,但可能外部利用了这个observer,并且依赖了某种时序,一旦某两行代码调整了顺序就可能导致异常。
这里有一个调整两行代码顺序导致问题的例子:
.... std::string str = "1234"; SomeStrToInt(str); SomeClassConstruct class (std::move(str));
其中第3行和第4行的位置调整就会导致异常,而这个问题非常难以发现,因为最开始的这段代码可能比较久远,甚至不是自己写的,因此就会忽视后面对string move的调用。
有经验的程序员是否可以避免上述问题,足够细心的条件下一些简单的错误可以被避免,比如上面的std::move 顺序问题。但是对于更复杂的场景忽略掉也是可以被理解的,更不用说,粗心是一种很容易犯的问题。
因此黑盒测试的必要性是无法被白盒测试替代,白盒测试100%覆盖是一个理想而不及的目标,受限于代码可测性、ut质量等等因素。意味着一定有不少场景是UT无法覆盖的部分,对于大型项目尤其如此。(尽管如此,UT重要性仍然是不言而喻)
我个人的一点想法是对任何提交MR做以下两点检查:
上面的两点check不能避免所有的问题,但可以拦截大部分很低级的问题(事实很问题都来自低级的错误),除此之外,成熟的工程会一般会有完备的稳定性流程来拦截更复杂的问题。
💼 工作记录 下班后如非必要,最好是不要打开与工作相关的任何网站、软件。只是简单的看看消息也会很快的让人感觉到“班味”。这对于放松心情是非常有害的,同时也不利于第二天更有精神的工作,长此以往会导致越来越强的厌倦。
字节中有「字节圈」,类似内网的“微博”程序。之前很长一段时间会经常的刷,虽然这些内容都是素不相识,但也是打发时间了,不仅如此我还会频繁的去看飞书上一些免打扰群的消息,即使那些消息和我并没什么关系。后来我发现这种状态是非常有害的。即,我已经下班了,但是我的状态并没有完全下班,是祈求用忙碌、麻木的工作错觉来填补自己无事可做而已。这就是为什么上述说的如非必要,一定不要查看任何与工作相关的任何信息。
平均来说,越少的工作时间确实是可以有更好的效率的。尝试了一段时间强制自己更早下班,会发现为了要更早下班,自己会强迫自己提高效率完成今天的事情。就好似是一种dealline。(当然特殊情况除外,但要尽量的少)。
所以,如果一个公司强制员工更早的下班,同时以工作成果为绩效导向,我觉得是会让员工自发的寻找效率更高的方式的。
💼 工作记录 职场中应该会有很多时候会受到挑战。比如工作流程(开发/需求流程等等)是否合规,技术方案是否合理,考虑全面,代码是否严谨等。要学会受到挑战的时候不要急的把自己择出去,这样的心态会让自己会急躁的为自己辩解。但事实上很多时候不需要辩解,只需要解释,所以要缓一缓,如果是通讯工具沟通,不要急于回复,理清思路再回。面对面沟通,也可以停顿、思考片刻后给出回答,切勿自乱阵脚,有理也说不清。
📝 每日记录 今天北京下大雪了,这可真算得上是鹅毛大雪!下班的时候,走在路上,雪特别的厚,踩在上面还有咯吱咯吱的声音,非常治愈
补充一则记录:春节前,第一次点这家的烤串,点了一个烤猪蹄,特别好吃,送过来的时候温度也不错,猪蹄也挺嫩的。复工回来的时候,又点了一次烤串,发现很一般了。相似的经历是之前的一家炸鸡店,第一次点手枪腿,真的是太好吃了,手枪腿里还有汁水,第二次点怎么这么一般。不太清楚是丧失了新鲜感,还是确实餐品质变差了!
PS:已经高强度上班三天了!PSS:明早还要早起赶文档!!
📝 每日记录 从4月末开始,每天熬夜到1点半,身体每况愈下,以至于再也不能不重视了。
身边新冠第二波的人也变多了。倒是一直没有发烧过,因此也不知道自己有没有阳过,不过其他的症状从1月放开后持续不断。 腰痛、咽喉不舒服,胸闷,呼吸不畅,口腔溃疡等等几乎不间断轮番上阵。
这半个月来,从新需求启动忙到焦头烂额。但是身体永远是第一位,所以下班后不再想任何工作的事情了。
💼 工作记录 关于工作,从0启动了一个需求,所以涉及到大量的方案设计与评审的工作。在这里体会最深的一点是:过度设计是一切的根源。很多优秀的技术架构是需要演变的,而不是一步到位。
在代码设计中,有很多不错的设计模式和设计原则,以便代码便于扩展,容易测试。但是在实际的设计中,很容易从一个具体的需求想要设计一种“极其通用”的设计方式。模块越通用带来的复杂度就越高,因为需要兼顾更多的场景。
所以不如变成两个模块来做,而不是想要一个模块非常灵活、通用的完成所有需求。
尤其是在刚刚接触一些设计原则的时候,我们想要在代码的所有地方去应用,比如单一职责,开闭原则、MVC等等。可能会让一个没有那么复杂的需求拆分成很多独立的模块,导致这些模块之间需要还需要通信,或者函数需要不断的通过层级来偷传,这无疑增加了复杂度。
当然好的代码需要一定的设计,这其中的权衡是需要在不断的实践中掌握的。
💼 工作记录 「输出论据比论点更有价值」最近在写绩效评价相关的,有一个感受就是情绪或者主观评价都是比较虚的。所以才会有所谓的「夸夸宝典」,这些主观评价就像是一个结论或是论点,必须需要有论据支撑才有价值。当然这个场景下论据与论点结合更适合。
这个观点同样适用于其他的事情上。比如与别人沟通上,即使你要和别人吵架,提出你的不满,你可以数落对方做的不好的地方,让你烦、讨厌的事情,但最好减少去输出主观的评价或情绪。比如直接人身攻击,大骂对方没素质等等。输出论据,大家也能心知肚明知道你的不满了。而情绪和观点是可能会变的,过几天你可能会因为一时冲动输出太多情绪而后悔,但是事实是不会变的,这不会让自己觉得“冲动了”。
💼 工作记录 写文档和设计代码有一些相似之处。一个比较复杂的话题想要展开,就好比设计一个复杂功能的类。全部代码写在一个文件中当然可以,就会导致单文件代码行数太多,阅读起来很费劲。如果我们能更好的封装与模块化代码,单个类的功能就会更清晰。
同理,写一篇复杂话题的文章,也可以有类设计的思想,先介绍最基础的部分,然后基于这个基础会有多个分支展开(子类继承)。多篇文章之间环环相扣,而每篇文章也不会太长,阅读压力也不大。
我也看到过有很长文章从头到尾讲一个复杂话题的,写的也特别的好,这个就好比仍然是多个类,只不过放到同一个文件里面而已。
💼 工作记录 当我们CR代码的时候,我们在review什么。 其实很难和代码作者本身理解程度来review代码逻辑的正确性,而是应该review一些常见的代码写法的问题。比如指针是否有空指针风险,函数本身的设计(如输入参数在输出参数前面)等等代码规范的问题。
除此之外,如果对代码需求的细节了解更多,可以review 一些代码的逻辑,比如改动代码是否会影响之前的调用流程。
CR中几乎做不到的是判断每个变量计算的值是否符合预期,这个需要代码作者本身来保证。
正常来说,别人给你CR的意见都是你自己每次自己CR的时候应该发现的,所以提高代码质量的一个好方法就是记下每次别人给自己的评论,并反思为什么自己在检查代码的时候没有发现(还是自己并没有检查代码)?
📝 每日记录 工作如果获取不到持续的成就感和进步,是很容易陷入一种痛苦、迷茫、虚无的感受的。尤其是如果一直工作没办法按照排期完成,一直后延、后延、后延,只是无尽的麻烦... 💼 工作记录
💼 工作记录 因为国庆大部分时间都在忙工作,节后的几天又继续加班到挺晚才回来,快晚上十点回来后,因为天气变冷,挑选一些过冬东西,然后就已经到凌晨了。这种连轴转到今天早上的时候,闹钟都叫不醒我。整个人特别的困,与此同时也会让我面对环境更加敏感脆弱。所以,过大的压力、不好的作息这些会更让人容易emo,陷入不好的情绪当中。
今天晚上吃完晚饭就回来了,调节一下。工作的本质,不是为了ld工作,而是给自己工作,提高自己的技能,能挣钱才是目标。不要让自己陷入无尽的社交困境里面,找准靶心,调整节奏,健康作息。
最近快入冬,身边感冒越来越多,流感也来了,永远是只有身体不舒服的时候才知道健康多重要,
加载失败!尝试重新加载
来自南部的一个小城市,个性不张扬,讨厌随波逐流。
💼 工作记录 职场中应该会有很多时候会受到挑战。比如工作流程(开发/需求流程等等)是否合规,技术方案是否合理,考虑全面,代码是否严谨等。要学会受到挑战的时候不要急的把自己择出去,这样的心态会让...
此条为私密说说,仅发布者可见
💼 工作记录
这段代码是有隐患的,但是却比较难发现。因为如果这个数组中最后一位不是
\0
结束符,构造string的过程中就会一直按照地址递增访问内存直到找到结束符为止,这个过程会导致内存异常访问等问题但在真实环境中,可能不一定会导致崩溃,因为当我们new[body_len] 申请一段内存的时候,由于内存对齐以及操作系统的差异性,分配的大小会大于申请的大小,因此在body_len 位置的内存很可能就是结束符。 C++Tips
1:
std::unique_ptr<char[]> response_body(new char[body_len + 1]); // 分配空间 这种非常重要 且常见
memcpy(response_body.get(), origin_response_body.c_str(), body_len + 1); // 拷贝完整字符串
2:动态分配 在设计、开发阶段是要被严格管控的, 至少做到1、在详细设计阶段就要体现在文档里。2、边界检查 3、测试覆盖
好像发的不对,检查了下,基本没有临时的动态分配、
我这里简化了,memcpy的逻辑是另一个函数的事情,函数参数就是char*,所以外部必须传入一个分配好空间的字符指针进去
这个是sdk的代码,个人觉得c++项目而且没有那么高的性能要求下,尽量可以不用char*指针,同时这个sdk内部保存的就是string,但是函数参数是char*导致string->char*->string 这样诡异的逻辑出现
💼 工作记录
最近的两个需求尝试以 “面向测试开发”来开发。所谓“面向测试开发”,或者“测试驱动开发”,我理解就是先去写UT,先去在UT里面写好调用的函数和预期的接口。每写一个EXPECT,对应去实现类的功能,这样写完UT,功能也开发完成了,保证了模块的质量。
通过这种方式发现写代码的阻力更小一些。之前写代码脑子里可能混杂多个接口的设计想法,通过UT,每次只增加一个新的case,实现该case,能够“小步快走”,会更不容易出错。
这对项目代码质量是有比较大的要求的,如果是一个新的独立模块,还好一些,可以从零开始写UT,如果这个模块有依赖外部模块,需要mock或者外部模块也具有可测性。
如果是在已有的功能模块里新增新的功能,这就要求已有模块可测性非常强才行。历史的很多代码都没有UT,这也是困难之一吧。
💼 工作记录
“当你排除一切不可能的情况,剩下的,不管多难以置信,那都是事实。”
工作中排查bug的时候很像是侦探🕵️寻找真相。简单的bug可能很快从代码review就能发现,比如空指针等。这周遇到了一个bug ,简单来说,
线上的问题是在A操作过程中,出现了B操作,导致后续C操作的时候直接崩溃。所以线上会有概率非常小的情况下崩溃。
这里写代码的时候没有考虑到这个异步过程,同时B操作或者C操作中应该增加判断,如果A操作后,就是空操作。
💼 工作记录 对于客户端开发来说,crash是性能/稳定性中最重要的指标之一,因为crash意味着功能不可用。
最近工作上引入了两个功能crash,被折腾了一番,有一个感想:“对任何改动的上线一定要测试”。这里“测试”根据不同情况有不同程度测试,其中最基本的测试是确认功能是否能跑起来,而不仅仅是编译通过即可。
可能你会说,提代码肯定需要测试啊。但是有些场景,可能就会偷懒,比如加一行日志,或者简单增加一个指针判空,或者简单调整了两行代码的位置,就因为“匆忙”,并且过度自信,就没有测试,甚至基本测试都没有!
这些看上去“人畜无害”的代码,其实往往暗藏“玄机”。比如日志打印调用了一个指针的函数,却没有检查指针是否为空,误以为指针一定不为空,尤其是在编写宏的情况,更容易忽视。
除了这些改动极小的代码,一些不是特别大的改动也可能引入意想不到的问题。举个例子,移动了某一个observer 事件发送的位置,在模块owner看来可能没什么关系,但可能外部利用了这个observer,并且依赖了某种时序,一旦某两行代码调整了顺序就可能导致异常。
这里有一个调整两行代码顺序导致问题的例子:
其中第3行和第4行的位置调整就会导致异常,而这个问题非常难以发现,因为最开始的这段代码可能比较久远,甚至不是自己写的,因此就会忽视后面对string move的调用。
有经验的程序员是否可以避免上述问题,足够细心的条件下一些简单的错误可以被避免,比如上面的std::move 顺序问题。但是对于更复杂的场景忽略掉也是可以被理解的,更不用说,粗心是一种很容易犯的问题。
因此黑盒测试的必要性是无法被白盒测试替代,白盒测试100%覆盖是一个理想而不及的目标,受限于代码可测性、ut质量等等因素。意味着一定有不少场景是UT无法覆盖的部分,对于大型项目尤其如此。(尽管如此,UT重要性仍然是不言而喻)
我个人的一点想法是对任何提交MR做以下两点检查:
上面的两点check不能避免所有的问题,但可以拦截大部分很低级的问题(事实很问题都来自低级的错误),除此之外,成熟的工程会一般会有完备的稳定性流程来拦截更复杂的问题。
冒烟测试 你们这边是开发自测的吗 还是有专门的团队、工具做冒烟测试的呢?
crash我们一般很多会遇到,在冒烟测试拦截的居多, 然后取dump文件,分析定位,建BUGid 解决bug 回顾总结 写rootcase。
各个环节也是有的,比较头疼是写「回顾总结」文档,感觉团队里有些太重文档,文档写了具体原因还要一遍遍的修改细节,绘制图之类
💼 工作记录 下班后如非必要,最好是不要打开与工作相关的任何网站、软件。只是简单的看看消息也会很快的让人感觉到“班味”。这对于放松心情是非常有害的,同时也不利于第二天更有精神的工作,长此以往会导致越来越强的厌倦。
字节中有「字节圈」,类似内网的“微博”程序。之前很长一段时间会经常的刷,虽然这些内容都是素不相识,但也是打发时间了,不仅如此我还会频繁的去看飞书上一些免打扰群的消息,即使那些消息和我并没什么关系。后来我发现这种状态是非常有害的。即,我已经下班了,但是我的状态并没有完全下班,是祈求用忙碌、麻木的工作错觉来填补自己无事可做而已。这就是为什么上述说的如非必要,一定不要查看任何与工作相关的任何信息。
平均来说,越少的工作时间确实是可以有更好的效率的。尝试了一段时间强制自己更早下班,会发现为了要更早下班,自己会强迫自己提高效率完成今天的事情。就好似是一种dealline。(当然特殊情况除外,但要尽量的少)。
所以,如果一个公司强制员工更早的下班,同时以工作成果为绩效导向,我觉得是会让员工自发的寻找效率更高的方式的。
💼 工作记录 职场中应该会有很多时候会受到挑战。比如工作流程(开发/需求流程等等)是否合规,技术方案是否合理,考虑全面,代码是否严谨等。要学会受到挑战的时候不要急的把自己择出去,这样的心态会让自己会急躁的为自己辩解。但事实上很多时候不需要辩解,只需要解释,所以要缓一缓,如果是通讯工具沟通,不要急于回复,理清思路再回。面对面沟通,也可以停顿、思考片刻后给出回答,切勿自乱阵脚,有理也说不清。
📝 每日记录 今天北京下大雪了,这可真算得上是鹅毛大雪!下班的时候,走在路上,雪特别的厚,踩在上面还有咯吱咯吱的声音,非常治愈
补充一则记录:春节前,第一次点这家的烤串,点了一个烤猪蹄,特别好吃,送过来的时候温度也不错,猪蹄也挺嫩的。复工回来的时候,又点了一次烤串,发现很一般了。相似的经历是之前的一家炸鸡店,第一次点手枪腿,真的是太好吃了,手枪腿里还有汁水,第二次点怎么这么一般。不太清楚是丧失了新鲜感,还是确实餐品质变差了!
PS:已经高强度上班三天了!
PSS:明早还要早起赶文档!!
📝 每日记录 从4月末开始,每天熬夜到1点半,身体每况愈下,以至于再也不能不重视了。
身边新冠第二波的人也变多了。倒是一直没有发烧过,因此也不知道自己有没有阳过,不过其他的症状从1月放开后持续不断。 腰痛、咽喉不舒服,胸闷,呼吸不畅,口腔溃疡等等几乎不间断轮番上阵。
这半个月来,从新需求启动忙到焦头烂额。但是身体永远是第一位,所以下班后不再想任何工作的事情了。
💼 工作记录 关于工作,从0启动了一个需求,所以涉及到大量的方案设计与评审的工作。在这里体会最深的一点是:过度设计是一切的根源。很多优秀的技术架构是需要演变的,而不是一步到位。
在代码设计中,有很多不错的设计模式和设计原则,以便代码便于扩展,容易测试。但是在实际的设计中,很容易从一个具体的需求想要设计一种“极其通用”的设计方式。模块越通用带来的复杂度就越高,因为需要兼顾更多的场景。
所以不如变成两个模块来做,而不是想要一个模块非常灵活、通用的完成所有需求。
尤其是在刚刚接触一些设计原则的时候,我们想要在代码的所有地方去应用,比如单一职责,开闭原则、MVC等等。可能会让一个没有那么复杂的需求拆分成很多独立的模块,导致这些模块之间需要还需要通信,或者函数需要不断的通过层级来偷传,这无疑增加了复杂度。
当然好的代码需要一定的设计,这其中的权衡是需要在不断的实践中掌握的。
啊这我都以为新冠已经沦为过去式了
💼 工作记录 「输出论据比论点更有价值」最近在写绩效评价相关的,有一个感受就是情绪或者主观评价都是比较虚的。所以才会有所谓的「夸夸宝典」,这些主观评价就像是一个结论或是论点,必须需要有论据支撑才有价值。当然这个场景下论据与论点结合更适合。
这个观点同样适用于其他的事情上。比如与别人沟通上,即使你要和别人吵架,提出你的不满,你可以数落对方做的不好的地方,让你烦、讨厌的事情,但最好减少去输出主观的评价或情绪。比如直接人身攻击,大骂对方没素质等等。输出论据,大家也能心知肚明知道你的不满了。而情绪和观点是可能会变的,过几天你可能会因为一时冲动输出太多情绪而后悔,但是事实是不会变的,这不会让自己觉得“冲动了”。
💼 工作记录 写文档和设计代码有一些相似之处。一个比较复杂的话题想要展开,就好比设计一个复杂功能的类。全部代码写在一个文件中当然可以,就会导致单文件代码行数太多,阅读起来很费劲。如果我们能更好的封装与模块化代码,单个类的功能就会更清晰。
同理,写一篇复杂话题的文章,也可以有类设计的思想,先介绍最基础的部分,然后基于这个基础会有多个分支展开(子类继承)。多篇文章之间环环相扣,而每篇文章也不会太长,阅读压力也不大。
我也看到过有很长文章从头到尾讲一个复杂话题的,写的也特别的好,这个就好比仍然是多个类,只不过放到同一个文件里面而已。
💼 工作记录 当我们CR代码的时候,我们在review什么。 其实很难和代码作者本身理解程度来review代码逻辑的正确性,而是应该review一些常见的代码写法的问题。比如指针是否有空指针风险,函数本身的设计(如输入参数在输出参数前面)等等代码规范的问题。
除此之外,如果对代码需求的细节了解更多,可以review 一些代码的逻辑,比如改动代码是否会影响之前的调用流程。
CR中几乎做不到的是判断每个变量计算的值是否符合预期,这个需要代码作者本身来保证。
正常来说,别人给你CR的意见都是你自己每次自己CR的时候应该发现的,所以提高代码质量的一个好方法就是记下每次别人给自己的评论,并反思为什么自己在检查代码的时候没有发现(还是自己并没有检查代码)?
📝 每日记录 工作如果获取不到持续的成就感和进步,是很容易陷入一种痛苦、迷茫、虚无的感受的。尤其是如果一直工作没办法按照排期完成,一直后延、后延、后延,只是无尽的麻烦... 💼 工作记录
事情堆积的,一件又一件,没有尽头的感觉...
💼 工作记录 因为国庆大部分时间都在忙工作,节后的几天又继续加班到挺晚才回来,快晚上十点回来后,因为天气变冷,挑选一些过冬东西,然后就已经到凌晨了。这种连轴转到今天早上的时候,闹钟都叫不醒我。整个人特别的困,与此同时也会让我面对环境更加敏感脆弱。所以,过大的压力、不好的作息这些会更让人容易emo,陷入不好的情绪当中。
今天晚上吃完晚饭就回来了,调节一下。工作的本质,不是为了ld工作,而是给自己工作,提高自己的技能,能挣钱才是目标。不要让自己陷入无尽的社交困境里面,找准靶心,调整节奏,健康作息。
最近快入冬,身边感冒越来越多,流感也来了,永远是只有身体不舒服的时候才知道健康多重要,