函数运行时在内存中是什么样子?

本文深入探讨了函数在运行时的内存表现,特别是函数调用栈帧的工作原理,包括控制转移、参数传递、局部变量存储以及栈溢出问题。通过对函数调用过程的分析,揭示了栈在程序执行中的关键作用。
摘要由CSDN通过智能技术生成

在开始本篇的内容前,我们先来思考几个问题。

1. 我们先来看一段简单的代码:

void func(int a) {
  if (a > 100000000) return;
  
  int arr[100] = {0};
  func(a + 1);
}

你能看出这段代码会有什么问题吗?

2. 我们在上一篇文章《高性能高并发服务器是如何实现的》中提到了一项关键技术——协程,你知道协程的本质是什么吗?有的同学可能会说是用户态线程,那么什么是用户态线程,这是怎么实现的?

3. 函数运行起来后在内存中是什么样子?

这几个问题看似没什么关联,但这背后都指向一样东西,这就是所谓的函数运行时栈run time stack

接下来我们就好好看看到底什么是函数运行时栈,为什么彻底理解函数运行时栈对程序员来说非常重要。

从进程、线程到函数调用

汽车在高速上行驶时有很多信息,像速度、位置等等,通过这些信息我们可以直观的感受汽车的运行时状态。

同样的,程序在运行时也有很多信息,像有哪些程序正在运行、这些程序执行到了哪里等等,通过这些信息我们可以直观的感受系统中程序运行的状态。

其中,我们创造了进程、线程这样的概念来记录有哪些程序正在运行,关于进程和线程的概念请参见《看完这篇还不懂进程、线程与线程池你来打我》。

进程和线程的运行体现在函数执行上,函数的执行除了函数内部执行的顺序执行还有子函数调用的控制转移以及子函数执行完毕的返回。其中函数内部的顺序执行乏善可陈,重点是函数的调用。

因此接下来我们的视角将从宏观的进程和线程拉近到微观下的函数调用,重点来讨论一下函数调用是怎样实现的。

函数执行的活动轨迹:栈

玩过游戏的同学应该知道,有时你为了完成一项主线任务不得不去打一些支线的任务,支线任务中可能还有支线任务,当一个支线任务完成后退回到前一个支线任务,这是什么意思呢,举个例子你就明白了。

假设主线任务西天取经A依赖支线任务收服孙悟空B和收服猪八戒C,也就是说收服孙悟空B和收服猪八戒C完成后才能继续主线任务西天取经A;

支线任务收服孙悟空B依赖任务拿到紧箍咒D,只有当任务D完成后才能回到任务B;

整个任务的依赖关系如图所示:

现在我们来模拟一下任务完成过程。

首先我们来到任务A,执行主线任务:

如果对于大尺寸的图像使用cv::warpAffine速度太慢,可以考虑使用OpenCV提供的cv::cuda::warpAffine函数进行加速处理。这个函数是OpenCV的CUDA模块函数,可以利用GPU的并行计算能力加速图像变换操作。 下面是使用cv::cuda::warpAffine函数对3072x2048的图像进行加速处理的示例代码: ``` c++ cv::Mat inputImage = cv::imread("input.jpg"); cv::Mat outputImage; // 创建GPU内存 cv::cuda::GpuMat inputGpu, outputGpu; // 将输入图像上传到GPU内存 inputGpu.upload(inputImage); // 定义旋转心 cv::Point2f center(inputImage.cols / 2, inputImage.rows / 2); // 定义旋转角度 double angle = 45; // 定义缩放比例 double scale = 1; // 计算旋转矩阵 cv::Mat rotateMat = cv::getRotationMatrix2D(center, angle, scale); // 将旋转矩阵上传到GPU内存 cv::cuda::GpuMat rotateMatGpu(rotateMat); // 加速warpAffine函数 cv::cuda::warpAffine(inputGpu, outputGpu, rotateMatGpu, inputImage.size(), cv::INTER_LINEAR + cv::WARP_INVERSE_MAP); // 将输出图像从GPU内存下载到CPU内存 outputGpu.download(outputImage); // 显示输入和输出图像 cv::imshow("input", inputImage); cv::imshow("output", outputImage); cv::waitKey(0); ``` 在上述代码,我们首先读取一张3072x2048的图像,然后将其上传到GPU内存。接着,我们定义旋转心、旋转角度和缩放比例,并使用cv::getRotationMatrix2D函数计算了旋转矩阵。然后,我们将旋转矩阵上传到GPU内存,并使用cv::cuda::warpAffine函数,将输入图像inputGpu进行仿射变换得到输出图像outputGpu。其,我们使用了cv::INTER_LINEAR和cv::WARP_INVERSE_MAP两个加速标志,前者表示使用双线性插值算法进行图像采样,后者表示使用逆变换矩阵进行变换。最后,我们将输出图像从GPU内存下载到CPU内存,并将输入和输出图像进行显示,然后等待用户按下任意键退出程序。 需要注意的是,使用cv::cuda::warpAffine函数需要支持CUDA加速的硬件和相关的CUDA驱动程序和CUDA工具包。如果没有支持CUDA加速的硬件,可以考虑使用其他的图像处理库或者算法进行加速处理。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值