STL源码--alloc

C++内存分配详解五:std::alloc源码剖析 标准容器分配器源码剖析 阅读详情



//关于内存管理与配置,标准做法与内存池做法,内存池解决内存碎片的问题
//首先对于第一级配置器,我们直接使用new操作符就可以,第二级配置器是我们的主要战场。
//那么我们为什么设计制造第一级配置器呢?直接使用new就好了。
//首先,明确我们为什么设计两级配置器,因为我们针对不同的应用可以选择合适的配置器,那么我们就必须让配置器的使用
//对象看不出两者的差异:即,两者要有相同的接口。
//怎么样的接口?配置内存,释放内存,提供像new一样的功能。stl中有三个接口:allocate,deallocate,reallocate,
//接口设计好了,类就完成了一半。
#  if defined(__STL_NO_BAD_ALLOC) || !defined(__STL_USE_EXCEPTIONS)
#    include <stdio.h>
#    include <stdlib.h>
#    define __THROW_BAD_ALLOC fprintf(stderr, "out of memory\n"); exit(1)
#  else /* Standard conforming out-of-memory handling */
#    include <new>
#    define __THROW_BAD_ALLOC throw std::bad_alloc()
#endif
#include<cassert>
//第一级配置器:
/*
template<class _Tp>
class __malloc_alloc_template
{
public:
	static _Tp* allocate(size_t __n)
	{
		_Tp* __result=new _Tp[__n];
		return __result;
	}
	static void deallocate(_Tp* __p,size_t __n)
	{
		if(__n==1) delete __p;
		else if(__n>1) delete[] __p;
	}
};
*/
//上述设计是可以的,仅仅是包装了一下new/delete机制,仅仅换了一下他们的调用名称,但是:这个类是依赖于类型的。
//可以用,但是我们有更好的办法,可以设计出更好的类--它不依赖于具体的类型,仅仅分配字节,实现与new/delete一样的
//功能,注意这是一个静态类,因为我们不用产生不同的实体,我们仅仅是调用函数

template<int __inst>
class __malloc_alloc_template
{
	typedef void(* _Malloc_handler)();
private://首先模拟出new操作的错误处理机制--回调函数
	static void* _S_oom_malloc(size_t);
	static void* _S_oom_realloc(void*,size_t);
	static _Malloc_handler __malloc_alloc_oom_handler;
public:
	static void* allocate(size_t __n)
	{
		void* __result=malloc(__n);
		if(__result==0) _S_oom_malloc(__n);
		return __result;
	}
	//此处有点疑问
	static void deallocate(void* __p,size_t)
	{
		free(__p);
	}
	static void* reallocate(void* __p,size_t ,size_t __new_size)
	{
		void* __result=realloc(__p,__new_size);
		if(__result==0) _S_oom_realloc(__p,__new_size);
		return __result;
	}
	static void __set_malloc_handler(_Malloc_handler __f)
	{
		_Malloc_handler __old_handler=__malloc_alloc_oom_handler;
		__malloc_alloc_oom_handler=__f;
		return __old_handler;
	}
};
template<int __inst>
 __malloc_alloc_template<__inst>::_Malloc_handler 
	__malloc_alloc_template<__inst>::__malloc_alloc_oom_handler=0;

template<int __inst>
 void* __malloc_alloc_template<__inst>::_S_oom_malloc(size_t __n)
{
	_Malloc_handler  __my_oom_handler;
	void* __result;
	for(;;){
		__my_oom_handler=__malloc_alloc_oom_handler;
		if(__malloc_alloc_oom_handler==0) {__THROW_BAD_ALLOC;}
		__my_oom_handler();
		__result=malloc(__n);
		if(__result) return __result;
	}
 }
 template<int __inst>
 void* __malloc_alloc_template<__inst>::_S_oom_realloc(void* __p,size_t __n)
 {
	 _Malloc_handler __my_malloc_handler;
	 void* __result;
	 for(;;){
		 __my_malloc_handler=__malloc_alloc_oom_handler;
		 if(__malloc_alloc_oom_handler==0){__THROW_BAD_ALLOC;}
		 __my_oom_handler();
		 __result=realloc(__p,__n);
		 if(__result) return __result;
	 }
 }

 typedef __malloc_alloc_template<0>  malloc_alloc;
 //至此,第一级配置器完成,回顾一下设计目的:设计与其他配置器接口一样的配置器,功能与new./delete相似;不依赖于
 //具体类型;
 //额外的技术:回调函数机制--模拟new的异常处理



 //第二级配置器:与第一级配置器的接口相同,不过,内存碎片少,涉及了新的思想,
 //我们设计一个存储着内存的链表,程序使用的内存,我们直接从链表中提取,程序释放的内存存储为链表的一个节点,这样我们
 //就让链表扮演者“heap”的角色,但是还是那句话,构建依赖于类型的链表好构建,因为节点的大小已经确定,但是
 //我们的目的设设计通用的1,不依赖于类型的配置器,所以,链表不依赖与类型,而依赖于内存大小;若果不依赖于类型
 //我们怎么知道需要内存大小?
 //:这里的设计策略是,我们维护16个链表,每个链表存储着8*n byte大小的节点,最大的节点是128byte.这样,内存需要7byte
 //我们就分配给它8byte,因为小于128byte的内存都是从链表中得到的,所以我们回收的时候,如果回收对象7byte,那么就回收
 //8byte,注意,要实现这一功能,就得好好利用指针。
 //如果链表中的内存不够用了怎么办?
 //:我们从内存池里填充,这里的内存池是由两个指针标示的一段区域
 //如果内存池内存不够怎么办?
 //:从heap里分配
 //如果heap内存不够怎么办?抛出异常
 template<int __inst>
 class __default_alloc_template
 {
 private:
	 enum{__ALIGN=8};//链表的节点大小都是此值的倍数
	 enum{__MAX_BYTE=128};//链表中结点的最大大小
	 enum{__NFREELISTS=16};//维持的链表条数
	 //不知道为什么,作者这样实现这几个值,而且不是用一个enum;
	 static size_t _S_round_up(size_t __n)//将__n调整为大于它的8的倍数,即:可以在链表中找到相应大小的节点
	 {
		 return (__n+__ALIGN-1)&~(__ALIGN-1);
	 }
	 
	 union _Obj
	 {//链表中节点的结构
		 union _Obj* _M_free_list_link;
		 char data[1];
	 };
	 static _Obj* _S_free_list[_NFREELISTS];//维持着16条链表,每条链表中的节点内存都不一样,同一链表中结点内存一样

	 static size_t _S_free_index(size_t __n)//对于__n寻找合适的链表索引
	 {
		 return (((__n+__ALIGN)&~(__ALIGN-1))/__ALIGN)-1;
	 }
	 //下面两个函数的功能解决的问题:当节点大小为__n的链表为空时,我们需要填充链表。
	 //从内存池中分配内存,填充这条链表;如果内存池为空,则从heap中分配内存填充内存池
	 //我们很自然的分为两层,第一层:用内存池中的内存填充链表;第二层:用heap中的内存填充内存池
	 //可是,这样分层,却不是很好操作,因为第一层有两个动作:从内存池种分配内存;填充链表;两个动作都比较复杂
	 //第二层的两个动作都比较简单
	 //于是,函数操作分三层:从heap中的内存填充内存池;从内存池分配内存;填充链表
	 static void* _S_refill(size_t __n);
	 static void* _S_chunk_alloc(size_t __n,int& __nobjs);//引用传递,我们可以更改
	 static void* _S_malloc(size_t __n);
	 
	 //数据成员
	 static char* _S_start_free;//内存池的起始位置
	 static char* _S_end_free;//结束位置
	 static size_t _S_heap_size;//没弄明白什么作用


 public:
	 //配置器的统一接口
	 static void* allocate(size_t __n)
	 {
		 void* __result;
		 if(__n>__MAX_BYTE){
			__result= malloc_alloc::allocate(__n);
		 }else{
			 _Obj** __my_free_list=_S_free_list+_S_free_index[__n];
			 if(*__my_free_list==0)
				__result= _S_refill(_S_round_up(__n));
			 else{
				 __result=*__my_free_list;
				 (*__my_free_list)=(*__my_free_list)->_M_free_list_link;
			 }
		 }
		 return __result;
	 }

	 static void deallocate(void* __p,size_t __n)
	 {
		 if(__n>__MAX_BYTE){
			 malloc_alloc::deallocate(__p,__n);
		 }else{
			 _Obj** __my_free_list=_S_free_list+_S_free_index(__n);
			 ((_Obj*)__p)->_M_free_list_link=*__my_free_list;
			 *__my_free_list=(_Obj*)__p;
		 }
	 } 
	 static void* reallocate(void* __p,size_t __old_size,size_t __new_size);
 };
 /*我的实作版本,所用的是倒序添加,即每添加一个元素都是添加到链表的开头
 template<int __inst>
 void* __default_alloc_template<__inst>::_S_refill(size_t __n)//__n是8的倍数
 {
	 int __nobjs=20;
	 void* __chunk=_S_chunk_alloc(__n,__nobjs);
	 if(__nobjs==1) return __chunk;
	 _Obj** __my_free_list=_s_free_list+_S_free_index(__n);
	 _Obj* __next_obj=(_Obj*)((char*)__chunk+__n);
	 __next_obj->_M_free_list_link=0;
	 _Obj* __current_obj;
	 *__my_free_list=__next_obj;
	 for(int __i=2;__i<__nobjs;++__i){
		 __current_obj=__next_obj;
		 __next_obj=_Obj*((char*)__next_obj+__n);
		 __next_obj->_M_free_list_link=*__my_free_list;
		 *__my_free_list=__next_obj;
	 }
	 return __chunk;
 }
 */
 //stl的实作版本,正序添加即:添加的每个元素都添加到元素的结尾,这里依赖的事实是:当重新填充链表时,链表已经为空
 template<int __inst>
 void* __default_alloc_template<__inst>::_S_refill(size_t __n)//__n是8的倍数
 {
	 int __nobjs = 20;
    char* __chunk = _S_chunk_alloc(__n, __nobjs);
    _Obj* __STL_VOLATILE* __my_free_list;
    _Obj* __result;
    _Obj* __current_obj;
    _Obj* __next_obj;
    int __i;

    if (1 == __nobjs) return(__chunk);
    __my_free_list = _S_free_list + _S_freelist_index(__n);

    /* Build free list in chunk */
      __result = (_Obj*)__chunk;
      *__my_free_list = __next_obj = (_Obj*)(__chunk + __n);
      for (__i = 1; ; __i++) {//注意此处的条件判断的转移
        __current_obj = __next_obj;
        __next_obj = (_Obj*)((char*)__next_obj + __n);
        if (__nobjs - 1 == __i) {
            __current_obj -> _M_free_list_link = 0;
            break;
        } else {
            __current_obj -> _M_free_list_link = __next_obj;
        }
      }
	  
    return(__result);
	//我对上段程序不敢苟同,我没有看出任何的c++风格,并且我觉得它的效率很低
	 /* //我的实作版本
	 int __nobjs=20;
	 void* __chunk=_S_chunk_alloc(__n,__nobjs);
	 if(__nobjs==1) return __chunk;
	 _Obj** __my_free_list=_s_free_list+_S_free_index(__n);
	 _Obj* __next_obj=(_Obj*)((char*)__chunk+__n);
	 _Obj* __current_obj;
	 *__my_free_list=__next_obj;
	 for(int __i=2;__i<__nobjs;++__i){
		 __current_obj=__next_obj;
		 __next_obj=_Obj*((char*)__next_obj+__n);
		 __current_obj->_M_free_list_link=__next_obj;
	 }
	 __next_obj->_M_free_list_link=0;
	 return __chunk;
	 */
}

//----------------------------------------------------------------------
 //从内存池中分配大小为__size的__nobjs个对象
 template<int __inst>
 void* __default_alloc_template<__inst>::_S_chunk_alloc(size_t __size,int& __nobjs)
 {
	 void* __result;
	 size_t __byte_left=_S_end_free-_S_start_free;
	 size_t __total_byte=__size*__nobjs;
	 if(__byte_left>__total_byte){//内存池中的内存足够
		 __result=_S_start_free;
		 _S_start_free+=__total_byte;
		 return __result;
	 }else if(__byte_left>=__size){//内存池中内存不足,但是足够一个__size
		 __nobjs=__byte_left/__size;
		 __total_byte=__nobjs*__size;
		 __result=_S_start_free;
		 _S_start_free+=__total_byte;
		 return __result;
	 }else{//连一个__size都不够
		 size_t __byte_to_get=2*__total_byte+ _S_round_up(_S_heap_size >> 4);//不知道为什么
		 //先处理到内存池中剩余的byte
		 if(__byte_left>0){
			 //这里有疑问,如果__byte_left=14,那么_S_free_index(__byte_left)返回1,那么对应的节点大小为16byte,而
			 //剩余内存不足以支撑起来,所以我认为还得减一,除非我们分配的都是8的倍数,剩余的都是8的倍数
			 _Obj** __my_free_list=_S_free_list+_S_free_index(__byte_left);
			 ((_Obj*) _S_start_free)->_M_free_list_link=*__my_free_list;
			 *_my_free_list=_S_start_free;
		 }

		 _S_start_free=(char*)malloc(__byte_to_get);
		 if(_S_start_free==0){//内存分配失败
			 //这时候就是把链表中大于__size的节点分配给内存池
			 _Obj** __my_free_list;
			 for(size_t __i=__size;__i<__MAX_BYTE;__i+=__ALIGN){
				 __my_free_list=_S_free_list+_S_free_index(__size);
				 __p=*__my_free_list;
				 if(__p!=0){
					 *__my_free_list=__p->_M_free_list_link;
					 _S_start_free=(char*)__p;
					 _S_end_free=(char*)__p+__i;
					 return (_S_chunk_alloc(__size,__nobjs));
				 }
			 }
			 _S_end_free=0;
			 _S_start_free=(char*)malloc_alloc::allocate(__byte_to_get);//使用异常处理机制
		 }
		 _S_heap_size+=__byte_to_get;
		 _S_end_free=_S_start_free+_byte_to_get;
		 return _S_chunk_alloc(__size,__nobjs);
	 }
 }

 template<int __inst>
 void* __default_alloc_template<__inst>::reallocate(void* __p,size_t __old_size,size_t __new_size)
 {
	 if(__old_size>___MAX_BYTE && __new_size>___MAX_BYTE){
		 malloc_alloc::reallocate(__p,__old_size,__new_size);
	 }else if(_S_round_up(__old_size)==_S_round_up(__new_size)){
		 return __p;
	 }else{
		 void* __result=allocate(__new_size);
		 size_t __copy_sz=__new_size>__old_size?__old_size:__new_size;
		 memcpy(__result,__p,__copy_sz);
		 deallocate(__p,__old_size);
		 return __result;
	 }
 }

 template<int __inst> char* __default_alloc_template<__inst>::_S_start_free=0;
 template<int __inst> char* __default_alloc_template<__inst>::_S_end_free=0;
 template<int __inst> size_t __default_alloc_template<__inst>::_S_heap_size=0;
 template<int __inst> typename __default_alloc_template<__inst>::_Obj*
	 __default_alloc_template<__inst>::_S_free_list[
		  __default_alloc_template<__threads, __inst>::_NFREELISTS ]=
		  {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};

 typedef __default_alloc_template<0> alloc;
 //第二级配置器的主要是内存与指针的控制,内存池技术
 
 //下面的一个类的主要目的是介绍指针的技术:我们在内存的开始处,记录这块内存的大小
 template<class _Alloc>
 class debug_alloc
 {
 private:
	 enum {_S_extra=8};//8byte足够存储任意大的整数
 public:
	 static void* allocate(size_t __n)
	 {
		 char* __result= (char*) _Alloc::allocate(__n);
		 *(size_t*)__result=__n;
		 return __result+(int)_S_extra;
	 }
	 static void deallocate(void* __p,size_t __n)
	 {
		 char* __real_p=(char*)__p-_S_extra;
		 assert(*(size_t*)__real_p==__n);
		 _Alloc::deallocate(__real_p,__n+_S_extra);
	 }
	 static void* reallocate(void* __p,size_t __old_sz,size_t __new_sz)
	 {
		 char* __real_p=(char*)__p-_S_extra;
		 assert(*(size_t*)__real_p==__old_sz);
		 char* __result=(char*)_Alloc::reallocate(__p,__old_sz_+_S_extra,__new_sz+_S_extra);
		 *(size_t*)__result=__new_sz;
		 return __result+_S_extra;
	 }
 };

 //要知道,我们使用时分配内存是需要依赖于类型的,所以,我们需要一层封装,可以不用直接跟内存大小打交道,而是和
 //对象的个数打交道。
 template<class _Tp,class _Alloc>
 class simple_alloc
 {
 public:
	 static void* allocate(size_t __n){return _Alloc::allocate(__n*sizeof(_Tp));}
	 static void* allocate(void){return _Alloc::allocate(sizeof(_Tp));}
	 static void deallocate(void* __p,size_t __n){if(__n!=0) _Alloc::deallocate(__p,__n*sizeof(_Tp));}
	 static void deallocate(void* __p){ _Alloc::deallocate(__p,sizeof(_Tp));}
 };

 //我们的四个allocator
 typedef __default_alloc_template<0> alloc;
 typedef __default_alloc_template<0> single_client_alloc;

 //还有malloc_alloc,pthread_alloc

//c++ 标准allocator定义
 template<class _Tp>
 class allocator
 {
	 typedef alloc _Alloc;
 public:
  typedef size_t     size_type;
  typedef ptrdiff_t  difference_type;
  typedef _Tp*       pointer;
  typedef const _Tp* const_pointer;
  typedef _Tp&       reference;
  typedef const _Tp& const_reference;
  typedef _Tp        value_type;

  template<class _Tp1>
  struct rebind
  {
	  typedef allocator<_Tp1> other;
  };

  allocator() {}
  allocator(const allocator&)  {}
  template <class _Tp1> allocator(const allocator<_Tp1>&) __STL_NOTHROW {}
  ~allocator() {}

  pointer address(reference __x){return &__x;}
  const_pointer address(const_reference __x) const { return &__x; }
    // __n is permitted to be 0.  The C++ standard says nothing about what
  // the return value is when __n == 0.
  _Tp* allocate(size_type __n, const void* = 0) {
    return __n != 0 ? static_cast<_Tp*>(_Alloc::allocate(__n * sizeof(_Tp))) 
                    : 0;
  }

  // __p is not permitted to be a null pointer.
  void deallocate(pointer __p, size_type __n)
    { _Alloc::deallocate(__p, __n * sizeof(_Tp)); }

  size_type max_size() const  
    { return size_t(-1) / sizeof(_Tp); }//max:size_t(-1)

  void construct(pointer __p, const _Tp& __val) { new(__p) _Tp(__val); }
  void destroy(pointer __p) { __p->~_Tp(); }
};
//void 的特化版本
 template<>
class allocator<void> {
public:
  typedef size_t      size_type;
  typedef ptrdiff_t   difference_type;
  typedef void*       pointer;
  typedef const void* const_pointer;
  typedef void        value_type;

  template <class _Tp1> struct rebind {
    typedef allocator<_Tp1> other;
  };
};
//上面最不容易理解的可能就是rebind的作用了,其实他的作用也不是很大,
//根据msdn的例子http://msdn.microsoft.com/en-us/library/5fk3e8ek.aspx,我们可知道他的作用,主要是用于容器

//下面是alloc_traits,主要是两个成员,一是真正的allocator,二是是否需要allocator实例对象。一般来说,allocator是不需要实例的,
//因为allocator多事静态函数,但是,stl文档中是这样描述的:
/* This is occasionally a significant restriction. For example, it is not possible to arrange for different containers to 
   allocate memory mapped to different files by passing different allocator instances to the container constructors. 
   Instead one must use one of the following alternatives:
   1.The container classes must be instantiated with different allocators, one for each file. This results in different 
   container types. This forces containers that may be mapped to different files to have distinct type, which may be a
   troublesome restriction, though it also results in compile-time detection of errors that might otherwise be difficult 
   to diagnose.
   2.The containers can be instantiated with a single allocator, which can be redirected to different files by calling
   additional member functions. The allocator must be suitably redirected before container calls that may allocate. 
 */
//对于alloc_traits,没理解好暂时不写。


STL源码剖析 --- 空间配置器 std::alloc STL是建立在泛化之上的。数组泛化为容器,参数化了所包含的对象的类型。函数泛化为算法,参数化了所用的迭代器的类型。指针泛化为迭代器,参数化了所指向的对象的类型。STL中的六大组件:容器、算法、迭代器、配置器、适配器、仿函数。 这六大组件中在容器中分为序列式容器和关联容器两类,正好作为STL源码剖析这本书的内容。迭代器是容器和算法之间的胶合剂,从实现的角度来看,迭代器是一种将operator*、o 阅读详情

相关推荐

从零开始:用YOLOv8-Pose实现实时人体姿态检测(附完整代码)

本文提供了一份从零开始的完整实战指南,详细介绍了如何使用YOLOv8-Pose构建实时人体姿态检测系统。内容涵盖环境搭建、数据准备、模型训练与调优,以及高性能部署和进阶应用开发,并附有可直接运行的代码示例,帮助开发者快速掌握Pose Estimation技术并将其应用于实际项目。

h6i7j8的博客 621

【侯捷C++-----内存管理Chapter1(至G2.9std:alloc源码)】

malloc是memory allocation的意思~~

weixin_53459056的博客 1049

CPU系统级验证——测试激励——imperas公司riscvOVPsimPlus文件分析

本分析重点关注该repo向量扩展部分。 1. repo简介 该repo是指令集验证的仿真环境包括,大部分是指令集的测试用例,也包含了一些模拟器,如riscvOVPsimPlus。 主要介绍的是riscvOVPsimPlus指令集模拟器,riscvOVPsimPlus(下面统称ISS)是imperas公司在riscvOVPsim基础上扩充了向量扩展的指令集模拟器,该repo于今年9月份部分开源 什么叫部分开源呢? 首先该repo必须在imperas官网注册下载,而且必须是企业用户(免费邮箱人家瞧不上.

知识,既贵,又便宜。 4459

iOS内存管理——alloc/release/dealloc方法的GNUstep实现与Apple的实现

iOS内存管理——alloc/release/dealloc方法的GNUstep实现与Apple的实现接上篇关于iOS内存管理的规则考我们通过alloc/release/dealloc方法的具体实现来深入探讨内存管理。什么是GNUstep `GNUstep`是`Cocoa`框架的互换框架,从源代码的实现上来说,虽然和Apple不是完全一样,但是从开发者的角度来看,两者的行为和实现方式是一样,或

王学森的专栏 4078

海康工业相机SDK开发实战:从环境搭建到实时图像采集(附避坑指南)

本文详细介绍了海康工业相机SDK在Windows平台上的开发实战流程,涵盖从环境搭建、运行时库路径配置到实时图像采集的全过程。重点解析了MVS SDK部署、设备连接、参数设置及图像处理等核心环节,并提供了实用的避坑指南和错误排查方法,帮助开发者构建稳定的机器视觉系统。

weixin_29248611的博客 846

基于电子海图的水面无人艇全局路径规划

Research and Implementation of Global Path Planning for Unmanned Surface Vehicle Based on Electronic Chart (基于电子海图的水面无人艇全局路径规划)   该论文已经在ICMIR2017会议上发表,附上springer的文献地址 Research and Implementation of Gl...

weixin_30797199的博客 1590

泛读《STL源码剖析》第二章:空间配置器

目录目录目录目录 前言 SGI特殊空间配置器,std::alloc 构造和析构基本工具:construct()与destroy() std::alloc空间的配置与释放 一级配置器: 二级配置器: 空间配置函数allocate() 空间释放函数deallocate() 重新填充free lists:refill()函数 内存池 内存基本处理工具 ①uninitialized...

z-k的博客 590

优秀的 Verilog/FPGA开源项目介绍(二十六)- ISP (图像信号处理)

介绍查看《ISP算法及架构分析介绍》今天项目的顺序就是先介绍几个关于ISP算法架构的项目,包括python、matlab、c等高级语言实现的ISP算法架构,最后介绍一个FPGA实现ISP的项目。openISPhttps://github.com/cruxopen/openISP项目介绍用python实现的ISP架构,该架构涉及到的知识如下:下图是最新实现的模块:主要模块如...

OpenFPGA的博客 4948

STL源码剖析之stl_alloc(一)

STL主要研究的六大问题:空间配置器,迭代器,容器,仿函数,算法,容器适配器 一级空间配置器源码如下: #if 0 #include&lt;new&gt; #define __THROW_BAD_ALLOC throw bad_alloc #else #include&lt;iostream.h&gt; #include&lt;malloc.h&gt; #include&lt;stdlib....

zzb2019的博客 1225

破局KS滑块验证码:从参数加密到轨迹生成,Python逆向全流程避坑实录

快手滑块验证码破解实战:从逆向分析到自动化实现 摘要:本文详细记录了破解快手滑块验证码(KS滑块)的完整过程。通过48小时的逆向分析,揭示了KS滑块的双重校验机制:不仅需要精准定位滑块缺口位置,还需满足参数加密和轨迹特征校验。文章从反爬逻辑分析入手,介绍了工具选型与环境配置的避坑要点,重点讲解了滑块缺口距离计算方法和核心加密参数slide_sign的逆向过程。通过OpenCV边缘检测和Frida动态调试技术,成功实现了滑块验证的自动化,准确率提升至99%。文中附有Python实现代码和实际操作踩坑记录,为开

专注于Python爬虫开发,分享爬虫技巧、项目实战与反爬经验,使用Scrapy、BeautifulSoup等工具,解决数据抓取难题。 1662

5分钟快速上手:用AI生成3D虚拟场景的保姆级教程

你是否想过:不用学复杂的3D建模软件,不用懂“多边形”“UV贴图”这些专业术语,也能快速生成一个梦幻的森林、未来感的城市,甚至外太空基地?本文的目的就是教完全没接触过3D技术的新手,用AI工具5分钟生成3D虚拟场景。我们会覆盖主流AI工具的选择、提示词编写技巧、生成后的简单调整,以及常见问题解决。本文会像“游戏任务指南”一样,从“认识工具”→“写提示词”→“生成场景”→“调整优化”逐步讲解,最后还会教你把生成的3D场景用起来!提示词:你给AI的“订单备注”,越详细效果越好。扩散模型。

AI 原生应用开发的博客 1963

stl_alloc.h源码剖析

本文主要介绍std::alloc stl_alloc.h 内存配置操作由 alloc:allocate()负责 内存释放操作由alloc::deallocate()负责 stl_construct.h 对象构造操作由::construct()负责 对象析构操作由::destory()负责 空间的配置与释放 std::alloc SGI设计哲学: 向system heap要求空间 考虑多线...

asladfa的博客 497

【RKNN】RKNN-Toolkit2 Python API函数详解

RKNN-Toolkit2 的 API 设计以开发者效率为核心,覆盖模型转换、量化、部署全流程。通过灵活的参数配置(如多核调度、混合量化)和调试工具(性能分析、精度对比),可快速适配复杂边缘场景。

浩瀚之水的专栏 786

《STL 源码剖析》——空间配置器alloc

栈和队列是应用最多的数据结构之二,有数组实现和链表实现两种方式。当需要对容器做出限制,只允许一边插入和取出数据时,则需要用到栈。下面将总结数组实现的栈和阐述其原理。 一、线性表——栈Stack 1.1栈Stack定义 栈是一种特殊的线性表,其插入(也称为入栈或压栈)和删除(也称为弹出或出栈)操作都在表的同一端进行;该插入和删除的端口称为栈顶(top),另一端称为栈底(bottom)。 1.2栈的基本运算 1.2.1基本运算 (1) 初始化(构造一个空的栈) (2) 计算栈长度(栈中节点个数) (3) 插入节

净无邪博客 1449

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

温度PID控制PLC程序

温度PID稳定控制程序,适用于欧姆龙PLC,对其他PLC也具有很大参考价值

《STL源码剖析》-- stl_alloc.h

// Filename: stl_alloc.h // Comment By: 凝霜 // E-mail: mdl2009@vip.qq.com // Blog: http://blog.youkuaiyun.com/mdl13412 // 特别说明: S

一个人的战争 6670

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

C++ STL源码剖析——stl_alloc.h

stl_alloc.h # // Comment By: 凝霜 # // E-mail: mdl2009@vip.qq.com # // Blog: http://blog.youkuaiyun.com/mdl13412 # # // 特别说明: SGI STL的allocator在我的编译环境下不使用内存池 # // 而其内存池不进行内存释放

仰起脸笑得像满月 1305

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

《STL源码剖析》--stl_alloc.h

// Filename:    stl_alloc.h // Comment By:  凝霜 // E-mail: mdl2009@vip.qq.com // Blog: http://blog.youkuaiyun.com/mdl13412 // 特别说明: SGI STL的allocator在我的编译环境下不使用内存池 // 而其内存池不进行内存释放操作, 其

在路上 544

STL源码剖析——内存配置器alloc

虽然STL的内存配置器在我们的实际应用中几乎不用涉及,但它却在STL的各种容器背后默默做了大量的工作,STL内存配置器为容器分配并管理内存。统一 的内存管理使得STL库的可用性、可移植行、以及效率都有了很大的提升,因此STL内存配置器是STL库中最重要的组成部分之一。 1、Constructor和Destroy 我们所习惯的C++内存空间分配动作如下: class Foo

storm 574

STL源码解析之内存分配器alloc

前言 正文 一, C++中的对象new的流程 在C++中 new是调用::operator new (); //分配内存的 在调用赋值函数 construct(); 释放的流程 destroy() ::operator delete ; //释放内存 //初始化对象的值 template <class T1, class T2> inline void construct(T1*p, const T2& value) { new (p) T

永远积极向上、永远热泪盈眶、永远豪情满怀、永远坦坦荡荡 573

《STL源码剖析》学习笔记3——内存配置器alloc

标签:C,C++,STL,源码,学习,笔记,内存,配置器   虽然STL的内存配置器在我们的实际应用中几乎不用涉及,但它却在STL的各种容器背后默默做了大量的工作,STL内存配置器为容器分配并管理内存。统一的内存管理使得STL库的可用性、可移植行、以及效率都有了很大的提升,因此STL内存配置器是STL库中最重要的组成部分之一。 1、Constructor和Destroy 我

LonelyWinter的专栏 2233

C++之STL心法#3-空间配置器stl_alloc源码解读

STL空间配置器源码stl_alloc;SGI STL;STL内存分配

Allen Roson 604

STL源码剖析(二)__alloc_traits特性

__alloc_traits特性 类__allocator_traits_base,用于获取内存分配器Alloc的属性,内存分配器不一定是std::allocator,可以是自定义的。 namespace std _GLIBCXX_VISIBILITY(default) { struct __allocator_traits_base { //分配器_Tp没有rebind成员函数时,调用普通版本__rebind template<typename _Tp, typename _

mei_true的博客 1844

STL源码剖析 -- STL Alloc 的allocate和construct

STL 中的allocate调用了::operator new() -----此函数不会调用construct;同理deallocate。 而new 或者 delete则编译器会自动算出size_t 和 void *p并传给::operator new及::operator delete,然后调用construct及deconstruct 一句话::operator new/::o

daeees的专栏 987

STL源码:alloc分配器

STL源码

zp126789zp的博客 286

《STL源码剖析》---stl_alloc.h阅读笔记

侯捷翻译的《STL源码剖析》stl_alloc.h阅读笔记。讲解的内存的配置与释放。

KangRoger的专栏 5099
上一篇: C++的I/O(vc版)(七)
下一篇: STL源码--iterator
wangyanphp
博客等级 码龄14年 90粉丝 51原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值