怎么知道BYTE* 指针指向内存的大小?

shiter
人工智能领域优质创作者
博客专家认证
2015-03-27 10:10:31
我在某地new 了一块大小出来,现在不知道大学只有这样一个指针pi

知道内存是BYTE类型的,怎么知道大小?
...全文
971 48 打赏 收藏 转发到动态 举报
写回复
用AI写文章
48 条回复
切换为时间正序
请发表友善的回复…
发表回复
yangyunzhao 2015-04-20
  • 打赏
  • 举报
回复
为什么不自己记录呢?
shiter 2015-04-18
  • 打赏
  • 举报
回复
引用 46 楼 my_live_123 的回复:
顺便贴上malloc.c的源码地址 http://code.woboq.org/userspace/glibc/malloc/malloc.c.html
非常感谢您的指导,我再琢磨琢磨,我觉的这个帖子斑竹应该加精啊
shiter 2015-04-17
  • 打赏
  • 举报
回复
引用 37 楼 xmxqiyan 的回复:
上面说的8个字节可能还小了,我这里试了16个字节应该包含了申请的大小 平台不一样申请占用的大小不一样。

printf("输入数据大小:");
		scanf("%d", &size);
		ptr = new unsigned char[size];
		p = ptr;
		for(i = 0; i <= 16; i++)
		{
			printf("Address %p value:0x%X(%d)\r\n", p, *p, *p);
			p --;
		}
		delete(ptr);
要是前16个字节有后面申请空间信息的话,那指针是怎么判断真正数据从哪里开始的呢?》
shiter 2015-04-17
  • 打赏
  • 举报
回复
引用 38 楼 xmxqiyan 的回复:
自己可以写一个结构体来表示前面16字节的内容

typedef struct 
{
	unsigned int size;		// 申请到的内存大小
	unsigned int flag;		// 若为1表示申请状态
	unsigned int totoal;	// 当前申请的总数,不一定是用户申请的,可能还包含系统申请的部分
	unsigned int reserved;	// 未知
}_mem_control_block;
测试代码更新如下:

unsigned char *ptr;
	unsigned char *p;
	int size;
	int i;
	_mem_control_block  *memctrl;

	while(1)
	{
		printf("输入数据大小:");
		scanf("%d", &size);
		ptr = new unsigned char[size];
		p = ptr;

		/*for(i = 0; i <= 16; i++)
		{
			printf("Address %p value:0x%X(%d)\r\n", p, *p, *p);
			p --;
		}
		delete(ptr);
		*/

		//delete(ptr); 测试
		memctrl = (_mem_control_block *)(p - sizeof(_mem_control_block));
		printf("申请地址:%p\r\n", p);
		printf("申请大小:%d\r\n", memctrl->size);
		printf("申请状态:%s\r\n", memctrl->flag == 1? "有效":"无效");
		printf("当前总数量:%d\r\n",memctrl->totoal);
		printf("\r\n");
	}
非常感谢您的回复,不知道memctrl这个函数来自何处,上面直接用打印前几个字节的解析方法跟这个有什么不同?
一根烂笔头 2015-04-17
  • 打赏
  • 举报
回复
一根烂笔头 2015-04-17
  • 打赏
  • 举报
回复
alloc_perturb此函数就是初始分配的内存,即全部清零!

然后看逆过程free

void
2914__libc_free (void *mem)
2915{
2916 mstate ar_ptr;
2917 mchunkptr p; /* chunk corresponding to mem */
2918
2919 void (*hook) (void *, const void *)
2920 = atomic_forced_read (__free_hook);
2921 if (__builtin_expect (hook != NULL, 0))
2922 {
2923 (*hook)(mem, RETURN_ADDRESS (0));
2924 return;
2925 }
2926
2927 if (mem == 0) /* free(0) has no effect */
2928 return;
2929
2930 p = mem2chunk (mem);
2931
2932 if (chunk_is_mmapped (p)) /* release mmapped memory. */
2933 {
2934 /* see if the dynamic brk/mmap threshold needs adjusting */
2935 if (!mp_.no_dyn_threshold
2936 && p->size > mp_.mmap_threshold
2937 && p->size <= DEFAULT_MMAP_THRESHOLD_MAX)
2938 {
2939 mp_.mmap_threshold = chunksize (p);
2940 mp_.trim_threshold = 2 * mp_.mmap_threshold;
2941 LIBC_PROBE (memory_mallopt_free_dyn_thresholds, 2,
2942 mp_.mmap_threshold, mp_.trim_threshold);
2943 }
2944 munmap_chunk (p);
2945 return;
2946 }
2947
2948 ar_ptr = arena_for_chunk (p);
2949 _int_free (ar_ptr, p, 0);
2950}

重点:
0.分配的hook,参考gnu相关内容,不管它
1.传入空指针,直接返回,没啥作用
2.p = mem2chunk (mem);
这是个宏

#define mem2chunk(mem) ((mchunkptr)((char*)(mem) - 2*SIZE_SZ))

看看多熟悉,上面是+,这里是减
3.如果是映射方式分配的大内存,用解映射方式释放,不管它
4.最后两句
倒数第二句全是宏,展开如下

ar_ptr = (((p)-> size & 0x4) ?
((heap_info *) ((unsigned long) (p) & ~((10 * 10) - 1)))->ar_ptr : &main_arena);

具体没有深究,暂且不论了
最后一句,它要完成释放的工作
这也是一个很大的函数,看主要部分
进此函数有一句
size = chunksize (p);
这个是个下面这个宏

#define PREV_INUSE 0x1
#define IS_MMAPPED 0x2
#define NON_MAIN_ARENA 0x4
#define SIZE_BITS (PREV_INUSE | IS_MMAPPED | NON_MAIN_ARENA)
#define chunksize(p) ((p)->size & ~(SIZE_BITS))

意思就是屏蔽掉低3位,就得到chunk的大小了,
骚年,秒懂没?这就是你要的大小,至于windows下其怎么malloc和free的,自己研究吧

下面是测试程序

#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>

struct malloc_chunk {
size_t prev_size;
size_t size;
struct malloc_chunk *fd;
struct malloc_chunk *bk;
struct malloc_chunk *fd_nextsize;
struct malloc_chunk *bk_nextsize;
};

typedef struct malloc_chunk *mchunkptr;

int main(int argc, char *argv[])
{
void *mem;
mchunkptr p;
int ret;
int i;

for(i = 0; i < 10; ++i) {
mem = malloc(ret = rand() % 1024);

p = ((mchunkptr) ((char *) (mem) - 2 * (sizeof(size_t))));
printf("malloc size : %d; chunk size : %d\n", ret, p->size & ~0x7);

free(mem);
}
exit(0);

}

运行结果


一根烂笔头 2015-04-17
  • 打赏
  • 举报
回复
大家都只讨论在理论上,没有人深入实践中研究到底怎么回事 咱一起看看GNU的glib的malloc和free 开篇强调,此算法不一定是最好的,但是是普遍适用的

44* Why use this malloc?
45
46  This is not the fastest, most space-conserving, most portable, or
47  most tunable malloc ever written. However it is among the fastest
48  while also being among the most space-conserving, portable and tunable.
49  Consistent balance across these factors results in a good general-purpose
50  allocator for malloc-intensive programs.
51
52  The main properties of the algorithms are:
53  * For large (>= 512 bytes) requests, it is a pure best-fit allocator,
54    with ties normally decided via FIFO (i.e. least recently used).
55  * For small (<= 64 bytes by default) requests, it is a caching
56    allocator, that maintains pools of quickly recycled chunks.
57  * In between, and for combinations of large and small requests, it does
58    the best it can trying to meet both goals at once.
59  * For very large requests (>= 128KB by default), it relies on system
60    memory mapping facilities, if supported.
如果是你的性能瓶颈,可以自己实现malloc和free,据说有公司这样做 malloc函数实现

2878void *
2879__libc_malloc (size_t bytes)
2880{
2881  mstate ar_ptr;
2882  void *victim;
2883
2884  void *(*hook) (size_t, const void *)
2885    = atomic_forced_read (__malloc_hook);
2886  if (__builtin_expect (hook != NULL, 0))
2887    return (*hook)(bytes, RETURN_ADDRESS (0));
2888
2889  arena_get (ar_ptr, bytes);
2890
2891  if (!ar_ptr)
2892    return 0;
2893
2894  victim = _int_malloc (ar_ptr, bytes);
2895  if (!victim)
2896    {
2897      LIBC_PROBE (memory_malloc_retry, 1, bytes);
2898      ar_ptr = arena_get_retry (ar_ptr, bytes);
2899      if (__builtin_expect (ar_ptr != NULL, 1))
2900        {
2901          victim = _int_malloc (ar_ptr, bytes);
2902          (void) mutex_unlock (&ar_ptr->mutex);
2903        }
2904    }
2905  else
2906    (void) mutex_unlock (&ar_ptr->mutex);
2907  assert (!victim || chunk_is_mmapped (mem2chunk (victim)) ||
2908          ar_ptr == arena_for_chunk (mem2chunk (victim)));
2909  return victim;
2910}
2911libc_hidden_def (__libc_malloc)
重点是这句 victim = _int_malloc (ar_ptr, bytes); 这函数非常大,过百行,有兴趣的骚年,自己读去哈 主题思想就是根据用户申请的大小,做出不同的分配方案 怎么分配先不管喽,主要解决楼主的问题 其中有三句共有的重要的代码

  void *p = chunk2mem (victim); 
 alloc_perturb (p, bytes);
return p;
victim是分配算法分配的内存地址,chunk2mem是个宏

#define chunk2mem(p)   ((void*)((char*)(p) + 2*SIZE_SZ))
其中SIZE_SZ也是个宏,展开就是sizeof(size_t), 为什么加两个无符号整型大小呢? 看这里

struct malloc_chunk {
1112
1113  INTERNAL_SIZE_T      prev_size;  /* Size of previous chunk (if free).  */
1114  INTERNAL_SIZE_T      size;       /* Size in bytes, including overhead. */
1115
1116  struct malloc_chunk* fd;         /* double links -- used only if free. */
1117  struct malloc_chunk* bk;
1118
1119  /* Only used for large blocks: pointer to next larger size.  */
1120  struct malloc_chunk* fd_nextsize; /* double links -- used only if free. */
1121  struct malloc_chunk* bk_nextsize;
1122};
这个数据结构就malloc块信息结点,其中 INTERNAL_SIZE_T就是size_t,上文加上那个两个size_t就是跳过前两个成员 int_malloc返回偏移后的p,回到_lib_malloc中,return victim;即就是偏移后的p,即用户malloc得到的地址 布局的介绍:

/*
1126   malloc_chunk details:
1127
1128    (The following includes lightly edited explanations by Colin Plumb.)
1129
1130    Chunks of memory are maintained using a `boundary tag' method as
1131    described in e.g., Knuth or Standish.  (See the paper by Paul
1132    Wilson ftp://ftp.cs.utexas.edu/pub/garbage/allocsrv.ps for a
1133    survey of such techniques.)  Sizes of free chunks are stored both
1134    in the front of each chunk and at the end.  This makes
1135    consolidating fragmented chunks into bigger chunks very fast.  The
1136    size fields also hold bits representing whether chunks are free or
1137    in use.
1138
1139    An allocated chunk looks like this:
1140
1141
1142    chunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1143	    |             Size of previous chunk, if allocated            | |
1144	    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1145	    |             Size of chunk, in bytes                       |M|P|
1146      mem-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1147	    |             User data starts here...                          .
1148	    .                                                               .
1149	    .             (malloc_usable_size() bytes)                      .
1150	    .                                                               |
1151nextchunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1152	    |             Size of chunk                                     |
1153	    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1154
1155
1156    Where "chunk" is the front of the chunk for the purpose of most of
1157    the malloc code, but "mem" is the pointer that is returned to the
1158    user.  "Nextchunk" is the beginning of the next contiguous chunk.
1159
1160    Chunks always begin on even word boundaries, so the mem portion
1161    (which is returned to the user) is also on an even word boundary, and
1162    thus at least double-word aligned.
1163
1164    Free chunks are stored in circular doubly-linked lists, and look like this:
1165
1166    chunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1167	    |             Size of previous chunk                            |
1168	    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1169    `head:' |             Size of chunk, in bytes                         |P|
1170      mem-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1171	    |             Forward pointer to next chunk in list             |
1172	    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1173	    |             Back pointer to previous chunk in list            |
1174	    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1175	    |             Unused space (may be 0 bytes long)                .
1176	    .                                                               .
1177	    .                                                               |
1178nextchunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1179    `foot:' |             Size of chunk, in bytes                           |
1180	    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1181
1182    The P (PREV_INUSE) bit, stored in the unused low-order bit of the
1183    chunk size (which is always a multiple of two words), is an in-use
1184    bit for the *previous* chunk.  If that bit is *clear*, then the
1185    word before the current chunk size contains the previous chunk
1186    size, and can be used to find the front of the previous chunk.
1187    The very first chunk allocated always has this bit set,
1188    preventing access to non-existent (or non-owned) memory. If
1189    prev_inuse is set for any given chunk, then you CANNOT determine
1190    the size of the previous chunk, and might even get a memory
1191    addressing fault when trying to do so.
1192
1193    Note that the `foot' of the current chunk is actually represented
1194    as the prev_size of the NEXT chunk. This makes it easier to
1195    deal with alignments etc but can be very confusing when trying
1196    to extend or adapt this code.
1197
1198    The two exceptions to all this are
1199
1200     1. The special chunk `top' doesn't bother using the
1201	trailing size field since there is no next contiguous chunk
1202	that would have to index off it. After initialization, `top'
1203	is forced to always exist.  If it would become less than
1204	MINSIZE bytes long, it is replenished.
1205
1206     2. Chunks allocated via mmap, which have the second-lowest-order
1207	bit M (IS_MMAPPED) set in their size fields.  Because they are
1208	allocated one-by-one, each must contain its own trailing size field.
1209
1210*/
1211
bear234 2015-04-17
  • 打赏
  • 举报
回复
老老实实记录下大小不就行了?如果能通过指针直接获取指向空间的大小,那还是c++么,成java了
  • 打赏
  • 举报
回复
xmxqiyan 2015-04-17
  • 打赏
  • 举报
回复
_mem_control_block是自己定义的一个结构体,用来管理申请内存前面的那16个字节 当你申请一段10字节空间的时候,编译器实际会占用的字节为 【申请空间的头信息】【实际申请到的空间】 【申请空间的头信息】其实就是上面说到的那16个字节,我只是用_mem_control_block这个结构体来表示这16个字节而已。 【实际申请到的空间】某些平台这个区域长度与实际长度可能不一致辞,如你申请10个字节,在某些编译器为了字节对齐下会分配12(4字节对齐)个或16(8字节对齐)个字节。函数返回的指针是该区域的首地址。
xmxqiyan 2015-04-02
  • 打赏
  • 举报
回复
自己可以写一个结构体来表示前面16字节的内容


typedef struct
{
unsigned int size; // 申请到的内存大小
unsigned int flag; // 若为1表示申请状态
unsigned int totoal; // 当前申请的总数,不一定是用户申请的,可能还包含系统申请的部分
unsigned int reserved; // 未知
}_mem_control_block;


测试代码更新如下:

unsigned char *ptr;
unsigned char *p;
int size;
int i;
_mem_control_block *memctrl;

while(1)
{
printf("输入数据大小:");
scanf("%d", &size);
ptr = new unsigned char[size];
p = ptr;

/*for(i = 0; i <= 16; i++)
{
printf("Address %p value:0x%X(%d)\r\n", p, *p, *p);
p --;
}
delete(ptr);
*/

//delete(ptr); 测试
memctrl = (_mem_control_block *)(p - sizeof(_mem_control_block));
printf("申请地址:%p\r\n", p);
printf("申请大小:%d\r\n", memctrl->size);
printf("申请状态:%s\r\n", memctrl->flag == 1? "有效":"无效");
printf("当前总数量:%d\r\n",memctrl->totoal);
printf("\r\n");
}


xmxqiyan 2015-04-02
  • 打赏
  • 举报
回复
上面说的8个字节可能还小了,我这里试了16个字节应该包含了申请的大小
平台不一样申请占用的大小不一样。

printf("输入数据大小:");
scanf("%d", &size);
ptr = new unsigned char[size];
p = ptr;
for(i = 0; i <= 16; i++)
{
printf("Address %p value:0x%X(%d)\r\n", p, *p, *p);
p --;
}
delete(ptr);


xmxqiyan 2015-04-02
  • 打赏
  • 举报
回复
把new到的指针地址前面8个地址的值都打印出来,数据长度应该在那里面 多测试几组找一下规律,不同编译器不一样
赵4老师 2015-03-30
  • 打赏
  • 举报
回复
VMMap 是进程虚拟和物理内存分析实用工具。http://technet.microsoft.com/zh-cn/sysinternals/dd535533
d741963250 2015-03-30
  • 打赏
  • 举报
回复
就从语言特性上面来说,是不支持的,换句话说,编译器也做不到,比如什么sizeof(*p)之类的。 从code角度或者从操作系统角度来说,是可以的。比如说在用户申请的内存,加上内存头,内存尾等。中间可以加一堆调试信息。 而这些都是代码层面的。
lin5161678 2015-03-30
  • 打赏
  • 举报
回复
引用 10 楼 xiaohuh421 的回复:
new出来的内存是可以得到分配大小的. 实际就是在数据区的前面. A *pA = new A[11]; A *pCopyA = pA; int nCount = *((int *)pCopyA-1); //这里就可以取得分配的元素个数. (注意, 是元素个数, 不是字节数) delete [] pA;
这做法是错的 别误人子弟啊
xiaohuh421 2015-03-30
  • 打赏
  • 举报
回复
引用 11 楼 wangyaninglm 的回复:
[quote=引用 10 楼 xiaohuh421 的回复:] new出来的内存是可以得到分配大小的. 实际就是在数据区的前面. A *pA = new A[11]; A *pCopyA = pA; int nCount = *((int *)pCopyA-1); //这里就可以取得分配的元素个数. (注意, 是元素个数, 不是字节数) delete [] pA;
请问这么写的原理是啥,没看懂[/quote]
引用 15 楼 zhangxiangDavaid 的回复:
经验证,10楼的不对
怪我没有说明使用此方法的条件. 使用这种方法计算大小, 需要满足以下条件. 1. 必需是以new[] 来分配的内存. 2. 必需是自定义类型, 不能是基本数据类型. 如果要计算基本数据类型的大小. 需要使用这里说的.方法http://blog.csdn.net/will_hsbsch/article/details/21124055 下面这个也可以参考: http://blog.sina.com.cn/s/blog_6a820b3c0100lbyl.html 其原理都是一样. 利用内存管理结构的特殊性. 特别注意: 可能不同的IDE或者不同的操作系统可能导致不同, 因为内存管理机制可能不同. size_t _msize( void *memblock ); 对于malloc系列的函数是可用的. 但对于new[]出的, 在VS2008中是崩溃. 不能得出大小. 它的原理是:http://blog.sina.com.cn/s/blog_6a820b3c0100lbyl.html debug环境下代码如下:
extern "C" _CRTIMP size_t __cdecl _msize_dbg (
        void * pUserData,
        int nBlockUse
        )
{
        size_t nSize;
        _CrtMemBlockHeader * pHead;

        /* validation section */
        _VALIDATE_RETURN(pUserData != NULL, EINVAL, -1);

        /* verify heap before getting size */
        if (check_frequency > 0)
            if (check_counter == (check_frequency - 1))
            {
                _ASSERTE(_CrtCheckMemory());
                check_counter = 0;
            }
            else
                check_counter++;

        _mlock(_HEAP_LOCK);         /* block other threads */
        __try {

        /*
         * If this ASSERT fails, a bad pointer has been passed in. It may be
         * totally bogus, or it may have been allocated from another heap.
         * The pointer MUST come from the 'local' heap.
         */
        _ASSERTE(_CrtIsValidHeapPointer(pUserData));

        /* get a pointer to memory block header */
        pHead = pHdr(pUserData);

         /* verify block type */
        _ASSERTE(_BLOCK_TYPE_IS_VALID(pHead->nBlockUse));

        /* CRT blocks can be treated as NORMAL blocks */
        if (pHead->nBlockUse == _CRT_BLOCK && nBlockUse == _NORMAL_BLOCK)
            nBlockUse = _CRT_BLOCK;

/* The following assertion was prone to false positives - JWM */
/*        if (pHead->nBlockUse != _IGNORE_BLOCK)              */
/*            _ASSERTE(pHead->nBlockUse == nBlockUse);        */

        nSize = pHead->nDataSize;

        }
        __finally {
            _munlock(_HEAP_LOCK);   /* release other threads */
        }

        return nSize;
}
lin5161678 2015-03-30
  • 打赏
  • 举报
回复
引用 28 楼 xihu1364 的回复:
[quote=引用 25 楼 lin5161678 的回复:] [quote=引用 24 楼 xiaohuh421 的回复:] [quote=引用 22 楼 lin5161678 的回复:] 这做法是错的 别误人子弟啊
请看21楼 [/quote]21楼依然没说对 使用这种方法计算大小, 需要满足以下条件. 1. 必需是以new[] 来分配的内存. 2. 必需是自定义类型, 不能是基本数据类型. 还有一个条件3 分配策略 会在分配的内存前面记录分配数量 这个条件3至关重要[/quote] 这只是分配策略的问题,但是21楼说的这个思路是一种内存的分配策略 但是你自己去分配的大小都不记,那你搞毛啊!系统已经帮你在delete的时候 delete[] 省去了传入大小[/quote] 不知道你在说些什么 21楼说了一个分配策略 但是 实际的分配策略未必如21楼所说 所以 21楼所说的内容要成立 必须要有一个重要前提 必须假定 分配策略一定是这样 后面的说法才有意义 然后 自己分配的大小记不记 是楼主的事 和我没关系 和分配策略也没关系 你在喷啥? 先把靶子摆好吧
版主大哥 2015-03-30
  • 打赏
  • 举报
回复
引用 31 楼 wangyaninglm 的回复:
[quote=引用 28 楼 xihu1364 的回复:] [quote=引用 25 楼 lin5161678 的回复:] [quote=引用 24 楼 xiaohuh421 的回复:] [quote=引用 22 楼 lin5161678 的回复:] 这做法是错的 别误人子弟啊
请看21楼 [/quote]21楼依然没说对 使用这种方法计算大小, 需要满足以下条件. 1. 必需是以new[] 来分配的内存. 2. 必需是自定义类型, 不能是基本数据类型. 还有一个条件3 分配策略 会在分配的内存前面记录分配数量 这个条件3至关重要[/quote] 这只是分配策略的问题,但是21楼说的这个思路是一种内存的分配策略 但是你自己去分配的大小都不记,那你搞毛啊!系统已经帮你在delete的时候 delete[] 省去了传入大小[/quote] 那为啥delete可以不用指定大小?[/quote] 如有的分配策略是 malloc 传入大小 返回 指针 如:大小为12 真实分配内存是大于12,因为需要保存大小等信息,有可能是2个字节,有可能是4个字节等等.... 所以free的时候就可以得到大小 而我们是不确定分配策略的
赵4老师 2015-03-30
  • 打赏
  • 举报
回复
new里面自动调用各层继承类的构造函数 delete里面自动调用各层继承类的析构函数 类的实例是对象,不是一段内存,求其BYTE*指针指向内存的大小本身就是一个伪命题。 我觉得。 《深度探索C++对象模型》 《C++反汇编与逆向分析技术揭秘》
加载更多回复(27)
 OpenGL-自主高性能三维GIS平台架构与实现/第二季:实现三维GIS球体+ 高程数据章节名称DEM基础1DEM基础知识1.介绍基本的DEM知识2.什么是DEM,作用是什么2DEM数据1.如何获取/ 传统测量/激光扫描/无人机测量/ 点云数据/ 倾斜摄影2.如何使用/局部小规模(栅格数据,图片/tif),3. 组织方式4. 根据使用目的不同,介绍多种优化方法3DEM图层的实现原理14DEM数据结构定义struct  V3U3N4顶点数据的生成和计算WGS84投影计算5wgs84 投影球体被切成一个个小圆弧,一共60个投影带,分别为01,02.........60WGS的最新版本为WGS 84(也称作WGS 1984、EPSG:4326),1984年定义、最后修订于2004年。接口定义坐标转换Wgs84 数据加载6瓦片编号计算生成算法1. 经纬度到大地坐标的转换2.大地坐标到经纬度坐标转换3. 根据经纬度获取瓦片编号框架重构7智能指针重构框架1. 基类定义(所有的类继承自基类),基类派生自 std::enbale_shared_from_this2. 实现智能指针的动态转换接口3. 实现向下转换4. 已有的类实现全部使用智能指针重构5. 任务系统(多线程加载任务)8引入图层(Layer)1. 介绍图层的概念以及重要性2. 图层类实现3. 修改框架(使用图层的方式重构框架)9Layer-bug排查(绘制过程中出现错位,偶发)1. 框架重构后遇到问题(绘制结果错误)2. 瓦片索引方式发生变化,多线程中引起内存问题3. 修改索引方式,解决绘制偶发错误问题10引入数据源(TileSource)1. 数据源的作用与设计目的2. 当前存在的问题,数据调度中存在问题3. 数据源(TileSource)类实现11数据格式管理(FormatMgr)1. 数据格式管理(FormatMgr) 提出的目的,需要解决的问题2. CELLFormat基类接口抽象3. 实现几个标准格式类4. 修改框架流程,使用FormatMgr重构流程5. 扩展支持,后续支持任务格式数据加入系统12Task(任务)优化1. 任务中低耦合数据结构,目的是让Task更加的通用2. 修改任务读取代码与任务处理代码,完善处理流程DEM高程13DEM-数字高程定义1. 什么是数字化高程数据2. 当下GIS系统中有哪些常见的高程格式3. 课程体体系中使用的哪种格式4. 高程类定义以及实现,并加入到FormatMgr 管理系统中14高程瓦片数据读取1. 介绍GIS系统相关的工具(在数据转换)数据生成方面可以解决大量时间2. 自定义高程瓦片格式说明3. 自定义高程格式文件解析,并以智能对象的方式引入到系统中4. 完善框架代码,适配高程数据15高程瓦片文件的读取1. 实现基本的读取算法2. 增加格式化组件,并加入到系统中3. 配置高程图层以及高程数据源,并加载数据,验证数据正确性16瓦片数据结构重构1.顶点生成2.UV坐标计算3.面数据生成17DEM重构绘制流程1. 修改绘制数据结构,去除无用字段2. 增加Mesh类,实现光栅数据转换成三角面数据,计算UV数据,提炼接口3. 修改系统调度,实现顶点数据,UV数据,以及面数据的生成与更新4. 按需更新数据,而不是每一帧更新18DEM-数据精度问题(CPU)1. 因为瓦片数据使用大地坐标作为系统输入,造成瓦片坐标很大,单浮点数据精度不够2. 使用局部坐标的方式解决单浮点精度问题3. 调整相机参数,解决投影矩阵数据计算深度精度问题4. 修改绘制shader 实现对瓦片数据的绘制19DEM-数据精度问题(LogDepth)1. 使用对数深度(log depth )算法在GPU中 计算解决单浮点经纬计算问题2. 修改shader ,增加对(logDepth)算法支持3. 修改C++端代码,实现对shader数据的输入20DEM-数据结构优化1.当下使用CPU端数据通过接口的方式传递给GPU,速度慢2. 使用Instance 方式降低Vertex Buffer 的大小,优化渲染系统21DEM-GPU缓冲区优化1. 使用Vertex Buffer Object / Index Buffer Object  / Instance  方式优化渲染系统2. 修改绘制接口,使用DrawElementsInstanceBaseInstance方式提升系统性能内存池与对象池22瓦片生成优化/对象池1. 相机移动过程中会频繁的建立与释放瓦片,对CPU有较大的消耗2. 引入内存池,避免频繁的内存申请与释放,降低CPU时间3. 改造智能指针对象,对象释放通知到内存管理,回收对象内存23改造任务系统支持对象池1. 任务系统是一个公用模块,被多个模块使用,避免频繁的内存操作,引起的内存碎片2. 实现对象池,并应用到任务模块法线计算24法线计算1. 修改现有顶点结构,增加法线支持2. 修改shader,增加法线顶点输入,使用平行光光照模型3. 修改绘制流程,支持光照计算,使用探照灯作为光源输入25顶点法线计算/共享法线计算1. 增加数据结构保存顶点数据被多个面共享的次数2. 计算面法线,并累加到顶点法线中3. 根据顶点被面共享的次数做平均法线计算4. 修改流程,按需更新法线数据26法线数据压缩1. 法线数据使用3 * float 数据存储,大大的增加了系统的数据2. 实现算法,将3 * float 数据压缩成4字节数据3. 改造绘制代码,支持压缩数据输入27GPU中计算产生法线数据(去掉CPU中计算)1. 引擎支持 Geometry Shader 阶段2. 编写 Geometry Shader,实现法线计算系统功能优化28重构CPU拾取流程1. 当下的拾取流程,只支撑二维数据拾取,无法准群的拾取三维数据2. Terrain中增加拾取接口,输入射线,输出拾取到顶点数据29绘制拾取结果1. 增加一个绘制点的方法,实现绘制代码2. 修改shader,增加logdepth3. 调试代码,花费了很多时间排查错误,最总排查到是因为uniform参数笔误写错造成。30任务系统完善,避免任务队列无线膨胀1. 任务系统中,没有限制队列的大小,生产者的能力远大于消费者的能力,造成任务队列膨胀2. 处理办法,限制生产者的生产能力,而不是限制任务队列大小(这种方式会造成业务逻辑异常复杂)3. 使用sleep休眠方式(这种方式是严重错误的)31如何避免瓦片数据抖动1. 产生瓦片抖动的原因 ? 分裂算法与回退算法中间没有过度2. 引入过度流程,避免内存抖动,参数因子是一个重要的数据,需要谨慎使用3. 有必要结合瓦片自身数据动态计算参数因子32瓦片数据管理-fepk文件格式支持-全球数据加载1. 支持fepk文件格式,增加fepk读取组件,适配fepk文件2. fepk管理数据方式:一般情况选择全球前10级别作为基础级别,因数据量不大(1G)左右,后续以8级作为基础级别,全球19级别数据被划分为 2^8 * 2^7(512 * 256)个块。每个块中包含了256 * 256 张小瓦片33fepk高程数据读取 34高程分裂处理当瓦片没有高程数据,那么子节点以及其他后代节点该如何共享父节点的数据35lesson-734-高程瓦片分裂处理(2)-算法实现高程数据分裂算法实现实现对高程数据的切分,并对特殊数据进行处理36高程瓦片分裂处理(3)-问题排查 37高程瓦片分裂处理(4)-(后代节点更新问题)当一个瓦片高程数据更新后,他的儿子节点,孙子节点...该如何处理?38瓦片视锥裁剪错误高程数据更新后,没有技术计算瓦片包围盒信息,造成包围盒错误,进而引视锥计算错误39http支持1.引入三方库 Libcurl2.http类封装,支持http读取数据40fepk.server使用 生成三维地球41改造四叉树-统一使用经纬度输入42地形网络生成算法重构 43引入球体坐标系 44使用球体坐标改造瓦片 45多图层(加载标签数据) 课时截图:镜头拉近后,显示细节数据加载矢量SHP国界线数据:加载矢量三维白膜数据截图高程数据加载点云数据 加载倾斜摄影数据 

69,371

社区成员

发帖
与我相关
我的任务
社区描述
C语言相关问题讨论
社区管理员
  • C语言
  • 花神庙码农
  • 架构师李肯
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧