【代码阅读】darknet源码阅读(一):list.c/list.h

目录

1.list.h

2.list.c

3.额外的知识

3.1.关于#ifdef  __cplusplus    extern "C"

3.2 xmalloc


先放上参考资料:https://blog.youkuaiyun.com/caicaiatnbu/category_9096319.html

就是跟着别人的解析,一步一步去看darknet的结构。顺道加深C的学习,努力学习中。。

[使用的是这个版本的  https://github.com/AlexeyAB/darknet,因为一直在更新]

1.list.h

定义了节点和列表,申明了操作函数。可以看到,这个list就是简单地链表操作

#ifndef LIST_H
#define LIST_H

//这里先构建两个结构:节点和列表
typedef struct node{
    void *val;//空指针,存放当前节点的值
    struct node *next;//当前节点的下一节点
    struct node *prev;//当前节点的上一节点
} node;

typedef struct list{
    int size;//当前链表的长度
    node *front;//当前链表的第一个节点
    node *back;//当前链表的最后一个节点
} list;

#ifdef __cplusplus
extern "C" {
#endif
//定义的函数操作
list *make_list();//初始化链表
int list_find(list *l, void *val);//查找链表
void list_insert(list *, void *);//插入链表
void **list_to_array(list *l);//存储链表到数组

//释放存储空间
void free_list_val(list *l);
void free_list(list *l);
void free_list_contents(list *l);
void free_list_contents_kvp(list *l);

#ifdef __cplusplus
}
#endif
#endif

2.list.c

PS:关于xmalloc函数,我以为是X-分配器中的一部分,所以做了注解,但是读到utils.c文件的时候,发现就是源码自己的一个开辟空间的函数,只是多了一个判断而已。附上代码:

xmalloc函数:

//malloc构建size大小的存储空间
void *xmalloc(size_t size) {
    void *ptr=malloc(size);
    if(!ptr) {
        malloc_error();
    }
    return ptr;
}


//calloc构建size大小的存储空间
void *xcalloc(size_t nmemb, size_t size) {
    void *ptr=calloc(nmemb,size);
    if(!ptr) {
        calloc_error();
    }
    return ptr;
}

继续说我们今天看的list.c

#include <stdlib.h>
#include <string.h>
#include "list.h"
#include "utils.h"
#include "option_list.h"

//1.初始化链表
list *make_list()
{
    list* l = (list*)xmalloc(sizeof(list));//分配链表的存储空间
    l->size = 0;//链表长度
    l->front = 0;//链表的头指针
    l->back = 0;//链表的尾指针
    return l;//返回初始化的链表
}

/*
void transfer_node(list *s, list *d, node *n)
{
    node *prev, *next;
    prev = n->prev;
    next = n->next;
    if(prev) prev->next = next;
    if(next) next->prev = prev;
    --s->size;
    if(s->front == n) s->front = next;
    if(s->back == n) s->back = prev;
}
*/

//删除链表最后一个节点
void *list_pop(list *l){
    if(!l->back) return 0;//如果链表的最后一个节点为null,返回0.【!l->back这里表示链表为空】
    //如果链表最后一个节点存在,链表不为空
    node *b = l->back;//中间节点b指向链表最后一个节点
    void *val = b->val;//获取最后一个节点的值
    l->back = b->prev;//将链表的最后一个节点指向b的上一个节点,也就是原链表的倒数第二个节点
    if(l->back) l->back->next = 0;//将链表尾指针的next节点设为null【切断原链表倒数第一个节点和倒数第二个节点的联系】
    free(b);//释放中间节点的存储空间
    --l->size;//将链表长度减一

    return val;//返回删除节点的值
}

//链表的插入操作,按顺序插在最末
void list_insert(list *l, void *val)
{
    node* newnode = (node*)xmalloc(sizeof(node));//首先创建一个待被插入的节点newnode
    newnode->val = val;//赋值
    newnode->next = 0;//因为是最末节点,所以nextnode=null

    if(!l->back){//如果当前链表为空
        l->front = newnode;//链表的头节点==newnode
        newnode->prev = 0;//newnode的上一节点也应该是null
    }else{//如果不为空
        l->back->next = newnode;//链表的最后节点的next节点就为待插入的节点
        newnode->prev = l->back;//newnode的上一节点应该是链表之前的最后节点
    }
    l->back = newnode;//新链表的最后节点,无论是什么情况,都应该是插入的节点
    ++l->size;//链表长度加一
}

//下面都是释放空间的操作

//释放节点空间,从传入节点n开始,后面的节点空间全部释放
void free_node(node *n)
{
    node *next;
    while(n) {
        next = n->next;//获取下一释放节点
        free(n);//释放当前节点
        n = next;//循环更新
    }
}

//释放链表的值空间,从链表头结点开始,全部释放
void free_list_val(list *l)
{
    node *n = l->front;
    node *next;
    while (n) {
        next = n->next;
        free(n->val);
        n = next;
    }
}

//释放整个链表l的存储空间
void free_list(list *l)
{
    free_node(l->front);//从节点开始释放链表
    free(l);//释放链表空间
}

//不是跟free_list_val相似吗
void free_list_contents(list *l)
{
    node *n = l->front;
    while(n){
        free(n->val);
        n = n->next;
    }
}

//这里突然有一个结构体kvp,被定义在"option_list.h"头文件中
/*
是用来提取.cfg文件中的关键字的
typedef struct{
    char *key;
    char *val;
    int used;
} kvp;
*/
//也是释放空间,具体是什么操作,等我往后面看
void free_list_contents_kvp(list *l)
{
    node *n = l->front;
    while (n) {
        kvp* p = (kvp*)n->val;
        free(p->key);
        free(n->val);
        n = n->next;
    }
}

//将链表中所有的节点进行保存
// 因为每个节点里保存的值是void类型的指针,故指针的指针,即二维指针【?】
void **list_to_array(list *l)
{
    // 分配存储空间, 长度l-size, 每个空间大小为一个void类型指针
    void** a = (void**)xcalloc(l->size, sizeof(void*));
    int count = 0;
    node *n = l->front;//从链表初始节点开始
    while(n){
        a[count++] = n->val;//存放值(void*型)
        n = n->next;//更新循环
    }
    return a;
}

3.额外的知识

3.1.关于#ifdef  __cplusplus    extern "C"

关键字:extern "C" 表示编译生成的内部符号名使用C约定

#ifdef  __cplusplus
extern "C" {
#endif

// 代码

#ifdef  __cplusplus
}
#endif

这个代码的意思是【参考:https://www.cnblogs.com/nx520zj/p/5920782.html】:

为了在C++代码中调用用C写成的库文件,就需要用extern"C"来告诉编译器:这是一个用C写成的库文件,请用C的方式来链接它们。两者语言的编译规则不一样。编译器对函数名的处理方法也不一样。

在C++中支持函数重载,而C中是不支持函数重载的。

3.2 xmalloc

【参考:https://www.oschina.net/translate/replace-malloc-free-with-a-fast-fixed-block-memory?print

参考文献中说:X-分配器的基石,替换系统的malloc()free()函数。

和大部分固定块分配器不同,X-分配器可以在预先不知道块大小和数量的前提下,以完全动态的方式运行。X-分配器也会为你提供所有的固定块管理方式。完美运行在任何PC或嵌入式设备上。此外,它还提供了内存的动态使用图可用于内存使用情况的统计。

如果你有一个应用程序真的需要反复申请堆内存,并引起了性能问题,或者你担心程序中的堆碎片问题,把 Allocator/xallocator 整合到你的程序里可能会解决这些问题。

YOLOlayer.h是个头文件,其中定义了YOLO层的相关函数和结构体。该头文件包含了以下内容: 1. 构造YOLO层的函数make_yolo_layer,用于创建YOLO层的实例。 2. YOLO层的前向传播函数forward_yolo_layer,用于执行YOLO层的前向传播操作。 3. YOLO层的反向传播函数backward_yolo_layer,用于执行YOLO层的反向传播操作。 4. 调整YOLO层大小的函数resize_yolo_layer,用于调整YOLO层的输入尺寸。 5. 计算YOLO层检测结果数量的函数yolo_num_detections,用于计算YOLO层的检测结果数量。 此外,该头文件还包含了些与GPU相关的函数,如forward_yolo_layer_gpu和backward_yolo_layer_gpu,用于在GPU上执行YOLO层的前向传播和反向传播操作。\[1\] YOLOlayer.h是darknet源码中的个文件,主要用于实现YOLO v3中的三个detection层,分别对应52*52*75,26*26*75和13*13*75的输出。这些层是YOLO v3论文的核心部分。\[2\] 此外,YOLOlayer.h还与TensorRT加速YOLOv5相关。可以通过GitHub手动获取对应版本的tensorrtx,也可以使用相应版本的指令进行安装。\[3\] #### 引用[.reference_title] - *1* *2* [【darknet源码解析-20】yolo_layer.h 和 yolo_layer.c 源码解析](https://blog.csdn.net/caicaiatnbu/article/details/102962445)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^koosearch_v1,239^v3^insert_chatgpt"}} ] [.reference_item] - *3* [YOLOv5-v3.1,推理环境配置、Tensorrt加速步到位(各种问题总结,吐血整理)](https://blog.csdn.net/knowledge112233/article/details/126262744)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^koosearch_v1,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值