
c++
文章平均质量分 58
zhanglehes
这个作者很懒,什么都没留下…
展开
-
记一次ndk版本升级
事情的起因是做一次android版本的业务迭代,发现程序crash掉了。经过分析,原因是中台部门对库进行了升级,正好我们的业务也会用到库,导致两个库版本冲突。具体crash的原因可以参见参考文献1。为了解决该问题,中台的同学提出让我们升级ndk版本,使之和中台用到的库版本保持一致。原创 2024-06-27 17:20:15 · 1528 阅读 · 0 评论 -
CMakeFile根据不同指令集配置加载obj对象
Android Studio可以使用不同的指令集进行编译,如arm64-v8a,armeabi-v7a。有时我们需要在c层感知当前编译的指令集,并进行适当的调整,如使用不同的obj对象(.o文件)。本文介绍具体的做法。原创 2024-06-07 17:30:44 · 270 阅读 · 0 评论 -
C++默认构造函数/拷贝构造函数/赋值构造函数
本文主要讲解C++默认构造函数,拷贝构造函数和赋值构造函数在哪些场景下会被调用到场景一调用代码输出注:虽然对于c的赋值使用的是等号,但是调用的仍然是拷贝构造函数输出原创 2024-03-12 14:44:17 · 467 阅读 · 0 评论 -
g2o--ba代码解析
g2o是常用的图优化理论c++库,其自带了很多example讲解如何使用该库文件,本文分析其中ba的示例代码。所谓的图优化,就是把一个常规的优化问题,以图(Graph)的形式来表述。在图中,以顶点表示优化变量,以边表示观测方程。于是总体优化问题变为n条边加和的形式边是约束在具体编写g2o代码时,我们也需要明确哪些是顶点(优化项),哪些是边(约束项)。原创 2024-01-25 17:45:03 · 572 阅读 · 0 评论 -
CMake编译选项CMAKE_CXX_FLAGS详解
概要本文涉及cmake在模式下的编译选项控制,其具体的实践是基于submodule的代码组织形式。基础知识先看一下和相关的参数默认值参数默认值无-g如果对应参数未设置,则使用默认值。我们在使用cmake命令时会指定使用哪种编译模式,它是通过来定义的,如我们可以这么干:Debug编译:Release编译:对于debug模式,实际使用的编译选项是对于release模式,实际使用的编译选项是代码假设我们有个工程,代码组织如下。原创 2024-01-11 17:38:12 · 5667 阅读 · 0 评论 -
双buffer切换与代码实现
在很多场景需要并发的去读写数据,如下图所示:考虑到数据写入的顺序性,通常只会有一个线程写入,读数据是可以多线程的。由于对于Data的一次写入不是原子操作,一个常用通常的方式就是在写的时候加写锁,读的时候加读锁。这在同一个线程每次读数据没有依赖时是可行的,否者还是可能出现问题。如在一次数据处理中,先通过用户“姓名”找到Data中对应的id,再通过id去Data中查找用户其它信息。在这两步之前,写线程可能已经把该用户从Data中删除了,这时就会出现异常。原创 2024-01-10 16:41:42 · 1367 阅读 · 0 评论 -
std::cout输出设置项
在c++编程中,我们常常需要使用std::cout来打印日志,但是std::cout打印日志的格式可能和预期的不一致。笔者最近遇到有两处需要修改默认项的,都是针对double类型,记录如下。原创 2024-01-09 16:45:26 · 597 阅读 · 0 评论 -
pragma once与ifndef的区别
代码编译过程中,为了防止同一份代码被重复引用,通常有两种实现方式方式一方式二#endif //!TEST_H通常情况下,使用上述两种方式中的任意一种都是可以的。最近工作中,代码按照其功能性被划分出不同的模块,这时二者的区别就体现出来了。原创 2023-10-19 19:06:04 · 233 阅读 · 0 评论 -
valgrind排查内存问题
valgrind能在保证程序不会core的情况,将存在double free的问题代码快速定位。原创 2023-09-18 15:11:29 · 677 阅读 · 0 评论 -
通过lambda表达式实现上下层类型的解耦
代码架构中一种常见的组织结构 class A --> class B,A作为上层类型,可以调用类型B的方法。然而B类型也有可能会回调A类型的方法(同时修改A成员变量的值)。实现时可能有多种方案(假设都是单例模式)B类型中也包含A类型指针作为成员变量,这种方式实现最为简单,但要求A类型对于B类型是完全可见的(紧耦合);使用lambda表达式,在A类型调用B类型方法时,指定回调函数,这样B类型就不必去感知A类型的存在(松耦合);原创 2023-08-17 15:01:47 · 150 阅读 · 0 评论 -
C++ json-cpp库的基本使用方法
Json::Value value = array[i] // 每个元素也是一个Json::Value类型。double json_double = value.asDouble() // double类型。float json_float = value.asFloat() // float类型。bool json_bool = value.asBool() // bool类型。// value是一个有赋值的json类型.int json_int = value.asInt() // int类型。原创 2022-12-02 14:52:09 · 1881 阅读 · 1 评论 -
libcurl库简介
/一旦实例化后需要通过下一个函数清理,否则会产生内存泄漏设置headers// headers再赋值后也需要清理// 设置headers// 释放资源设置请求类型curl_easy_setopt(curl, CURLOPT_POST, 1) // post请求curl_easy_setopt(curl, CURLOPT_GET, 1) // get请求url设置超时设置// 读写超时// 连接超时写body接收返回的headers// 设置headers的载体//设置回调函数。原创 2022-11-10 14:54:54 · 624 阅读 · 0 评论 -
Cmake常用命令(五)
本文主要介绍CMAKE_BUILD_TYPE及其相关参数或者不同的type对应的编译选项 Type编译选项DebugCMAKE_CXX_FLAGS_DEBUGReleaseCMAKE_CXX_FLAGS_RELEASERelWithDebInfoCMAKE_CXX_FLAGS_RELWITHDEBINFOMinSizeRelCMAKE_CXX_FLAGS_MINSIZEREL注 2、除了CMAKE_CXX_FLAGS变量,还可以使用add_compile_optio原创 2022-07-14 17:42:38 · 1975 阅读 · 0 评论 -
Cmake常用命令(四)
将指定目录添加到编译器的头文件搜索路径之下,指定的目录被解释成当前源码路径的相对路径。它相当于g++选项中的-I参数的作用,也相当于环境变量中增加路径到CPLUS_INCLUDE_PATH变量的作用编译时的路径搜索必须精确指定文件夹,makefile不会递归搜索子文件夹After和before 关键字控制的是添加文件夹到列表的最后还是最前,makefile在搜索头文件时会按照该列表的顺序进行搜索,只要找到便停止搜索。指定目标依赖的头文件路径,功能和include_directories类似。不同的是i原创 2022-07-11 20:02:59 · 879 阅读 · 0 评论 -
Cmake常用命令(三)
本文介绍IF语句,它有两组语法格式语法condition类型基础条件表达式常量 逻辑值常量值true1、ON、YES、TRUE、Y、非0数字false0、OFF、NO、FALSE、N、IGNORE、NOTFOUNT、空字符串、-NOTFOUND结尾字符串如果常量取值不是以上内容,则按照/条件处理。表示一个变量,变量取值不是上述定义的false常量时其逻辑值为true,否则逻辑值为false。注:表示带引号的字符串。以下...原创 2022-07-08 10:01:18 · 1202 阅读 · 0 评论 -
Cmake常用命令(二)
本文主要介绍File关键字,它是文件系统相关的操作的入口命令格式解释示例READfile(READ [OFFSET ] [LIMIT ] [HEX])读取文件名为 的文件并将其内容存储到 变量中。可选的参数: 指定起始读取位置, 最多读取字节数,HEX 将数据转为十六进制(处理二进制数据十分有用)STRINGSfile(STRINGS ...原创 2022-07-06 09:58:47 · 613 阅读 · 0 评论 -
Cmake常用命令(一)
Cmake就是一门脚本语言,用于生成Makefile.在 CMakeList.txt 文件中运行一条shell命令示例表示在${DIR}目录里运行字符串里的命令该命令指明了对cmake的最低(高)版本的要求,...为低版本和高版本之间的连接符号示例语法project命令用于指定cmake工程的名称,实际上,它还可以指定cmake工程的版本号(VERSION关键字)、简短的描述(DESCRIPTION关键字)、主页URL(HOMEPAGE_URL关键字)和编译工程使用的语言(LANGU原创 2022-07-05 09:43:58 · 1250 阅读 · 0 评论 -
C++的构建框架
通常我们使用cmake或makefile来构建一个c++的系统,但如果只是使用这两个工具之一的话,我们需要将工程所有依赖库和头文件都手动添加进去,会很不灵活,不利于升级和维护。另一方便,公司级的标准库需要放在一个统一的地方,方便给个团队使用。本文介绍一种构建框架将业务代码与公司标准组件(库)进行解耦合。将所有的标准库放在git上;提供业务系统依赖的标准库目录地址和commit code,通过commit code确保依赖库不会随着版本更新而发生变动;编译时先将依赖的标准库clone下来,然后进行编译(cma原创 2022-06-21 20:34:20 · 1077 阅读 · 0 评论 -
C++编译时遇到protobuf版本不一致的问题
我们的项目中会引用到各种sdk,项目代码和sdk中都有可能会使用protobuf。当protobuf版本不一致时,编译就会报错。有两种可能的报错信息This file was generated by a newer version of protoc which is incompatible with your Protocol Buffer headers. Please update your headers.This file was generated by an older version原创 2022-06-09 17:58:51 · 4377 阅读 · 2 评论 -
C++ attribute[fallthrough]
fallthrough在switch语句中,不同case间如果有statement(如函数调用,赋值等操作),但没有break语句,很有可能是coder的一个bug。在C++17中,部分compiler会提示用户,给出相应的warning信息。但如果是coder故意而为,又不希望出现该warning信息,可以使用该关键词提示compiler。具体用法请见下面的例子:#include &l...原创 2020-03-04 20:47:05 · 4256 阅读 · 2 评论 -
linux alignment总结
c++中的内存对齐(alignment)不同的类型(eg. char, int, double)等有不同的对齐要求,在我的电脑上的值如下:类型 alignof(type)返回值 char 1 int 4 double 8 也就是int类型的变量,其地址的值一定是4的整数倍;同理double类型变量的地址,其值要求是8的整数倍。对于struct...原创 2020-03-04 17:39:06 · 675 阅读 · 1 评论 -
c++ template中的个别处理方式
Template的作用是把仅类型不同但功能相似的函数合并在一起,但是有时候template中的函数并不能满足所有的类型调用。如下所示:template inline int hash_wrap(const Kty& k){ return (int)k;}所有的数字类型使用该模板都没有问题,但是string类型却不行,因为不支持有string到int的类型转换。这样我们就原创 2014-07-23 15:18:45 · 535 阅读 · 0 评论 -
c++中实现daemon服务
实现Daemon后,进程与终端脱离。这时关闭终端原创 2014-08-05 10:42:28 · 1111 阅读 · 0 评论 -
打印release版本coredump时的栈信息的一种方式
本文介绍的这种方式通过c语言中的原创 2014-08-05 19:38:32 · 1873 阅读 · 0 评论 -
c++ release和debug编译后的结果不一致
最近遇到一个问题,c++ release和debug编译后的结果不一致,查了h原创 2014-07-23 15:46:04 · 1263 阅读 · 0 评论 -
动态库的加载与测试
之前写了个程序,使用了第三方库lzma(装了xz命令(make install))。程序写好以后,编译没有问题,但是运行时却报了如下的错误:./Searcher: error while loading sharedlibraries: liblzma.so.5: cannot open shared object file: No such file or directory我重新察看了原创 2014-09-01 15:29:06 · 1644 阅读 · 0 评论 -
一种快速加载大文件的方法
问题的来源是这样的。我们的服务有大概20G的索引文件(大概两百多个文件),现在的加载方式是使用mmap(该命令之后会有专门的一篇文章介绍)。使用这个命令的好处就是初始化速度非常快,但是也带来了一些问题。比如第一次查询某个词的时候速度就会特别慢,这当然和mmap只建映射却不拷贝有关。为了解决该问题,领导让我思考一下如何能快速的把20G的文件加载进来。我是这么考虑的。首先一个一个文件读取是最简原创 2014-09-01 15:29:50 · 1650 阅读 · 0 评论 -
给线程加个名
最近要搭一个比较复杂的系统,主进程中有多个功能模块线程,因此想到给每个线程加个名。如果不加名的话,线程的名字是和当前进程的名字相同的。#include#include#includevoid* tmain(void*arg){ char name[32]; prctl(PR_SET_NAME,(unsigned long)"y原创 2014-11-27 16:42:01 · 490 阅读 · 0 评论 -
socket read浅析
使用read函数去读取socket生成的file handle是个什么原理呢?今天研究了一下。代码的逻辑就是server段发出当前时间的字符串,client端去接收该字符串。Server端的部分代码如下 for ( ; ; ) { connfd = accept(listenfd, (struct sockaddr *) NULL, NULL);原创 2014-12-21 15:17:45 · 1749 阅读 · 0 评论 -
一种trie树 的实现方式
Trie树,又被称为前缀树。 它查询的基本原理是通过当前字的下一个字定位到其子节点。如果我们限制所有有效的输入仅是普通的英文字母,那么它最多会有52个子节点。我之前见过的一种做法就是一旦插入产生第一个子节点, 所有52个节点会同时生成。这种做法的好处是查询速度非常快, 因为直接通过输入的字符就直接可以定位到子节点。缺陷也非常的明显, 即是上述的应用场景都会造成严重的空间浪费.。如果我们把原创 2015-01-28 11:38:39 · 730 阅读 · 0 评论 -
errno之我见
Errno能帮我们找到系统函数的错误信息。比如open函数,如果正常返回时,其返回值是一个非负的整数。异常时会返回-1,同时该系统函数会设置errno的值,让我们可以了解错误的原因。 Errno的正确用法是,首先要明确系统函数调用异常(比如返回-1或NULL),然后再去判断errno的值。我们不能直接去判断errno的值来断定系统函数调用是否发生了一场。因为errno值是不会被清零,它只是原创 2014-12-23 11:36:58 · 682 阅读 · 0 评论 -
一种分布式框架设计(三)
本文讨论在分布式框架中使用到的两个数据结构。为了实现高性能,这两个数据结构都是无锁的。第一个数据结构存储的是客户端发过来的socket。由于我们的框架只有一个线程接受用户的请求,所以很容易对每一个socket创建一个unique number(稍候我们再来看unique number包含了哪些信息)。框架中有一个线程专门来做清理工作,同时关闭没有返回给客户端的socket。最后框架中有多个线程原创 2015-03-09 17:52:41 · 846 阅读 · 0 评论 -
如何在程序中添加svn版本信息
如果一个可执行文件能输出版本信息,会带来非常大的便利,本文ji原创 2014-07-23 15:40:00 · 1007 阅读 · 0 评论