C++的门道(一些C++的关键坑)

2023-05-16

C++的门门道道

【导语】 C++是一门被广泛使用的系统级编程语言,更是高性能后端标准开发语言;C++虽功能强大,灵活巧妙,但却属于易学难精的专家型语言,不仅新手难以驾驭,就是老司机也容易掉进各种陷阱。 本文结合作者的工作经验和学习心得,对C++语言的一些高级特性,做了简单介绍;对一些常见的误解,做了解释澄清;对比较容易犯错的地方,做了归纳总结;希望借此能增进大家对C++语言了解,减少编程出错,提升工作效率。

【1】我的程序里用了全局变量,但为什么进程正常停止的时候会莫名其妙的core掉

Rule:C++在不同模块(源文件)里定义的全局变量,不保证构造顺序;但保证在同一模块(源文件)里定义的全局变量,按定义的先后顺序构造,按定义的相反次序析构。

我们程序在a.cpp里定义了依次全局变量X和Y;

按照规则:X先构造,Y后构造;进程停止执行的时候,Y先析构,X后析构;但如果X的析构依赖于Y,那么core的事情就有可能发生。

结论:如果全局变量有依赖关系,那么就把它们放在同一个源文件定义,且按正确的顺序定义,确保依赖关系正确,而不是定义在不同源文件;对于系统中的单件,单件依赖也要注意这个问题。

【2】编译器为什么不给局部变量和成员变量做默认初始化

因为效率,C++被设计为系统级的编程语言,效率是优先考虑的方向,c++秉持的一个设计哲学是不为不必要的操作付出任何额外的代价,所以它有别于java,不给成员变量和局部变量做默认初始化,如果需要赋初值,那就由程序员自己去保证。

结论:从安全的角度出发,定义变量的时候赋初值是一个好的习惯,很多错误皆因未正确初始化而起,C++11支持成员变量定义的时候直接初始化,成员变量尽量在成员初始化列表里初始化,且要按定义的顺序初始化。

【3】std::sort()的比较函数有很强的约束,不能乱来啊

相信工作5年以上至少50%的C/C++程序员都被它坑过,我已经听到过了无数个悲伤的故事,《圣斗士星矢》,《仙剑》,还有别人家的项目《天天爱消除》,都有人掉坑,程序运行几天莫名奇妙的Crash掉,这锅好沉。

如果要用,要自己提供比较函数或者函数对象,一定搞清楚什么叫“严格弱排序”,一定要满足以下3个特性:

非自反性

非对称性

传递性

尽量对索引或者指针sort,而不是针对对象本身,因为如果对象比较大,交换(复制)对象比交换指针或索引更耗费。

【4】注意操作符短路

考虑游戏玩家回血回蓝(魔法)刷新给客户端的逻辑。玩家每3秒回一点血,玩家每5秒回一点蓝,回蓝回血共用一个协议通知客户端,也就是说只要有回血或者回蓝就要把新的血量和魔法值通知客户端。

玩家的心跳函数heartbeat()在主逻辑线程被循环调用

void GamePlayer::Heartbeat()
{
if (GenHP() || GenMP())
{
NotifyClientHPMP();
}
}
如果GenHP回血了,就返回true,否则false;不一定每次调用GenHP都会回血,取决于是否达到3秒间隔。

如果GenMP回蓝了,就返回true,否则false;不一定每次调用GenMP都会回血,取决于是否达到5秒间隔。

实际运行发现回血回蓝逻辑不对,Word麻,原来是操作符短路了,如果GenHP()返回true了,那GenMP()就不会被调用,就有可能失去回蓝的机会。OMG,你需要修改程序如下:

void GamePlayer::Heartbeat()
{
bool hp = GenHP();
bool mp = GenMP();
if (hp || mp)
{
NotifyClientHPMP();
}
}
逻辑与(&&)跟逻辑或(||)有同样的问题, if (a && b) 如果a的表达式求值为false,b表达式也不会被计算。

有时候,我们会写出 if (ptr != nullptr && ptr->Do())这样的代码,这正是利用了操作符短路的语法特征。

【5】理解std::vector的底层实现

(a) vector是动态扩容的,2的次方往上翻,为了确保数据保存在连续空间,每次扩充,会将原member悉数拷贝到新的内存块; 不要保存vector内对象的指针,扩容会导致其失效 ;可以通过保存其下标index替代。

(b) 运行过程中需要动态增删的vector,不宜存放大的对象本身 ,因为扩容会导致所有成员拷贝构造,消耗较大,可以通过保存对象指针替代。

©resize()是重置大小;reserve()是预留空间,并未改变size(),可避免多次扩容; clear()并不会导致空间收缩 ,如果需要释放空间,可以跟空的vector交换,std::vector .swap(v),c++11里shrink_to_fit()也能收缩内存。

(d) 理解at()和operator[]的区别 :at()会做下标越界检查,operator[]提供数组索引级的访问,在release版本下不会检查下标,VC会在Debug版本会检查;c++标准规定:operator[]不提供下标安全性检查。

(e)C++标准规定了std::vector的底层用数组实现,认清这一点并利用这一点。

【6】用c标准库的安全版本(带n标识)替换非安全版本,比如用strncpy替代strcpy,用snprintf替代sprintf,用strncat代替strcat,用strncmp代替strcmp,memcpy(dst, src, n)要确保[dst,dst+n]和[src, src+n]都有有效的虚拟内存地址空间。;多线程环境下,要用系统调用或者库函数的安全版本代替非安全版本(_r版本),谨记strtok,gmtime等标准c函数都不是线程安全的

【7】理解函数调用的性能开销(栈帧建立和销毁,参数传递,控制转移),性能敏感函数考虑inline

X86_64体系结构因为通用寄存器数目增加到16个,所以64位系统下参数数目不多的函数调用,将会由寄存器传递代替压栈方式传递参数,但栈帧建立、撤销和控制转移依然会对性能有所影响。

【8】理解user stack空间很有限,不能在栈上定义过大的临时对象,递归函数要有退出条件且不能递归过深

一般而言,用户栈只有几兆(典型大小是4M,8M),所以栈上创建的对象不能太大;虽然递归函数能简化程序编写,但也常常带来运行速度变慢的问题,所以需要预估好递归深度,优先考虑非递归实现版本。

【9】内存拷贝小心内存越界;memcpy,memset有很强的限制,仅能用于POD结构,不能作用于stl容器或者带有虚函数的类

带虚函数的类对象会有一个虚函数表的指针,memcpy将破坏该指针指向。

对非POD执行memset/memcpy,免费送你四个字:自求多福。

【10】用sprintf格式化字符串的时候,类型和格式化符号要严格匹配,因为sprintf的函数实现里是按格式化串从栈上取参数,任何不一致,都有可能引起不可预知的错误; /usr/include/inttypes.h里定义了跨平台的格式化符号,比如PRId64用于格式化int64_t

【11】stl容器的遍历删除要小心迭代器失效,vector,list,map,set等各有不同的写法

#include
#include
#include
#include
#include

int main(int argc, char *argv[])
{
//vector遍历删除
std::vector v(8);
std::generate(v.begin(), v.end(), std::rand);
std::cout << “after vector generate…\n”;
std::copy(v.begin(), v.end(), std::ostream_iterator(std::cout, “\n”));

for (auto x = v.begin(); x != v.end(); )
{
    if (*x % 2)
        x = v.erase(x);
    else
        ++x;
}

std::cout << "after vector erase...\n";
std::copy(v.begin(), v.end(), std::ostream_iterator<int>(std::cout, "\n"));

//map遍历删除
std::map<int, int> m = {{1,2}, {8,4}, {5,6}, {6,7}};

for (auto x = m.begin(); x != m.end(); )
{
    if (x->first % 2)
        m.erase(x++);
    else
        ++x;
}

return 0;

}
有时候遍历删除的逻辑不是这么明显,可能循环里调了另一个函数,而该函数在某种特定的情况下才会删除当前元素,这样的话,就是很长一段时间,程序都运行得好好的,而当你正跟别人谈笑风生的时候,忽然crash,这就尴尬了。

圣斗士星矢项目曾经遭遇过这个问题,基本规律是一个礼拜game server crash一次,折磨团队将近一个月。

比较low的处理方式可以把待删元素放到另一个容器WaitEraseContainer里保存下来,再走一趟单独的循环,删除待删元素。

当然,我们推荐在遍历的同时删除,因为这样效率更高,也显得行家里手。

【12】积极的使用const,理解const不仅仅是一种语法层面的保护机制,也会影响程序的编译和运行

const常量会被编码到机器指令。

【13】理解四种转型的含义和区别,避免用错,尽量少用向下转型(可以通过设计加以改进)

static_cast, dynamic_cast,const_cast,reinterpret_cast,傻傻分不清?

C++砖家说:一句话,尽量少用转型,强制类型转换是C Style,如果你的C++代码需要类型强转,你需要去考虑是否设计有问题。不管您信不信,我反正是信了。

【14】打开的句柄要关闭,加锁/解锁,new/delete,new[]/delete[],malloc/free要配对,可以使用RAII技术防止资源泄露,编写符合规范的代码

Valgrind对程序的内存使用方式有期望,需要干净的释放,所以规范编程才能写出valgrind干净的代码,不然再好的工具碰到不按规划写的代码也是武功尽废啊。

【15】理解多继承潜在的问题,慎用多继承

多继承会存在菱形继承的问题,多个基类有相同成员变量会有问题,需要谨慎对待。

【16】有多态用法抽象基类的析构函数要加virtual关键字

主要是为了基类的析构函数能得到正确的调用。

virtual dtor跟普通虚函数一样,基类指针指向子类对象的时候,delete ptr,根据虚函数特征,如果析构函数是普通函数,那么就调用ptr显式(基类)类型的析构函数;如果析构函数是virtual,则会调用子类的析构函数,然后再调用基类析构函数。

【17】避免在构造函数和析构函数里调用虚函数

构造函数里,对象并没有完全构建好,此时调用虚函数不一定能正确绑定,析构亦如此。

【18】从输入流获取数据,要做好数据不够的处理,要加try catch;没有被吞咽的exception,会被传播

从网络数据流读取数据,从数据库恢复数据都需要注意这个问题。

【19】协议尽量不要传float,如果传float要了解NaN的概念,要做好检查,避免恶意传播

【20】定义宏要遵循常规,要对每个变量加括弧,有时候需要加do {} while(0)或者{},以便能将一条宏当成一个语句。要理解宏在预处理阶段被替换,不用的时候要#undef,要防止污染别人的代码

【21】了解智能指针,理解基于引用计数法的智能指针实现方式,了解所有权转移的概念,理解shared_ptr和unique_ptr的区别和适用场景

考虑用std::shared_ptr管理动态分配的对象。

【22】了解c++高阶特性:模板和泛型编程,union,bitfield,指向成员的指针,placement new,显式析构,异常机制,nested class,local class,namespace,多继承、虚继承,volatile,extern "C"等

有些高级特性只有在特定情况下才会被用到,但技多不压身,平时还是需要积累和了解,这样在需求出现时,才能从自己的知识库里拿出工具来对付它。

【23】了解C++新标准,关注新技术,c++11/14/17、lambda,右值引用,move语义,多线程库等

c++98/03标准到c++11标准的推出历经13年,13年来程序设计语言的思想得到了很大的发展,c++11新标准吸收了很多其他语言的新特性,虽然c++11新标准主要是靠引入新的库来支持新特征,核心语言的变化较少,但新标准还是引入了move语义等核心语法层面的修改,每个CPPer都应该了解新标准。

【24】OOP设计原则并不是胡扯

设计模式六大原则(1):单一职责原则

设计模式六大原则(2):里氏替换原则

设计模式六大原则(3):依赖倒置原则

设计模式六大原则(4):接口隔离原则

设计模式六大原则(5):迪米特法则

设计模式六大原则(6):开闭原则

【25】熟悉常用设计模式,活学活用,不生搬硬套

神化设计模式和反设计模式,都不是科学的态度,设计模式是软件设计的经验总结,有一定的价值;GOF书上对每一个设计模式,都用专门的段落讲它的应用场景和适用性,限制和缺陷,在正确评估得失的情况下,是鼓励使用的,但显然,你首先需要准确get到她。

【26】了解延迟计算、COW和分散计算

比如游戏服务器端玩家的战力,由属性a,b决定,也就是说属性a,b任何一个变化,都需要重算战力;但如果ModifyPropertyA(),ModifyPropertyB()之后,都重算战力却并非真正必要,因为修改属性A之后有可能马上修改B,两次重算战力,显然第一次重算的结果会很快被第二次的重算覆盖。

而且很多情况下,我们可能需要在心跳里,把最新的战力值推送给客户端,这样的话,ModifyPropertyA(),ModifyPropertyB()里,我们其实只需要把战力置脏,延迟计算,这样就能避免不必要的计算。

在GetFightValue()里判断FightValueDirtyFlag,如果脏,则重算,清脏标记;如果不脏,直接返回之前计算的结果。

分散计算是把任务分散,打碎,避免一次大计算量,卡住程序。

延迟计算和分散计算都是常见的套路。

【27】理解字节对齐

自己对齐能让存储器访问速度更快。
自己对齐跟cpu架构相关,有些cpu访问特定类型的数据必须在一定地址对齐的储存器位置,否则会触发异常。

字节对齐的另一个影响是调整结构体成员变量的定义顺序,有可能减少结构体大小,这在某些情况下,能节省内存。

【28】牢记3 rules和5 rules,当然C++11又多了&&的copy ctor和op=版本

只在需要接管的时候才自定义operator=和copy constructor,如果编译器提供的默认版本工作的很好,不要去自找麻烦,自定义的版本勿忘拷贝每一个成分,如果要接管就要处理好。

【29】组合优先于继承,继承是一种最强的类间关系

【30】减少依赖,注意隔离

最大限度的减少文件间的依赖关系,用前向声明拆解相互依赖。

了解pimpl技术。

头文件要自给自足,不要包含不必要的头文件,也不要把该包含的头文件推给user去包含,一句话,头文件包含要不多不少刚刚好。

【31】别让循环停不下来

for (unsigned int i = 5; i >=0; --i)
{

}
程序跑到这,纳尼?根本停不下来啊?问题很简单,unsigned永远>=0,是不是心中一万只马奔腾?

解决这个问题很简单,但是有时候这一类的错误却没这么明显,你需要罩子放亮点,多个心眼。

【32】size_t到底是个什么鬼?我该用有符号还是无符号整数?

size_t类型是被设计来保存系统存储器上能保存的对象的最大个数。

32位系统,一个对象最小的单位是一个字节,那2的32次方内存,最多能保存的对象数目就是4G/1字节,正好一个unsigned int能保存下来(typedef unsigned int size_t)。

同样,64位系统,unsigned long是8字节,所以size_t就是unsigned long的类型别名。

对于像索引,位置这样的变量,是用有符号还是无符号呢?像money这样的属性呢?

一句话:要讲道理,用最自然,最顺理成章的类型。比如索引不可能为负用size_t,账户可能欠钱,则money用int。

比如

template class vector
{
T& operator(size_t index) {}
};
标准库给出了最好的示范,因为如果是有符号的话,你需要这样判断

if (index < 0 || index >= max_num) throw out_of_bound();

而如果是无符号整数,你只需要判断 if (index >= max_num),你认可吗?

【33】对于在启动时加载好,运行中不变化的查询结构,可以考虑用sorted array替代map,hash表等

因为有序数组支持二分查找,效率跟map差不多。对于只需要在程序启动的时候构建(排序)一次的查询结构,有序数组相比map和hash可能有更好的内存命中性(局部命中性)。

运行过程中,稳定的查询结构(比如配置表,需要根据id查找配置表项,运行过程中不增删),有序数组是个不错的选择;如果不稳定,则有序数组的插入删除效率比map,hashtable差,所以选用有序数组需要注意适用场合。

【34】std::map还是std::unorder_map,我真的很纠结

想清楚他们的利弊,map是用红黑树做的,unorder_map底层是hash表做的,hash表相对于红黑树有更高的查找性能。hash表的效率取决于hash算法和冲突解决方法(一般是拉链法,hash桶),以及数据分布,如果负载因子高,就会降低命中率,为了提高命中率,就需要扩容,重新hash,而重新hash是很慢的,相当于卡一下。

而红黑树有更好的平均复杂度,所以如果数据量不是特别大,map是胜任的。

【35】整型一般用int,long就很好,用short,char需要很仔细,要防止溢出

大多数情况下,用int,long就很好,long一般等于机器字长,long能直接放到寄存器,硬件处理起来速度也更快。

很多时候,我们希望用short,char达到减少结构体大小的目的。但是由于字节对齐,可能并不能真正减少,而且1,2个字节的整型位数太少,一不小心就溢出了,需要特别注意。

所以,除非在db、网络这些对存储大小非常敏感的场合,我们才需要考虑是否以short,char替代int,long。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

C++的门道(一些C++的关键坑) 的相关文章

  • debug时一个非常坑爹的问题——单步调试正常但是运行没结果

    单步调试能得到正确答案 xff0c 运行不出来 本人用的是codeblocks xff0c 20 03版本 话说有一天晚上 xff0c 那个不平凡的夜 xff0c 还有不到十个小时数据结构的实验课就要上交报告了 xff0c 而自己的程序却出
  • DataX使用、同步MySQL数据到HDFS案例

    文章目录 4 DataX使用4 1 DataX使用概述4 1 1 DataX任务提交命令4 1 2 DataX配置文件格式 4 2 同步MySQL数据到HDFS案例4 2 1 MySQLReader之TableMode4 2 1 1 编写配
  • 支持期限提至10年,Ubuntu 18.04 LTS

    给技术最前线加星标 xff0c 每天看技术热点 综合自 xff1a cnBeta COM Solidot Mark Shuttleworth宣布将支持Ubuntu 18 04 LTS长达十年时间 xff0c 让LTS版本的含金量更足 xff
  • 实训第五天:我的页面布局,API接口(一言,天气预报)

    1 不用不用脚本和弹窗获取手机信息 xff0c 用微信公众平台的组件开发能力 open data用于展示微信开放的数据 部分代码 xff1a lt view class 61 34 container 34 gt lt view class
  • 这是一个失败的程序员

    写程序至今 xff0c 未入门 xff0c 什么都不懂 xff01
  • adb dumpsys命令用法

    dumpsys命令功能很强大 xff0c 能dump系统服务的各种状态 xff0c 非常有必要熟悉该命令的用法以及含义 一 概述 1 1 dumpsys命令用法 可通过dumpsys命令查询系统服务的运行状态 对象的成员变量属性值 xff0
  • matlab subs函数

    在matlab命令行查看subs函数的帮助 subs函数一共有三种使用方法 xff1a subs s old new subs s new subs s 点击 subs 的参考页可以看到下面的详细说明 第一种使用方法 说明 xff1a su
  • Docker----如何更改docker镜像的存储路径

    原文链接 Docker 如何更改docker镜像的存储路径 背景 随着docker容器已经镜像的使用 xff0c docker镜像占用大量磁盘空间 xff0c 当然可以通过不断的删除镜像或者设置定时任务删除镜像 xff0c 但是有时候还是挺
  • ROS的geometry_msgs/PoseWithCovarianceStamped Message 消息格式

    溪西创客小屋 geometry msgs PoseWithCovarianceStamped Message Raw Message Definition This expresses an estimated pose with a re
  • 线程和进程的理解

    一 介绍线程和进程 什么是线程 是程序执行的最小单位 xff0c 一个进程在执行过程中产生建多个线程 xff0c 同一进程中的 多个 线程共享同一块内存空间及系统资源 xff0c 线程数进程的一部分 xff0c 因此线程数也被称为轻量级进程
  • Windows安装tensorflow-gpu

    0 想在Windows环境安装tensorflow gpu xff0c 显卡必须是N卡 xff08 本文以3070显卡为例进行说明 xff09 1 安装好Anaconda以及Pycharm xff08 安装教程 xff1a https ww
  • 16.进程-进程间通信概述

    进程间通信 xff0c 也就是大家常说的 IPC Inter Process Communication xff0c 指的是不同的进程间进行交流 xff0c 本质上就是进程之间发送和接收数据 xff1b 本质上 xff0c 信号也是属于进程
  • PNP问题-位姿估计方法梳理(pose estimation)

    tags 单目视觉 位姿测量 目标3D精确模型已知 xff08 建立2D 3D对应关系 xff09 xff1a 点特征 P3P问题 基于针孔成像模型 Gao的方法 xff08 opencv emgucv xff09 Kneip 的 P3P
  • 室内无人机定位导航

    个人观点 xff1a 可研究的方向 1 静态规划方面 xff1a 将控制与定位结合起来 xff1b 修正回环检测误差 xff0c 提高算法的计算精度和执行效率 xff1b 2 动态规划方面 xff1a 用神经网络识别运动物体的行进方向 xf
  • 树莓派3b程序控制无人机 (一)——电脑连树莓派

    设备 xff1a 树莓派3b xff08 备有键盘 xff0c 鼠标 xff09 xff1b win10 x64笔记本 xff1b UAV pixhawk飞控板 etc network interfaces 的设置可参考以下链接 xff1a
  • 三星6410裸机程序开发

    网上关于S3C6410裸机程序开发都是基于RealView RVDS 也有一些是基于eclipse的 xff0c 但都没有详细介绍在eclipse中如何建立S3C6410裸机程序工程 尽管友善之臂提供的6410裸机程序示例使用了eclips
  • linux socket can程序cantool

    最近写了个自认为不错的基于linux socket can程序 xff0c 主要功能 xff1a 程序具备全部CAN功能 xff0c 包括CAN标准帧 扩展帧接收与发送 CAN总线错误判断 环回等功能适用基于LINUX SOCKET机制实现
  • Linux CAN编程详解

    Linux CAN编程详解 是一篇百度文库上的文档 xff0c 主要描述了以下内容 xff1a can总线介绍及其帧类型 xff1b Linux 系统中CAN 接口配置 xff1b Linux 系统中CAN 接口应用程序开发 xff1b L
  • c++中冒号(:)和双冒号(::)的用法和c/c++ 位域结构体

    1 冒号 xff08 xff09 用法 xff08 1 xff09 表示结构体内 位域的定义 xff08 即该变量占几个bit空间 xff09 typedef struct XXX unsigned char a 4 unsigned ch
  • CAN总线与RS485的比较

    最近一个项目总体方案设计为分布式系统 xff0c 于是在通讯上纠结于CAN总线还是RS485 因此在网上搜索一些了一些关于RS485和CAN总线的资料 xff0c 除进一步认识RS485通讯特点外 xff0c 认识了CAN总线的特点及其与R

随机推荐

  • Linux内核中常见内存分配函数

    1 原理说明 Linux 内核中采 用了一种同时适用于32 位和64 位系统的内 存分页模型 xff0c 对于32 位系统来说 xff0c 两级页表足够用了 xff0c 而在x86 64 系 统中 xff0c 用到了四级页表 xff0c 如
  • MII、RMII、GMII接口的详细介绍

    概述 xff1a MII Media Independent Interface 介质无关接口 或称为媒体独立接口 xff0c 它是IEEE 802 3定义的以太网行业标准 它包括一个数据接口和一个MAC和PHY之间的管理接口 数据接口包括
  • Visual Studio .NET 2003中出现“无法启动调试 没有正确安装调试器”错误的解决方法

    最近 xff0c 装了Visual Studio NET 2010后 xff0c 在Visual Studio NET 2003中进行运行调试 xff0c 突然出现 无法启动调试 没有正确安装调试器 提示 xff0c 不能向往常一样进入控制
  • ftime()函数

    ftime 函数取得目前的时间和日期 相关函数 xff1a time ctime gettimeofday 表头文件 xff1a include lt sys timeb h gt 函数定义 xff1a int ftime struct t
  • 几道经典的嵌入式C语言笔试题

    C语言测试是招聘嵌入式系统程序员过程中必须而且有效的方法 这些年 xff0c 我既参加也组织了许多这种测试 xff0c 在这过程中我意识到这些测试能为带面试者和被面试者提供许多有用信息 xff0c 此外 xff0c 撇开面试的压力不谈 xf
  • 解决eclipse中出现Resource is out of sync with the file system问题

    作者 xff1a reille 本博客网址 xff1a http blog csdn net reille xff0c 转载本博客原创文章请注明出处 本文内容概要 xff1a 解决eclipse中出现Resource is out of s
  • 代码中特殊的注释技术——TODO、FIXME和XXX的用处

    作者 xff1a reille 本博客网址 xff1a http blog csdn net reille xff0c 转载本博客原创文章请注明出处 本文内容概要 xff1a 代码中特殊的注释技术 TODO FIXME和XXX的用处 更多请
  • 个人网站梦想终实现即reille blog | velep.com成长之路

    最近用wordpress开放平台软件建立了一个属于自己的个人博客网站velep com即reille blog xff0c 中文名 xff1a reille博客 xff0c 圆了自己多年来的梦想 xff0c 感觉像是在这大千互联网里找到了属
  • PaddleX树莓派部署--神经计算棒2代

    PaddleX树莓派部署 神经计算棒2代 PaddleX支持在树莓派上插入NCS2 神经计算棒2代 通过OpenVINO部署PadlleX训练出来的分类模型 注意 xff1a 目前仅支持分类模型 仅支持Armv7hf的树莓派 前置条件 OS
  • Hbase数据结构和体系架构

    1 HBase与关系数据库比较 1 xff09 行式数据库 优点 1 数据存储在一起 2 INSERT UPDATE数据较容易 缺点 1 选择操作 xff08 select xff09 时 xff0c 即使是几行所有数据也要被读取 2 xf
  • Ubuntu安装remmina

    官方教程 xff1a https github com FreeRDP Remmina wiki sudo apt span class hljs attribute add span span class hljs attribute r
  • ros运行rviz时出现QXcbConnection: XCB error: 148错误

    原因 xff1a 由于使用了vnc远程控制下位机 xff0c rviz是一个基于opengl开发的图形插件 xff0c 需要使用理论的屏幕参数 xff08 thetis screen xff09 xff0c 使用vnc会导致屏幕参数值不对
  • FreeRTOS内核源码解读之-------系统启动(三)

    前面文章两篇文章介绍了FreeRTOS的启动过程 xff0c 但是有些问题还没有解决 xff0c 在本篇文章中将会逐一解决 首先 xff0c 在 FreeRTOS内核源码解读之 系统启动 xff08 一 xff09 中提到Cortex M4
  • C++ MathGL 二维数据绘图

    C 43 43 MathGL环境搭建参考 https blog csdn net vaincury article details 105438971 MathGL官网 http mathgl sourceforge net doc en
  • 面经——小马智行2022秋招嵌入式

    笔试 单选 xff1a 双向链表 实时操作系统特征 死锁的必要条件 小端对齐时 xff0c 不用sizeof判断int长度 const typedef 结构体字节对齐 堆和栈 n阶阶乘的时间复杂度 tcpudp static 常见通信协议
  • silicon labs平台通过串口升级固件方案

    开发环境 windowssimplicity studio 5geck sdk 4 1 一 bootloader 新建BGAPI UART DFU工程 工程新建完成以后看一下linkerfile ld文件的flash和ram的配置跟自己的a
  • Postman前置脚本

    位置 xff1a 作用 xff1a 调用脚本之前需要执行的代码片段 一 产生随机数字 生成0 1之间的随机数 xff0c 包括0 xff0c 不包括1 xff1b var random 61 Math random console log
  • Ubuntu下启动后网卡没有服务没有启动的问题

    参照了很多帖子 xff0c 两个典型的帖子分别是 https blog csdn net ErErFei article details 98205463 Ubuntu 18 04设置开机自动启动 https blog csdn net w
  • 错误:datatype/md5sum

    学习中科院ros入门时 xff0c 在用roscpp实现主题的发布和订阅 xff0c 遇到以下错误 xff1a ERROR Client listener wants topic gps info to have datatype md5s
  • C++的门道(一些C++的关键坑)

    C 43 43 的门门道道 导语 C 43 43 是一门被广泛使用的系统级编程语言 xff0c 更是高性能后端标准开发语言 xff1b C 43 43 虽功能强大 xff0c 灵活巧妙 xff0c 但却属于易学难精的专家型语言 xff0c