个人Linux C++问题汇总
-
避免使用
vector<bool>
,尽量使用bitset
或者deque<bool>
因为
vector<bool>
不是容器,底层是bool值按bit存储 -
STL list容器数据结构上看是带空头的双向循环链表
-
容器迭代器要注意迭代器失效问题,insert/erase后要及时更新迭代器
-
auto_ptr不能管理数组对象、自定义对象;应该使用C++11中的智能指针加自定义删除器
unique_ptr<char, function<void(char*)>> sp(new char[100], [](char *p)->void { // 返回值为空,可省略 delete []p; } ); auto deletor = [](char* p){delete[] p;}; unique_ptr<char, decltype(deletor)>> sp(new char[100], deletor); // make_unique 不支持自定义删除器
-
为什么 C++ 有了函数指针还要引入
std::function
?函数指针指向的是代码段中的一段代码,不具备捕捉上下文的能力,当一个回调传入需要模块A中定义的函数和模块B的运行产生的数据一起传递给C模块来调用时,单纯的函数指针不够用。
-
C++ 11: push/insert --> emplace | push_front ---> emplace_front | push_back ---> emplace_back
- 增加移动构造函数 Test(Test &&t) 复用产生的临时对象t,以提高效率
-
C++ 17: std::map 提供了 try_emplace 方法和 insert_or_assign 方法
- try_emplace 方法: 该方法会检测指定的key是否存在,如果存在,则什么也不做。
- insert_or_assign 方法:map中指定的 key不存在则插入相应的 value,存在则更新其value。
-
实现了移动构造函数或移动赋值运算符的类对象才支持std::move()
-
Move Constructor & Move operator=
template<typename T, typename Deletor> class unique_ptr { public: // Move Constructor unique_ptr(unique_ptr&& rhs) { this->m_pT = rhs.m_pT; rhs.m_pT = nullptr; } // Move operator= unique_ptr& operator=(unique_ptr&& rhs) { this->m_pT = rhs.m_pT; rhs.m_pT = nullptr; return *this; } };
-
goto label 到 label之间不能存在变量声明
-
不要频繁调用printf()
最近遇见调用一个库里函数会打印2条信息,循环调用1w次,总时间达到90秒左右,和单次调用的时间开销天壤之别;函数调用前后计时,大部分情况是40+us,隔一段时间出现350+ms,让负责维护库的同学去掉打印后,调用1w次总时间150ms.
- 频繁输出信息时,最好一次性输出,避免频繁调用
printf()
; - 当需要立即将缓冲区中的数据输出时,可以显式地调用
fflush(stdout)
,强制刷新缓冲区; - 对于频繁需要输出大量信息的情况,也可以使用系统调用 write() 来代替 printf()。
- 使用
printf()
打印消息并带有 '\n'(换行符)可以让缓冲区立即刷新, 但使用printf()
打印消息并不一定会实时刷新缓冲区,因为缓冲区的刷新时间受到多种因素的影响,例如硬件设备、是否输出到终端、缓冲区大小等等。
- 函数内部占内存较大的变量不要定义为局部变量
嵌入式设备的配置模块,一个函数中定义了一个占内存1M的局部变量,用来备份数据。在子函数init()的子函数getXCode()时程序异常结束运行,addr2line只能看到结束在getXCode()
注释掉getXCode(),又报在下一个子函数出错,推测函数压栈时出了问题,走读代码,尝试修改时发现问题原因
解决:堆或者定义为静态变量每次使用时memset
13.top输出中各字段详解
在计算机科学中,"top" 是一个常用的命令行工具,用于显示系统中运行的进程的实时信息。下面是 "top" 输出中各字段的详细解释:
- PID(Process ID):进程的唯一标识符。每个运行的进程都有一个独特的PID。
- USER(Username):启动该进程的用户名。
- PR(Priority):进程的优先级。较低的数值表示较高的优先级。
- NI(Nice Value):进程的优先级调整值。负值表示较高的优先级,正值表示较低的优先级。
- VIRT(Virtual Memory):进程使用的虚拟内存量,包括代码、库、数据等。
- RES(Resident Memory):进程当前使用的物理内存量。
- SHR(Shared Memory):进程使用的共享内存量。
- S(Status):进程的状态,常见的状态有:
- R:运行(Running)R:运行(运行)
- S:睡眠(Sleeping)S:睡眠(Sleeping)
- D:不可中断的睡眠状态(Uninterruptible sleep)
- Z:僵尸进程(Zombie)
- T:停止(Stopped)T:停止(Stopped)
- %CPU(CPU Usage):进程在最近一次更新期间使用的CPU资源百分比。
- %MEM(Memory Usage):进程使用的物理内存占总内存的百分比。
- TIME+(CPU Time):进程已经使用的CPU时间总量。
- COMMAND(Command Name):启动进程的命令或程序名称。
这些字段提供了关于系统中运行的进程的重要信息,帮助用户了解进程的资源消耗情况、优先级以及当前状态,从而进行系统性能监测和调优。
14.top进程的各个状态对应的可能原因
以下是常见的进程状态及其可能的原因:
- R(Running):进程正在运行或准备运行。可能原因包括:
- 进程正在执行其主要任务。
- 进程正在等待系统资源(如CPU时间片、I/O等)。
- S(Sleeping):进程处于睡眠状态,等待某些事件的发生。可能原因包括:
- 进程在等待某个事件的发生,如I/O操作的完成、信号的到达等。
- 进程被阻塞,等待某个条件的满足。
- D(Uninterruptible sleep):进程处于不可中断的睡眠状态,通常发生在与硬件设备交互时。可能原因包括:
- 进程正在等待硬件设备的响应,无法被中断。
- 进程在等待某些硬件资源的释放。
- Z(Zombie):僵尸进程,进程已经终止,但是其父进程尚未对其进行资源清理。可能原因包括:
- 父进程没有正确处理子进程的退出状态。
- 父进程已经终止,无法进行清理操作。
- T(Stopped):进程处于停止状态,可能是由于收到了停止信号。可能原因包括:
- 进程收到了停止信号,如SIGSTOP或SIGTSTP。
- 进程在调试过程中被暂停。
这些是常见的进程状态及其可能的原因。进程的状态会根据不同的情况和系统环境发生变化。通过观察进程的状态,可以帮助诊断进程的运行情况,如是否正常运行、是否等待某些事件、是否发生了异常等。
15.top输出中vsz %vsz stack rss dirty 分别是什么意思
在 "top" 命令的输出中,以下字段表示:
- VSZ(Virtual Set Size):进程使用的虚拟内存大小(以KB为单位)。它包括进程的代码、数据、堆、共享库以及映射的文件等。
- %VSZ(Virtual Set Size的百分比):进程使用的虚拟内存大小占系统总虚拟内存的百分比。
- Stack(栈大小):进程使用的栈空间大小(以KB为单位)。栈用于存储局部变量、函数调用等。
- RSS(Resident Set Size):进程当前使用的物理内存大小(以KB为单位)。它表示实际驻留在物理内存中的部分,包括进程的代码、数据和堆。
- Dirty(脏页):进程所占用的内存中已经被修改但尚未写回到磁盘的部分(以KB为单位)。脏页是指进程对内存中的数据进行了修改,但尚未同步到磁盘。
这些字段提供了关于进程内存使用情况的信息。VSZ表示进程使用的虚拟内存大小,而RSS表示实际使用的物理内存大小。%VSZ表示进程虚拟内存大小在系统总虚拟内存中的比例。Stack字段显示进程使用的栈空间大小。Dirty字段表示进程所占用的内存中被修改但尚未写回磁盘的部分。
这些字段可以帮助您了解进程的内存占用情况,判断进程的内存使用情况是否合理以及是否存在内存泄漏等问题。
-
new 失败直接抛出
bad_alloc
异常,不返回 null 。若不处理异常,应当用new(std::nothrow)
代替new -
malloc_stats 打印 glibc 分配内存信息。
void print_mem_info(const char* s) {
printf("------------------------\n");
printf("-- %s\n", s);
printf("------------------------\n");
malloc_stats();
}
int main(int argc, char** argv) {
int cnt = atoi(argv[1]);
std::list<char*> free_list;
print_mem_info("begin");
for (int i = 0; i < cnt; i++) {
char* m = new char[1024 * 64];
memset(m, 'a', 1024 * 64);
free_list.push_back(m);
}
print_mem_info("alloc blocks");
for (auto& v : free_list) {
delete[] v;
}
print_mem_info("free blocks");
free_list.clear();
print_mem_info("clear list.");
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库