C/C++
文章平均质量分 92
一个程序员的修炼之路
顺势而为
展开
-
杂想之一个C++内存泄露案例
对一个C++内存泄露案例进行的思考原创 2022-06-25 17:18:52 · 900 阅读 · 1 评论 -
C++类库隐藏私有属性和方法的两种方式
在我们编写程序的时候,会将程序模块化,常见的就是用动态链接库的方式,然后导出函数接口或者类。而对于导出类的方式,作为模块的实现者,不论是给第三方使用或者自己的项目使用,应该都不太愿意暴露自己的私有属性和方法,个人碰到的主要有以下两个常见原因:通过隐藏私有属性和方法,让被调用者猜不到其实现方式私有方法中或者属性中,可能会存在一些第三方的头文件或者库的依赖,而对于被调用方来说不应该直接依赖本文将介绍两种方式来满足以上的需求,一种是...原创 2022-05-08 18:15:08 · 2125 阅读 · 0 评论 -
单一职责原则(SRP)
什么是单一职责原则单一职责原则(英文名为Single Responsibility Principle,简称SRP)是Robert C. Martin提出的SOLID软件设计原则中的第一个字母S。Robert C. Martin给出的定义为, 有且仅有一个原因导致类的变化。A class should have one, and only one, reason to change.而本人更偏向于Wiki上对SRP的描述, 其单一职责原则应该运用于模块, 类以及文件。The single-r原创 2022-05-01 16:14:19 · 5818 阅读 · 2 评论 -
设计模式之简单工厂,工厂方法和抽象工厂
在面向对象的编程中,一般通过继承和虚函数来提供抽象能力,多态让程序在执行期,调用者只需要看到父类类型,而不需要关心继承的子类类型。举个例子: 比如有个游戏,里面的游戏的活动对象为动物,比如有老虎和猫,会对主人公进行攻击。那么可能会实现为如下:代码如下:class Animal{public: virtual void Attack() = 0;};class Tiger : public Animal{public: virtual void Attack() { std::cout原创 2022-01-03 21:26:07 · 2821 阅读 · 0 评论 -
谈谈多例模式(multiton)的使用
之前的文章<<谈谈单例模式>>介绍过单例模式, 其全局只会生成一个实例化的对象。当初采用的是全局配置文件的实践案例, 因为比较适合采用单例模式。设计模式是前辈们通过丰富的工程实践后总结出的经验。所以笔者认为对于设计模式的理解,并不仅仅在于看懂这个模式的实现方式,更重要的是明白什么时候该使用什么设计模式,而要做到这个,离不开的是不断地实践。注意这里的实践,并不是说手写一遍设计模式的实现,而是多做一些项目,从项目中汲取经验,才能理解的更加深刻,变为自己能够灵活运用的知识。而本文也将从原创 2021-10-22 20:43:38 · 1101 阅读 · 0 评论 -
Lambda表达式
常见的语言中都提供Lambda语法糖,比如C#, Python, Golang等。本文将探讨下C++ 11引入的Lamdba语法糖。语法糖是一种让程序员使用更加便利的一种语法,并不会带来额外的功能,比如Lambda,没有这种语法糖,其可以用已有的语法等价的实现出相应的功能。有编程实践经验的同学一定能够快速的理解Lamdba产生的意义,而缺乏编程经验的同学,跟着我一起来梳理下Lamdba给我们带来了哪些便利性?函数指针和对象函数因为笔者用Lambda最多的场景是回调函数,先说说回调函数。在编程中回调函数原创 2021-10-04 21:53:09 · 558 阅读 · 1 评论 -
谈谈单例模式
单例模式是一个很常见的设计模式,也广泛应用于程序开发。其具有如下特点:一个类只有一个实例化对象全局可以使用那么有人要问,那我不就定义一个类,程序只初始化一个全局的实例就好了吗? 没错,这样是可以的。但是我们都知道程序会经过多人的接手维护和开发,比如第N个接手程序的时候,并不知道这个类定义的时候只能初始化一个实例,然后又实例化了新的对象, 则可能会造成意想不到的场景。那么这时候就要提到防御性编程,个人认为单例模式的实现也是防御性编程的一种方式,让这个类保证只有一个实例化对象,并且如果试图构造多个对象原创 2021-09-19 20:09:15 · 355 阅读 · 0 评论 -
对象池的使用场景以及自动回收技术
对象池在编程中,我们经常会涉及到对象的操作,而经常的操作模式如下图所示:创建对象->使用对象->销毁对象。而这个对象有可能创建的时候会需要构建很多资源,消耗比较大, 比如:在hiredis的SDK中每次都创建一个redisContext,如果需要查询,那就首先要进行网络连接。如果一直都是上图的工作方式,那将会频繁的创建连接,查询完毕后再释放连接。重新建立连接,让网络的查询效率降低。这个时候就可以构建一个对象池来重复利用这个对象,并且一般要做到线程安全:从对象池中获取对象,如果没有对象原创 2021-08-29 21:31:35 · 1083 阅读 · 0 评论 -
Protobuf用过没?
一个故事在读书的时候,参与的第一个是实质性的项目,其中有一部分网络通信,基于socket编程。网络通讯TCP/IP相当于交通工具,上层应用协议还得自己设计。 学过计算机网络这门课的,自然会对所学的知识举一反三。首先查看一个TCP的协议格式:protobuf,语言之间的内容传递,进程间通信。protobuf 2 vs 3json vs protobuf参考<>...原创 2021-08-23 22:33:45 · 344 阅读 · 0 评论 -
你踩过几种C++内存泄露的坑?
在`Modern C++`之前,C++无疑是个更容易写出坑的语言,无论从开发效率,和易坑性,让很多新手望而却步。比如内存泄露问题,就是经常会被写出来的坑,本文就让我们一起来看看,这些让现在或者曾经的`C++`程序员泪流满面的`内存泄露`场景吧。你是否有踩过?原创 2021-08-16 12:05:25 · 752 阅读 · 0 评论 -
谈一谈Windows中的堆
如果在Windows中编程应该了解一些Windows的内存管理,而堆(Heap)也属于内存管理的一部分。Windows Heap下图参考<<Windows高级调试>>所画,并做了一些小小的修改。可以看出来程序中对堆的直接操作主要有三种:进程默认堆。每个进程启动的时候系统会创建一个默认堆。比如LocalAlloc或者GlobalAlloc也是从进程默认堆上分配内存。你也可以使用GetProcessHeap获取进程默认堆的句柄,然后根据用这个句柄去调用HeapAlloc达到在系统原创 2021-07-28 16:02:53 · 1820 阅读 · 0 评论 -
C++常见的三种内存破的场景和分析
有一定C++开发经验的同学大多数踩过内存破坏的坑,有这么几种现象:比如某个变量整形,在程序中只可能初始化或者赋值为1或者2, 但是在使用的时候却发现其为0或者其他的情况。对于其他类型,比如字符串等,可能出现了一种出乎意料的值!程序在堆上申请内存或者释放内存的时候,在内存充足的情况下,居然出现了堆错误。当出现以上场景的时候,你该思考一下,是不是出现了内存破坏的情况了。而本文主要通过展示和分析常见的三种内存破坏导致覆盖相邻变量的场景,让读者在碰到类似的场景,不至于束手无策。而对于堆上的内存破坏,很常见并原创 2021-07-18 21:45:30 · 1195 阅读 · 1 评论 -
从一个单元测试用例来说说编程中的编码问题
在编程中,大多数程序员都离不开编码问题: 系统的默认区域和语言设置,代码文件的编码,以及代码中字符串的编码。编码简述以及Windows默认配置一提到编码大家最熟悉的莫过于ASCII(American Standard Code for Information Interchange), 其采用7个bit表示128个字符,包含了常见的英文字符、数字,控制字符等。 但是ASCII不包含中文,日文等文字的编码,便出现了针对中文的编码GB2312,GBK等编码,针对日文的Shift_JIS编码,他们都兼容ASC原创 2021-07-10 17:38:59 · 537 阅读 · 2 评论 -
C++ RAII实现golang的defer
在之前一篇文章<<从lock_guard来说一说C++中常用的RAII>> 讲解了RAII, 其实一种常见的资源管理方式,减少了资源泄露的风险。 同事和我说是不是就是智能指针, 准确来说RAII是一种思想,一般是利用栈上对象初始化进行资源的申请,在其生命周期结束的时候,自动调用其析构函数,对资源进行释放。 比如std::string, std::lock_guard都属于RAII的一种实现,那么对于不同资源的管理我是否都要实现一个类似于std::lock_guard一样的实现,其实不原创 2021-06-26 19:06:13 · 625 阅读 · 1 评论 -
微软Debug CRT库是如何追踪C++内存泄露的?
本人在之前已经写过四篇关于Windows中如何查找内存泄露的方法,基本上可以说可以帮你找到内存泄露的问题所在。<<Windows内存泄露分析之DebugDialog>><<Windows程序内存泄漏(Memory Leak)分析之Windbg>><<Windows程序内存泄漏(Memory Leak)分析之UMDH>><<vmmap分析内存泄露问题>>那么为什么要写这篇文章呢?本人在逛知乎的时候,原创 2021-06-11 21:32:52 · 435 阅读 · 0 评论 -
栈上内存溢出漏洞利用之Return Address
程序员大多都碰到过栈上内存溢出溢出,最常见的结果是导致程序Crash,有时候也有可能因为覆盖栈上的信息导致程序执行一些意想不到的逻辑,这种情况往往比起Crash更加糟糕。在阅读本文之前,最好熟悉<<你了解函数调用过程吗?>> 文章的讲解: 以32位程序为例,讲解了函数调用是如何利用栈的。局部变量存放在栈上,而当局部变量是一个数组,那么在操作过程中就很容易发现溢出问题,即读/写数据操作了其空间。在大多数系统中,栈默认是由高地址向低地址扩展,并且在小端机器中低位在低地址,如果在写数组原创 2021-05-16 22:25:57 · 7804 阅读 · 1 评论 -
栈溢出的场景分析和建议
场景介绍有时候当你收到一个dump后,大多数情况可以通过k命令查找到导致栈溢出的函数。但是本文要讲的是,曾经碰到过的栈溢出(stackoverflow), 却无法直接通过k命令查看到当前的函数调用栈。 下面将介绍一个简单的方法,找到导致栈溢出的函数。样例代码先声明下,因为产品的实际分析不能够通过网络分享。下面的样例代码,实际上不会导致在上一章场景介绍中提到的问题,可以直接通过crash的栈查找到代码,本文只是通过这个例子来讲解如下场景的分析思路: 如果栈溢出了,通过k命令却无法查找到函数调用栈。#i原创 2021-04-15 21:22:47 · 758 阅读 · 0 评论 -
从lock_guard来说一说C++中常用的RAII
常见问题在一个函数中(或者一个{...}作用域)有时候会创建/引用了一个资源,而在这个函数结束的时候需要对这个资源进行释放。常见的场景:申请了一段内存,退出时候需要释放打开了一个文件,退出需要关闭文件统计某个函数调用的当前引用次数,进入的时候引用加一,退出的时候引用减一某个{...}作用域开始需要加锁,执行完代码后需要解锁等等…以上面的锁为例, 在进入函数的时候加锁,在函数退出的时候解锁。这种写法笔者认为可能会带来两个问题:在互斥区的代码有可能会有多处返回return, 在每个re原创 2021-04-01 09:26:44 · 460 阅读 · 0 评论 -
free一个合法的地址也会导致crash?
场景描述在Windows平台上使用C++开发了一个服务,其中组合了各种各样的第三方组件,一般以lib/dll和头文件的形式使用。有这样一种场景,如下图所示,应用程序申请了一段内存ptr, 但在调用lib.dll的函数接口中其调用了free(ptr)。一般来说我们也尽量避免在一个组件中申请内存,而在另一个组件中释放,这里恰巧是一个bug导致了跨组件的内存申请和释放。那么请各位读者思考一下,这样会有问题吗?如果你是一个老司机,也许已经发现,在某些情况下会在调用free(ptr)的时候导致程序crash。原创 2021-03-06 21:59:18 · 574 阅读 · 0 评论 -
你了解函数调用过程吗?
函数调用是编程语言都有的概念,也许你听说过函数调用栈,但是大家都知道函数调用是如何完成的吗?我们为什么要了解这个过程:对于程序运行机制中的数据结构和实现的了解,对自己开发程序有着启发作用碰到一些疑难杂症的时候,比如函数栈溢出了或者函数栈破坏了,如何从蛛丝马迹中寻找问题的原因。了解栈溢出可能带来的危害,黑客也许会利用栈溢出的漏洞进行攻击。这篇博文我们一起来对函数调用的过程进行探究。程序样例下面是这篇博文要用到的一个样例程序:程序在main中调用了FunAdd函数。本篇就先来研究一下:函数的原创 2021-01-03 09:17:48 · 819 阅读 · 0 评论 -
Windbg分析程序崩溃实践
1. 项目场景本故事纯属虚构。初入职场的小木,负责维护一个博客系统,后端采用C++编写,部署在Windows服务器上。刚刚熟悉完产品的小木,接到了后台服务的报警,服务器后端偶尔会程序崩溃。刚开始小木还有点慌张,脑子里面浮现出各种问题,这个是程序的bug吗?茫茫的代码如何寻找问题?log能看到线索吗?当冷静下来后,小木忽然想起前几天看的两篇文章<<Windbg调试----Windbg入门>>和<<Windows程序Dump收集>>,还没动手过呢,正好练习练习原创 2020-11-15 16:55:33 · 2333 阅读 · 0 评论 -
令人惊讶的NULL类指针
一.NULL指针NULL,在C/C++常用来表示空指针,即指向地址为0的指针。通常在指针初始化 或者 释放指针所指向空间后,将指针置为NULL,防治导致悬浮指针也使其表明自己未指向分配的空间。这样看来指向NULL的指针仅仅如此?当然我们也常常用一些小技巧来做一些很实用的事情比如,求Struct中某个变量的偏移位置:#define VALUEOFFSET(sType, vName原创 2012-05-15 20:12:07 · 2685 阅读 · 7 评论 -
关于预编译头以及StdAfx.cpp的解惑
预编译头就是将程序的头文件部分编译成一个二进制中间文件,提高整个工程的编译效率,一般以.pch格式存储。 1. 在编译器重已经采用了时间戳的方式,为何还需要预编头呢? 对.obj加以时间戳的方式,可以根据时间戳来决定哪些文件需要重新编译,从而提高效率。但重新编译这个文件,包括这个文件的头文件里的信息和预处理(指头文件中的预处理)都重新进行一遍,而预编译头正是解决了这原创 2012-05-24 22:50:35 · 7301 阅读 · 1 评论 -
Python调用C/C++动态链接库
吐槽(可略过):不知不觉,4月份毕业,5月份进入团队,已有7个月。大的方面经历着测试、解决客户问题/bug、出一个产品Patch,小的技术方面经历着C++,Shell,python,linux Kernel以及自动化测试框架,看起来经历都很丰富,但何尝不处于一种浅尝辄止的状态?!似乎就像学生时代,寂寞了,就找点不会的技术学学,然而都钻的不够深入。也许现在的境遇,和自己本身的职位也有所关系,不像De原创 2013-12-04 16:39:49 · 35524 阅读 · 3 评论 -
链接选项rpath,容易被忽略的一个功能
问题来源最近在做一个项目的客户端的SDK,实现为一个动态链接库,其依赖于其他的若干个动态库文件。那么在利用SDK开发应用程序的时候,编译的时候除了链接SDK库本身,还得链接SDK库所依赖的库,这样编译命令里面得一一的添加这些库。比如,SDK库的名称为liba.so, 其依赖于libb.so和libc.so,那么在编译应用程序的时候使用以下命令:+++++++++++++++++++++原创 2014-05-07 18:28:19 · 19775 阅读 · 1 评论 -
创建动态库时,建议使用的链接选项Bsymbolic
题外话:最近了解了一种轻量级标记语言,叫做Markdown.可以使用Markdown易读的文本格式,然后将其转换为HTML格式。虽然才知道,发现这个语法已经在无处不在了,著名的stack overflow发帖,以及一些wiki,或者一些博客都支持这种语法编辑了。OK,那么博主,这次也尝试下,本次博客采用的是MarkDownPad编辑器编写。问题描述回归正题,前段时间项目开发中,实现原创 2014-05-14 19:08:22 · 12415 阅读 · 0 评论 -
<<程序员的自我修养>>第二章读书读书笔记----静态链接
最近搞了一个Linux爱好者的微信订阅号,以Linux平台为主,定期也会分享一些网友的博文,和技术经验。因为网络文章,不和博主沟通,没法随意转发分享,如果您方便让您的经验一起分享,请您留下博客地址~~~以下是微信的订阅号,欢迎关注和讨论: 对一个不善写作的人来说,写一篇博客着实痛苦,但还是逼着自己去写,让所学的东西加深。本篇博客将对第二章内容进行回顾,理解,当然还要加上原创 2015-08-03 13:20:33 · 1120 阅读 · 0 评论 -
<<程序员的自我修养>>第一章读书读书笔记----从hello world说起
在读《程序员自我修养》这本书之前,是准备写读书笔记的,一来加深自己对本书的理解,而来可以和看到笔记的网友们互相讨论。当读到第三章的时候,心理暗暗偷懒,不想写博客了,要将自己的所读所理解的整理为一篇文章,确实会花费不少时间和精力,可又想了想了当初的目标和想法,还是决定写下去。 C语言Hello World程序你了解多少?第一章作者就抛出了一个问题,从一个简单的C程序的HelloWorld原创 2015-07-10 15:36:10 · 1780 阅读 · 0 评论 -
C/C++编程教训----'=='判断条件
程序质量保证个人谈一谈项目代码质量保证主要来源于以下几个方面:程序员的经验,防御性的避免一些错误/坑。单元测试: 单元测试应该是测试中最细粒度的测试,这个测试一般来说贯穿了整个开发以及后期维护;它能够保证到每一个函数/功能的健壮性,从而提高代码的整体质量。测试自动化: 测试自动化,应该来说至少应该包括了单元测试和功能测试自动化。 在开发或者维护过程中,在修改代码后,能够迅速的使用自动化测试进行原创 2017-04-22 16:47:32 · 1269 阅读 · 0 评论 -
C/C++编程教训----数据结构的类型别名和memset
问题描述学习微软,我们经常会这样定义数据结构, 并且定义了数据结构别名StructTest,和数据结构指针别名LPStructTest, 这样定义也许让程序的类型更加简洁。typedef _StructTest{ int iVal; char csStr[100];}StructTest, *LPStructTest;数据结构变量定义一般使用StructTest sTest这种形原创 2017-05-14 16:52:55 · 922 阅读 · 0 评论 -
C/C++编程教训----函数内静态类对象初始化非线程安全(C++11之前)
不少程序员在编写程序的时候,会使用函数内静态(static)变量,既能满足函数内这个变量可以持久的记录某些信息,又使其访问范围的控制局限于函数内。但函数内静态类对象初始化是非线程安全的。问题背景在我们产品中对log4cxx做了一些简单的封装 (采用VS2005编译),其中会调用到getWarn这个接口。由于这个函数存在非线程安全的问题,导致程序Crash。为了更好的描述问题,博主后面采用一个简单的例原创 2017-09-03 16:57:59 · 3401 阅读 · 1 评论 -
C/C++的宏
一.宏的概念C语言中使用一个标示来代替一个字符串,宏分为有参数和无参数两种;宏在编译之前的预处理阶段进行完成。二.宏的优劣优点:(1)提高程序本身的可读性,提高编程效率,但宏本身的可读性往往比较差;(2)将频繁的操作实现为一个宏,可以提高程序效率,避免函数调用的消耗;缺点:(1)宏替换固然使程序的可读性提高,但同时在替换的过程中也会带来很多意外的BUG(2)原创 2012-05-14 12:29:33 · 1817 阅读 · 1 评论