岗位情况
公司详情
领域:音视频
项目:云手机平台,webRTC
薪资:
3500(全勤情况下)
双休 (可能周六加班)
9:00-6:00,弹性
转正后:
8-10k
笔试
链表和数组的区别
int *p1[10];和int (*p2)[10];
int *p1[10]
和int (*p2)[10]
是两个不同的声明形式,它们有以下区别:
int *p1[10]
:这是一个数组,数组中每个元素都是指向int
类型的指针。可以将其理解为一个包含 10 个指针的数组。每个指针可以指向一个或多个int
值。cppCopy Codeint *p1[10];
int (*p2)[10]
:这是一个指针,指向一个包含 10 个int
元素的数组。可以将其理解为一个指向数组的指针。cppCopy Codeint (*p2)[10];
总结:
int *p1[10]
声明了一个包含 10 个指针元素的数组。
int (*p2)[10]
声明了一个指向包含 10 个int
元素的数组的指针。
molloc()是否有错?
手写快排和冒泡
#include <iostream>
using namespace std;
// 交换函数,用于交换数组中两个元素的位置
void swap(int& a, int& b) {
int temp = a;
a = b;
b = temp;
}
// 划分函数,将数组划分为左右两部分,并返回划分后基准元素的索引
int partition(int arr[], int low, int high) {
int pivot = arr[high]; // 选择最右边的元素作为基准
int i = low - 1; // i表示小于基准元素的区域边界
for (int j = low; j <= high - 1; j++) {
if (arr[j] < pivot) {
i++;
swap(arr[i], arr[j]); // 将小于基准的元素移到左边区域
}
}
swap(arr[i + 1], arr[high]); // 将基准元素放到正确的位置上
return i + 1; // 返回基准元素的索引
}
// 快速排序函数
void quickSort(int arr[], int low, int high) {
if (low < high) {
int pivotIndex = partition(arr, low, high); // 划分数组
quickSort(arr, low, pivotIndex - 1); // 对左半部分递归排序
quickSort(arr, pivotIndex + 1, high); // 对右半部分递归排序
}
}
// 打印数组
void printArray(int arr[], int size) {
for (int i = 0; i < size; i++) {
cout << arr[i] << " ";
}
cout << endl;
}
int main() {
int arr[] = {9, 2, 5, 7, 1, 8, 3};
int n = sizeof(arr) / sizeof(arr[0]);
cout << "原始数组:";
printArray(arr, n);
quickSort(arr, 0, n - 1);
cout << "排序后的数组:";
printArray(arr, n);
return 0;
}
UDP和TCP的区别和应用
UDP和TCP都属于计算机网络中的传输层协议,但它们有以下区别和不同的应用场景:
可靠性: TCP是一种可靠性协议,它保证了数据传输的可靠性,确保数据的完整性和顺序。UDP则是一种不可靠性协议,它不对数据传输的可靠性做出任何保证,因此可能会丢失或重复。
连接性: TCP是面向连接的协议,必须先建立连接然后再进行数据传输,以保证数据的正确传输。UDP则是无连接的协议,发送数据前不需要建立连接,每个数据包都是独立的。
速度: 由于TCP需要保证数据传输的可靠性和顺序,因此它通常会比UDP慢一些。UDP则相对来说更快,因为它不需要进行错误检查、确认和重传等操作。
应用场景: 在需要高可靠性、顺序传输的数据传输场景下(如文件传输、电子邮件等),TCP是首选协议。在需要快速传输且可靠性不是第一考虑因素的场景下(如音频、视频、游戏等),UDP是首选协议。
总之,TCP和UDP都有各自的优缺点和适用场景,需要根据具体的情况选择合适的协议
技术面
自我介绍
项目自己做的吗?
os设计是moon课的,我负责实现
项目中最难的,影响深刻的点?
os,plic 设备,总是出异常,中断,系统总是崩,
解决方法:查,
50多个终端异常码,对着异常码查。
然后看到底是哪出问题?
多线程同步?
”锁和cv信号量?共享内存
惊群效应,多个线程等待一个锁,
该锁释放,所有线程全国都起来抢一个锁,造成巨量浪费
用信号量(这里说错了),就只唤醒一个,
(开始胡说。。。。)本质上是一个双锁,外锁和内锁,当前持有锁的线程,在内锁中执行代码,获得内锁时释放外锁
第一个等待该锁的(也就是下一个要执行的)获得外锁等待内锁。
等真正到自己执行时,获得内锁释放外锁。
就这样,实现了只通知一个,不会引起惊群“
------
事后,其实是是条件变量std::condition_variable,cv.notify_one()至于后面的解释,我也不知道是不是对的。
您的回答有一些问题和混淆。
首先,锁和条件变量是多线程同步中常用的工具,它们可以协调不同线程之间的执行。当一个线程需要改变某个共享资源的值时,需要先获取锁来保证互斥性,然后再修改共享资源的值。如果另一个线程希望访问同一个共享资源,它需要等待锁的释放。当一个线程已经完成操作后,需要释放锁来允许其他线程对共享资源进行操作。
其次,信号量和条件变量是不同的同步机制。信号量是一种计数器,可以用来控制并发执行的线程数量。信号量具有两个基本操作:wait(等待)和signal(发布)。wait 操作会减少信号量的值,如果信号量的值变为 0,则在该信号量上等待的线程会被阻塞。signal 操作会增加信号量的值,并且唤醒至少一个在该信号量上等待的线程。
而条件变量是一种在多线程环境下用于线程间等待和通知的机制。它可以实现一些比较复杂的同步模式。条件变量包含一个等待队列和两个基本操作:wait 和 signal。wait 操作会使当前线程在条件变量的等待队列中等待,同时释放相关的锁。当另一个线程完成某些操作并发出 signal 信号时,被阻塞的线程会被唤醒,并重新尝试获取相关的锁。
最后,您提到的“双锁”机制,我不太理解它的具体含义。如果两个锁都需要获得才能执行代码,那么就相当于一个嵌套的互斥锁,这种情况下可能会导致死锁。因此,通常情况下只需要一个锁来保证互斥性。
综上所述,您回答的部分内容有误,建议在面试中注重对术语和概念的准确理解和表达,同时多思考实际问题中的具体场景和应用。
死锁
成因:
多个锁
锁的获取顺序不一样
资源不释放
解决方法:
尽量少用锁
确保锁的顺序一致
获取不了锁,一应该释放已有锁
(脑瘫瞎说)
哲学家问题,大家先哪左边锁,又拿右边锁
多态
设计模式中用的多
依赖倒置原则
高层模块不应该直接依赖底层模块,而应该依赖其抽象
这样高层模块不至于因为底层实现的更改而导致要跟着改变
c++内存管理
C++内存管理是指在C++程序中有效地分配和释放内存资源的过程。C++是一种直接支持内存管理的语言,它提供了各种机制来管理内存,包括手动管理和自动管理。下面是对C++内存管理的详细解释:
1. 手动内存管理:
C++允许开发人员手动分配和释放内存,这意味着程序员负责在需要时分配内存,并在使用完后手动释放它。手动管理内存的主要机制是通过`new`和`delete`运算符。
-
new
运算符:`new`运算符用于在堆上分配内存,并返回指向分配的内存的指针。语法如下:```cpp
type *ptr = new type;
```
这将分配一个类型为`type`的对象,并将指针`ptr`指向该对象。
-
delete
运算符:`delete`运算符用于释放由`new`分配的内存。语法如下:```cpp
delete ptr;
```
这将释放`ptr`指向的内存。
手动内存管理需要程序员显式地跟踪内存的分配和释放,确保在不再使用时及时释放内存,否则可能导致内存泄漏或悬空指针等问题。
2. 自动内存管理:
C++还提供了自动内存管理的机制,以减轻程序员手动管理内存的负担。自动内存管理主要通过两种方式实现:栈上分配和智能指针。
- 栈上分配:栈是一种自动管理内存的数据结构,它用于存储局部变量和函数调用的上下文信息。在C++中,局部变量的内存分配和释放是自动进行的。当变量超出其作用域时,其内存将自动释放。例如:
```cpp
void foo() {
int x = 10; // 变量x在栈上分配内存
// ...
} // 变量x超出作用域,内存自动释放
```
- 智能指针:智能指针是一种封装了指针的对象,它可以自动管理动态分配的内存。通过智能指针,内存的分配和释放可以自动进行,从而避免手动管理内存的错误和繁琐。C++标准库提供了两种智能指针:`std::unique_ptr`和`std::shared_ptr`。
-
std::unique_ptr
:`std::unique_ptr`是一种独占指针,它拥有对动态分配内存的唯一所有权。当`std::unique_ptr`超出作用域时,它自动释放所拥有的内存。示例:```cpp
std::unique_ptr<int> ptr = std::make_unique<int>(10); // 分配一个int类型的对象
// ...
```
-
std::shared_ptr
:`std::shared_ptr`是一种共享指针,它允许多个智能指针共享对同一块内存的所有权。内部使用引用计数来跟踪共享的指针数量,并在没有指针引用时自动释放内存。示例:```cpp
std::shared_ptr<int> ptr1 = std::make_shared<int>(10); // 分配一个int类型的对象
std::shared_ptr<int> ptr2 = ptr1; // 共享ptr1指向的内存
// ...
```
使用智能指针可以更安全地管理内存,避免内存泄漏和悬空指针问题。然而,仍然需要注意循环引用可能导致的内存泄漏问题。
除了手动和自动内存管理之外,C++还提供了一些其他的内存管理技术和概念,例如:
- 内存分配器(Memory Allocators):内存分配器是一种用于管理堆上内存分配和释放的机制。C++标准库提供了一些内存分配器,例如`std::allocator`和`std::allocator_traits`。开发人员也可以自定义内存分配器来满足特定的需求。
- RAII(Resource Acquisition Is Initialization):RAII是一种C++的编程范式,它利用对象的生命周期来管理资源(包括内存)。通过在对象的构造函数中获取资源,在析构函数中释放资源,可以确保资源在对象生命周期结束时被正确释放。智能指针就是基于RAII的思想实现的。
- 运算符重载:C++允许运算符重载,包括`new`和`delete`运算符。通过重载这些运算符,开发人员可以自定义内存分配和释放的行为,例如使用自定义的内存分配器或实现特定的内存管理策略。
总结起来,C++提供了多种内存管理的机制和技术,包括手动管理、自动管理(栈上分配和智能指针)、内存分配器、RAII和运算符重载。选择适当的内存管理方式取决于具体需求和情况,开发人员需要在性能、安全性和可维护性之间做出权衡。
全局变量和静态变量
全局变量和静态变量在C++中有一些重要的区别。下面是它们之间的主要区别:
1. 作用域:
- 全局变量:全局变量在整个程序中可见,可以在任何函数内部访问。
- 静态变量:静态变量的作用域限定在声明它的函数或文件内部,只能在所在的函数内部或文件内部访问。
2. 存储位置:
- 全局变量:全局变量存储在全局/静态区,它在程序启动时创建,在程序结束时销毁。
- 静态变量:静态变量也存储在全局/静态区,它在程序启动时创建,在程序结束时销毁。
3. 生命周期:
- 全局变量:全局变量的生命周期与整个程序的生命周期相同,即它们在程序启动时创建,在程序结束时销毁。
- 静态变量:静态变量的生命周期延长到整个程序的生命周期,即使在所在的函数内部,静态变量的值在函数调用结束后也会保留。
4. 默认初始化:
- 全局变量:全局变量在定义时会自动初始化为默认值,如0或空指针,除非显式指定其他初始值。
- 静态变量:静态变量在定义时会自动初始化为默认值,如0或空指针,除非显式指定其他初始值。
5. 访问权限:
- 全局变量:全局变量可以被程序中的任何函数访问和修改。
- 静态变量:静态变量可以被声明它的函数内部访问和修改,但对于其他函数是不可见的。
6. 编译单元:
- 全局变量:全局变量可以跨越多个编译单元(多个源文件)共享。
- 静态变量:静态变量只能在声明它的函数或文件内部共享。
需要注意的是,静态变量也可以在类中声明,这种情况下它们被称为静态成员变量,与普通的静态变量有一些区别。静态成员变量在类的所有实例之间共享,而不是每个实例都有自己的拷贝。
hr面
项目自己写的吗?
同上
获奖经历
自己的缺点
内向,怕生.....
什么时候意识到这一点?
学生会面试,演讲,说话不利索
实习面试
工作时遇到要和同事合作的任务怎么办?
第一次见面时尽量记住每个人的名字,大概认识一下
既然是与和同事合作,那就去与哪位同事先商量,分配一下任务。
(被打断)hr:"不不不,任务大多不是这么明确告诉你与具体的某某合作,你要自己判断"
我:?????(心理)
哦哦,感谢你提醒了我,在第一次见面时可能要先了解每个同事大概是做什么的,到真正需要与人合作时才不至于不知道找谁。
事后总结
应该再讲一下向别人请教时,虚心请教
反问:薪资、假期、上班时间
最上面
(可能加班,每年4月要上交)
WebRTC
一对多/多对多通信
如果需要实现一对多或多对多通信,按照上面代码的方式,那么在有其他客户端加入时就需要实时创建一个新的 peer,对其进行协商。这种方式产生的架构叫 Mesh。Mesh 中,每个客户端都是可以直接连接到其他端点的。
与 Mesh 对应的架构是 MCU,MCU 则是有一个中央服务器,每个端都连接到此服务器。中央服务器将接收每个端点的数据,因此可以对数据进行处理,如合并、调整等。
Mesh ???
WebRTC 简单入门与实践 - 掘金 (juejin.cn)
改linux内核
安卓镜像
ia s
驱动
游戏驱动
linux的应用
libevent库