realloc学习笔记

embedded/2024/11/14 20:54:10/

realloc_0">realloc学习笔记

最近用到curl做业务,引了自己写封装的curl库,看到的数据回调函数中使用了realloc函数,处理逻辑有些想不请来了,不排除这个函数是copy别人的。分析一下源码,做一下笔记

源码

    size_t STL_CURL::write_function_callback(void *data, size_t size, size_t nmemb, void *userp){size_t realsize = size * nmemb;CurlMemory *mem = (CurlMemory *)userp;char *ptr = (char *)realloc((void *)(mem->response), mem->size + realsize + 1); // 注意:realloc第一个参数为空或者内存空间,注意初始化if (ptr == NULL)return 0; /* out of memory! */mem->response = ptr;memcpy(&(mem->response[mem->size]), data, realsize);mem->size += realsize;mem->response[mem->size] = 0;return realsize;}

分析

这是一个用于处理 libcurl 数据写入回调函数 STL_CURL::write_function_callback。这个回调函数处理从服务器接收到的数据。

size_t STL_CURL::write_function_callback(void *data, size_t size, size_t nmemb, void *userp)
{size_t realsize = size * nmemb;CurlMemory *mem = (CurlMemory *)userp;
  • size_t realsize = size * nmemb;

    • size 是每个元素的大小(通常是字节数)。
    • nmemb 是元素的数量。
    • realsize 计算出从 libcurl 接收到的实际数据大小,即 data 指向的数据块的总大小。
  • CurlMemory *mem = (CurlMemory *)userp;

    • userp 是自定义的数据指针,传递给 libcurl 的回调函数。在这里,它被转换为 CurlMemory 类型的指针。CurlMemory 是一个用于存储接收到的数据的结构体,结构体包含一个指向存储数据的指针 response 和数据的当前大小 size
    char *ptr = (char *)realloc((void *)(mem->response), mem->size + realsize + 1); if (ptr == NULL)return 0; /* out of memory! */
  • char *ptr = (char *)realloc((void *)(mem->response), mem->size + realsize + 1);
    • realloc 是一个标准库函数,用于调整内存块的大小。
    • 这里的 realloc 调整了 mem->response 的内存大小,使其能够容纳现有数据 mem->size 加上新接收到的数据 realsize,再加上一个额外的字节(通常用于存储字符串的终止符 '\0')。
    • 如果 mem->response 为空(例如,第一次接收到数据时),realloc 的第一个参数可以是 NULL,它会像 malloc 一样分配新内存。
    • 如果内存分配失败,ptr 将是 NULL,在这种情况下,函数返回 0,表示内存不足,从而终止数据接收。
    mem->response = ptr;memcpy(&(mem->response[mem->size]), data, realsize);mem->size += realsize;mem->response[mem->size] = 0;
  • mem->response = ptr;

    • 将新分配的内存地址存回 mem->response,这确保了如果 realloc 成功,mem->response 指向的内存块是扩展后的。
  • memcpy(&(mem->response[mem->size]), data, realsize);

    • memcpy 是标准库函数,用于将 data 指向的 realsize 字节数据复制到 mem->response 的末尾。
    • &(mem->response[mem->size]) 计算出数据复制的目标地址,这里是 mem->response 当前内容的末尾。
  • mem->size += realsize;

    • 更新 mem->size 以反映新接收到的数据量。
  • mem->response[mem->size] = 0;

    • mem->response 的末尾添加一个空字符 '\0',将 response 作为一个以空字符结尾的字符串。这样,数据可以被当作一个标准 C 字符串处理。
    return realsize;
}
  • return realsize;

    • 返回实际处理的字节数。libcurl 使用此值来确定数据处理是否成功。如果返回值小于 realsizelibcurl 会认为发生了错误,并停止传输。
  • 这个回调函数通过 realloc 动态调整内存大小,以适应从 libcurl 接收到的任意大小的数据块。

  • 将接收到的数据追加到 mem->response 中,并确保它以空字符 '\0' 结尾。

  • 如果内存分配失败,回调函数会返回 0,从而中止操作。

realloc_86">realloc函数

realloc 函数会将原有指针指向的数据拷贝到新的内存空间中。

当调用 realloc 时,它的行为可以分为以下几种情况:

  1. 扩展现有内存块: 如果新的内存大小比当前大小大,且在原内存块后面有足够的连续空间,realloc 可能会直接扩展原来的内存块,并返回相同的指针。此时,数据保持不变,原指针数据不会被移动。

  2. 缩小现有内存块: 如果新的内存大小比当前大小小,realloc 也可能会在原位置直接缩小内存块。数据仍保持不变。

  3. 分配新的内存块: 如果不能扩展当前内存块(比如当前内存块后面没有足够的连续空间),realloc 会分配新的内存块,并将原内存块的数据复制到新分配的内存块中。此时,原有的指针会被替换为指向新内存块的指针,而原来的内存块会被释放。

  4. 分配失败: 如果分配新的内存块失败,realloc 返回 NULL,原来的内存块保持不变且不被释放。

例子:

int *arr = malloc(5 * sizeof(int)); // 分配初始内存
// 假设 arr 中已填充一些数据// 增加大小并重新分配内存
int *new_arr = realloc(arr, 10 * sizeof(int));if (new_arr) {// 如果重新分配成功,arr 中的数据已被复制到 new_arr 中arr = new_arr;
} else {// 重新分配失败,原来的内存块仍然有效,arr 不变
}

在这个例子中,realloc 将会在必要时分配一个新的内存块,并将 arr 中的数据复制到新的内存位置。如果成功,原来的内存块会被释放,新的内存块地址被返回。


http://www.ppmy.cn/embedded/96616.html

相关文章

【Redis】Redis 初探:特性、应用场景与高并发架构演进之路

目录 初识 Redis关于 Redis服务端高并发分布式结构演进之路概述常⻅概念基本概念应⽤(Application)/ 系统(System)模块(Module)/ 组件(Component)分布式(Distributed&…

python项目部署:Nginx和UWSGI认识

Nginx: HTTP服务器,反向代理,静态资源转发,负载均衡,SSL终端,缓存,高并发处理。 UWSGI: Python应用程序服务器,WSGI兼容,多进程管理,快速应用部署,多种协议支…

DM8 数据库查询版本号以及授权到期时间SQL

1.查看操作系统信息 [root@localhost ~]# cat /etc/.kyinfo [dist] name=Kylin milestone=Server-V10-GFB-Release-ZF9_01-2204-Build03 arch=arm64 beta=False time=2023-01-09 11:04:36 dist_id=Kylin-Server-V10-GFB-Release-ZF9_01-2204-Build03-arm64-2023-01-09 11:04:…

洛谷 P3369 【模板】普通平衡树

目录 tags中文题面题目描述输入格式输出格式样例 #1样例输入 #1样例输出 #1 提示 思路代码 tags 树状数组 数据结构 中文题面 题目描述 您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作:…

代码随想录算法训练营第二天 | 滑动窗口 + 螺旋矩阵

文章目录 Leetcode209 长度最小的连续子数组双指针/滑动窗口 Leetcode59 螺旋矩阵初始思路:找规律按索引填充 Leetcode209 长度最小的连续子数组 链接:https://leetcode.cn/problems/minimum-size-subarray-sum/ 代码随想录: https://programmercarl.com…

Java面试八股之简述消息队列P2P模型

简述消息队列P2P模型 P2P模型组件 生产者(Producer):生产者是创建并发送消息的实体。它可以是一个应用程序、服务或任何产生数据的系统组件。 队列(Queue):队列是存储消息的数据结构。在P2P模型中,队列扮演着中间存储的角色,负…

[Qt][对话框][上]详细讲解

目录 0.是什么?1.对话框的分类2.混合属性对话框 0.是什么? ⼀些不适合在主窗⼝实现的功能组件可以设置在对话框中对话框通常是⼀个顶层窗⼝,出现在程序最上层,⽤于实现短期任务或者简洁的⽤⼾交互Qt中使用QDialog类表示对话框&am…

Unity脚本一键修改所有预制体

需求 预制体中的Text组件默认是使用Unity的内置字体Arial。 但是在Unity2022之后,Text组件就被弃用了,内置字体Arial也移除了。 如果项目从2022之前的版本升到2022,那么Text组件的字体文件会自动改为LegacyRuntime.ttf文件。 其中LegacyR…