??xml version="1.0" encoding="utf-8" standalone="yes"?>久久A级毛片免费观看,国产成人精品久久一区二区三区,99久久国产热无码精品免费http://www.shnenglu.com/HUUYUU/zh-cnThu, 08 May 2025 23:26:52 GMTThu, 08 May 2025 23:26:52 GMT60Freetype学习W记http://www.shnenglu.com/HUUYUU/archive/2008/07/10/55839.htmlHUYUHUYUThu, 10 Jul 2008 14:22:00 GMThttp://www.shnenglu.com/HUUYUU/archive/2008/07/10/55839.htmlhttp://www.shnenglu.com/HUUYUU/comments/55839.htmlhttp://www.shnenglu.com/HUUYUU/archive/2008/07/10/55839.html#Feedback1http://www.shnenglu.com/HUUYUU/comments/commentRss/55839.htmlhttp://www.shnenglu.com/HUUYUU/services/trackbacks/55839.html阅读全文

HUYU 2008-07-10 22:22 发表评论
]]>
写operator new和operator delete时要遵@常规http://www.shnenglu.com/HUUYUU/archive/2008/01/22/41608.htmlHUYUHUYUTue, 22 Jan 2008 01:42:00 GMThttp://www.shnenglu.com/HUUYUU/archive/2008/01/22/41608.htmlhttp://www.shnenglu.com/HUUYUU/comments/41608.htmlhttp://www.shnenglu.com/HUUYUU/archive/2008/01/22/41608.html#Feedback0http://www.shnenglu.com/HUUYUU/comments/commentRss/41608.htmlhttp://www.shnenglu.com/HUUYUU/services/trackbacks/41608.html自己重写operator newӞ很重要的一Ҏ函数提供的行和系l缺省的operator new一致。实际做h也就是:要有正确的返回|可用内存不够时要调用出错处理函数Q处理好0字节内存h的情c此外,q要避免不小心隐藏了标准形式的new?

非类成员形式的operator new的伪代码Q?

void * operator new(size_t size)        // operator newq可能有其它参数
{                                      

  if (size == 0)                      // 处理0字节hӞ
  {

        size = 1;                            // 把它当作1个字节请求来处理

  }                                    
  while (1)

{
    分配size字节内存;

      if (分配成功)
           return (指向内存的指?;

    // 分配不成功,扑և当前出错处理函数
      new_handler globalhandler = set_new_handler(0);
     set_new_handler(globalhandler);

      if (globalhandler) (*globalhandler)();
      else throw std::bad_alloc();
  }
}

 

为特定类写的new往往没有考虑该类被承的情况Q用sizeof(父类)获得大小Q但是如果发生子c调用父cȝnewӞ往往

会出错,子类的size往往大于父类的size。最好父cȝnew应该q么写:

void * base::operator new(size_t size)
{
  if (size != sizeof(base))                  // 如果数量“错误”Q让标准operator newQ精华部分?/font>
    return ::operator new(size);        // d理这个请?br>                                                         //

  ...                                                    // 否则处理q个h
}

 

对于operator delete(以及它的伙伴operator delete[])Q情冉|单。所要记住的只是Qc++保证删除I指针永q是安全的,所以你要充分地应用q一保证?/p>

下面是非cL员Ş式的operator delete的伪代码Q?br>void operator delete(void *rawmemory)
{
  if (rawmemory == 0) return;   //如果指针为空Q返?br>                                 //

  释放rawmemory指向的内?

  return;
}

 

q个函数的类成员版本也简单,只是q必L查被删除的对象的大小。假讄的operator new?#8220;错误”大小的分配请求{l?:operator newQ那么也必须?#8220;错误”大小的删除请求{l?:operator deleteQ?

void base::operator delete(void *rawmemory, size_t size)
{
  if (rawmemory == 0) return;          // 查空指针

  if (size != sizeof(base))                 // 如果size"错误"Q?/p>

{    
    ::operator delete(rawmemory);  // 让标准operator来处理请?br>    return;                       
  }

  释放指向rawmemory的内?

  return;
}

有关operator new和operator delete(以及他们的数lŞ?的规定不是那么麻烦,重要的是必须遵守它。只要内存分配程序支持new-handler函数q正地处理了零内存hQ就差不多了Q如果内存释攄序又处理了空指针Q那没其他什么要做的了。至于在cL员版本的函数里增加承支持,那将很快可以完成?/p>

HUYU 2008-01-22 09:42 发表评论
]]>
堆和栈的区别http://www.shnenglu.com/HUUYUU/archive/2008/01/10/38435.htmlHUYUHUYUThu, 10 Jan 2008 05:22:00 GMThttp://www.shnenglu.com/HUUYUU/archive/2008/01/10/38435.htmlhttp://www.shnenglu.com/HUUYUU/comments/38435.htmlhttp://www.shnenglu.com/HUUYUU/archive/2008/01/10/38435.html#Feedback0http://www.shnenglu.com/HUUYUU/comments/commentRss/38435.htmlhttp://www.shnenglu.com/HUUYUU/services/trackbacks/38435.html一、预备知识—程序的内存分配
    一个由c/C++~译的程序占用的内存分ؓ以下几个部分
    1、栈区(stackQ?q译器自动分配释放 Q存攑և数的参数|局部变量的值等。其操作方式cM于数据结构中的栈?br>    2、堆区(heapQ??一般由E序员分配释放, 若程序员不释放,E序l束时可能由OS回收 。注意它与数据结构中的堆是两回事Q分配方式倒是cM于链表,呵呵?br>    3、全局区(静态区Q(staticQ—,全局变量和静态变量的存储是放在一块的Q初始化的全局变量和静态变量在一块区域, 未初始化的全局变量和未初始化的静态变量在盔R的另一块区域?- E序l束后有pȝ释放
    4、文字常量区—常量字W串是攑֜q里的?E序l束后由pȝ释放
    5、程序代码区—存攑ևC的二q制代码?/font>


例子E序
q是一个前辈写的,非常详细
//main.cpp
int a = 0; 全局初始化区
char *p1; 全局未初始化?br>main()
{
int b; ?br>char s[] = "abc"; ?br>char *p2; ?br>char *p3 = "123456"; 123456\0在常量区Qp3在栈上?br>static int c =0Q?全局Q静态)初始化区
p1 = (char *)malloc(10);
p2 = (char *)malloc(20);
分配得来?0?0字节的区域就在堆区?br>strcpy(p1, "123456"); 123456\0攑֜帔R区,~译器可能会它与p3所指向?123456"优化成一个地斏V?br>}


二、堆和栈的理论知?/font>

2.1甌方式
stack:
ql自动分配?例如Q声明在函数中一个局部变?int b; pȝ自动在栈中ؓb开辟空?br>heap:
需要程序员自己甌Qƈ指明大小Q在c中malloc函数
如p1 = (char *)malloc(10);
在C++中用newq算W?br>如p2 = (char *)malloc(10);
但是注意p1、p2本n是在栈中的?br>
2.2甌后系l的响应
栈:只要栈的剩余I间大于所甌I间Q系l将为程序提供内存,否则报异常提示栈溢出?br>堆:首先应该知道操作pȝ有一个记录空闲内存地址的链表,当系l收到程序的甌Ӟ
会遍历该链表Q寻扄一个空间大于所甌I间的堆l点Q然后将该结点从I闲l点链表中删除,q将该结点的I间分配l程序,另外Q对于大多数pȝQ会在这块内存空间中的首地址处记录本ơ分配的大小Q这P代码中的delete语句才能正确的释放本内存I间。另外,׃扑ֈ的堆l点的大不一定正好等于申L大小Q系l会自动的将多余的那部分重新攑օI闲链表中?br>
2.3甌大小的限?/strong>
栈:在Windows?栈是向低地址扩展的数据结构,是一块连l的内存的区域。这句话的意思是栈顶的地址和栈的最大容量是pȝ预先规定好的Q在WINDOWS下,栈的大小?MQ也有的说是1MQM是一个编译时q定的常数Q,如果甌的空间超q栈的剩余空间时Q将提示overflow。因此,能从栈获得的I间较小?br>堆:堆是向高地址扩展的数据结构,是不q箋的内存区域。这是由于系l是用链表来存储的空闲内存地址的,自然是不q箋的,而链表的遍历方向是由低地址向高地址。堆的大受限于计算机系l中有效的虚拟内存。由此可见,堆获得的I间比较灉|Q也比较大?br>

2.4甌效率的比?/strong>
栈由pȝ自动分配Q速度较快。但E序员是无法控制的?br>堆是由new分配的内存,一般速度比较慢,而且Ҏ产生内存片,不过用v来最方便.
另外Q在WINDOWS下,最好的方式是用VirtualAlloc分配内存Q他不是在堆Q也不是在栈是直接在q程的地址I间中保留一快内存,虽然用v来最不方ѝ但是速度快,也最灉|?br>
2.5堆和栈中的存储内?/strong>
栈: 在函数调用时Q第一个进栈的是主函数中后的下一条指令(函数调用语句的下一条可执行语句Q的地址Q然后是函数的各个参敎ͼ在大多数的C~译器中Q参数是由右往左入栈的Q然后是函数中的局部变量。注意静态变量是不入栈的?br>当本ơ函数调用结束后Q局部变量先出栈Q然后是参数Q最后栈指针指向最开始存的地址Q也是dC的下一条指令,E序p点l运行?br>堆:一般是在堆的头部用一个字节存攑֠的大。堆中的具体内容有程序员安排?br>
2.6存取效率的比?/strong>
char s1[] = "aaaaaaaaaaaaaaa";
char *s2 = "bbbbbbbbbbbbbbbbb";
aaaaaaaaaaa是在q行时刻赋值的Q?br>而bbbbbbbbbbb是在~译时就定的;
但是Q在以后的存取中Q在栈上的数l比指针所指向的字W串(例如?快?br>比如Q?br>Qi nclude
void main()
{
char a = 1;
char c[] = "1234567890";
char *p ="1234567890";
a = c[1];
a = p[1];
return;
}
对应的汇~代?br>10: a = c[1];
00401067 8A 4D F1 mov cl,byte ptr [ebp-0Fh]
0040106A 88 4D FC mov byte ptr [ebp-4],cl
11: a = p[1];
0040106D 8B 55 EC mov edx,dword ptr [ebp-14h]
00401070 8A 42 01 mov al,byte ptr [edx+1]
00401073 88 45 FC mov byte ptr [ebp-4],al
W一U在d时直接就把字W串中的元素d寄存器cl中,而第二种则要先把指针D到edx中,在根据edxd字符Q显然慢了?br>
2.7结
堆和栈的区别可以用如下的比喻来看出:
使用栈就象我们去饭馆里吃饭,只管点菜Q发出申P、付钱、和吃(使用Q,吃饱了就赎ͼ不必理会切菜、洗菜等准备工作和洗、刷锅等扫尾工作Q他的好处是快捷Q但是自由度?br>使用堆就象是自己动手做喜Ƣ吃的菜_比较ȝQ但是比较符合自q口味Q而且自由度大?br>


windowsq程中的内存l构


在阅L文之前,如果你连
堆栈是什么多不知道的话,请先阅读文章后面?/font>基础知识?br>
接触q?/font>~程的h都知道,高语言都能通过变量名来讉K内存中的数据。那么这些变量在内存中是如何存放的呢Q程序又是如何用这些变量的呢?下面׃Ҏq行深入的讨论。下文中的C语言代码如没有特别声明,默认都用VC~译的release版?br>
首先Q来了解一?C 语言的变量是如何在内存分部的。C 语言有全局变量(Global)、本地变?Local)Q静态变?Static)、寄存器变量(Regeister)。每U变量都有不同的分配方式。先来看下面q段代码Q?br>
Qi nclude <stdio.h>

int g1=0, g2=0, g3=0;

int main()
{
static int s1=0, s2=0, s3=0;
int v1=0, v2=0, v3=0;

//打印出各个变量的内存地址

printf("0x%08x\n",&v1); //打印各本地变量的内存地址
printf("0x%08x\n",&v2);
printf("0x%08x\n\n",&v3);
printf("0x%08x\n",&g1); //打印各全局变量的内存地址
printf("0x%08x\n",&g2);
printf("0x%08x\n\n",&g3);
printf("0x%08x\n",&s1); //打印各静态变量的内存地址
printf("0x%08x\n",&s2);
printf("0x%08x\n\n",&s3);
return 0;
}

~译后的执行l果是:

0x0012ff78
0x0012ff7c
0x0012ff80

0x004068d0
0x004068d4
0x004068d8

0x004068dc
0x004068e0
0x004068e4

输出的结果就是变量的内存地址。其中v1,v2,v3是本地变量,g1,g2,g3是全局变量Qs1,s2,s3是静态变量。你可以看到q些变量在内存是q箋分布的,但是本地变量和全局变量分配的内存地址差了十万八千里,而全局变量和静态变量分配的内存是连l的。这是因为本地变量和全局/静态变量是分配在不同类型的内存区域中的l果。对于一个进E的内存I间而言Q可以在逻辑上分?个部份:代码区,静态数据区和动态数据区。动态数据区一般就?#8220;堆栈”?#8220;?stack)”?#8220;?heap)”是两U不同的动态数据区Q栈是一U线性结构,堆是一U链式结构。进E的每个U程都有U有?#8220;?#8221;Q所以每个线E虽然代码一P但本地变量的数据都是互不q扰。一个堆栈可以通过“基地址”?#8220;栈顶”地址来描q。全局变量和静态变量分配在静态数据区Q本地变量分配在动态数据区Q即堆栈中。程序通过堆栈的基地址和偏U量来访问本地变量?br>

├———————┤低端内存区域
?…… ?br>├———————┤
?动态数据区 ?br>├———————┤
?…… ?br>├———————┤
?代码??br>├———————┤
?静态数据区 ?br>├———————┤
?…… ?br>├———————┤高端内存区域


堆栈是一个先q后出的数据l构Q栈地址L于{于栈的基地址。我们可以先了解一下函数调用的q程Q以便对堆栈在程序中的作用有更深入的了解。不同的语言有不同的函数调用规定Q这些因素有参数的压入规则和堆栈的^衡。windows API的调用规则和ANSI C的函数调用规则是不一LQ前者由被调函数调整堆栈Q后者由调用者调整堆栈。两者通过“__stdcall”?#8220;__cdecl”前缀区分。先看下面这D代码:

Qi nclude <stdio.h>

void __stdcall func(int param1,int param2,int param3)
{
int var1=param1;
int var2=param2;
int var3=param3;
printf("0x%08x\n",?m1); //打印出各个变量的内存地址
printf("0x%08x\n",?m2);
printf("0x%08x\n\n",?m3);
printf("0x%08x\n",&var1);
printf("0x%08x\n",&var2);
printf("0x%08x\n\n",&var3);
return;
}

int main()
{
func(1,2,3);
return 0;
}

~译后的执行l果是:

0x0012ff78
0x0012ff7c
0x0012ff80

0x0012ff68
0x0012ff6c
0x0012ff70


├———————┤<—函数执行时的栈ӞESPQ、低端内存区?br>?…… ?br>├———————┤
?var 1 ?br>├———————┤
?var 2 ?br>├———————┤
?var 3 ?br>├———————┤
?RET ?br>├———————┤<?#8220;__cdecl”函数q回后的栈顶QESPQ?br>?parameter 1 ?br>├———————┤
?parameter 2 ?br>├———————┤
?parameter 3 ?br>├———————┤<?#8220;__stdcall”函数q回后的栈顶QESPQ?br>?…… ?br>├———————┤<—栈底(基地址 EBPQ、高端内存区?br>

上图是函数调用q程中堆栈的样子了。首先,三个参数以从又到左的ơ序压入堆栈Q先?#8220;param3”Q再?#8220;param2”Q最后压?#8220;param1”Q然后压入函数的q回地址(RET)Q接着跌{到函数地址接着执行Q这里要补充一点,介绍UNIX下的~冲溢出原理的文章中都提到在压入RET后,l箋压入当前EBPQ然后用当前ESP代替EBP。然而,有一介lwindows下函数调用的文章中说Q在windows下的函数调用也有q一步骤Q但Ҏ我的实际调试Qƈ未发现这一步,q还可以从param3和var1之间只有4字节的间隙这点看出来Q;W三步,栈?ESP)减去一个数Qؓ本地变量分配内存I间Q上例中是减?2字节(ESP=ESP-3*4Q每个int变量占用4个字?Q接着初始化本地变量的内存空间。由?#8220;__stdcall”调用p调函数调整堆栈,所以在函数q回前要恢复堆栈Q先回收本地变量占用的内?ESP=ESP+3*4)Q然后取回地址Q填入EIP寄存器,回收先前压入参数占用的内?ESP=ESP+3*4)Ql执行调用者的代码。参见下列汇~代码:

;--------------func 函数的汇~代?------------------

:00401000 83EC0C sub esp, 0000000C //创徏本地变量的内存空?br>:00401003 8B442410 mov eax, dword ptr [esp+10]
:00401007 8B4C2414 mov ecx, dword ptr [esp+14]
:0040100B 8B542418 mov edx, dword ptr [esp+18]
:0040100F 89442400 mov dword ptr [esp], eax
:00401013 8D442410 lea eax, dword ptr [esp+10]
:00401017 894C2404 mov dword ptr [esp+04], ecx

……………………Q省略若q代码)

:00401075 83C43C add esp, 0000003C ;恢复堆栈Q回收本地变量的内存I间
:00401078 C3 ret 000C ;函数q回Q恢复参数占用的内存I间
;如果?#8220;__cdecl”的话Q这里是“ret”Q堆栈将p用者恢?br>
;-------------------函数l束-------------------------


;--------------ȝ序调用func函数的代?-------------

:00401080 6A03 push 00000003 //压入参数param3
:00401082 6A02 push 00000002 //压入参数param2
:00401084 6A01 push 00000001 //压入参数param1
:00401086 E875FFFFFF call 00401000 //调用func函数
;如果?#8220;__cdecl”的话Q将在这里恢复堆栈,“add esp, 0000000C”

聪明的读者看到这里,差不多就明白~冲溢出的原理了。先来看下面的代码:

Qi nclude <stdio.h>
Qi nclude <string.h>

void __stdcall func()
{
char lpBuff[8]="\0";
strcat(lpBuff,"AAAAAAAAAAA");
return;
}

int main()
{
func();
return 0;
}

~译后执行一下回怎么P哈,“"0x00414141"指o引用?0x00000000"内存。该内存不能?read"?#8221;Q?#8220;非法操作”喽!"41"是"A"?6q制的ASCII码了Q那明显是strcatq句出的问题了?lpBuff"的大只?字节Q算q结\0Q那strcat最多只能写??A"Q但E序实际写入?1?A"外加1个\0。再来看看上面那q图Q多出来?个字节正好覆盖了RET的所在的内存I间Q导致函数返回到一个错误的内存地址Q执行了错误的指令。如果能_ֿ构造这个字W串Q它分成三部分Q前一部䆾仅仅是填充的无意义数据以辑ֈ溢出的目的,接着是一个覆盖RET的数据,紧接着是一DshellcodeQ那只要着个RET地址能指向这Dshellcode的第一个指令,那函数返回时p执行shellcode了。但是Y件的不同版本和不同的q行环境都可能媄响这Dshellcode在内存中的位|,那么要构造这个RET是十分困隄。一般都在RET和shellcode之间填充大量的NOP指oQ得exploit有更强的通用性?br>

├———————┤<—低端内存区?br>?…… ?br>├———————┤<—由exploit填入数据的开?br>??br>?buffer ?lt;—填入无用的数据
??br>├———————┤
?RET ?lt;—指向shellcodeQ或NOP指o的范?br>├———————┤
?NOP ?br>?…… ?lt;—填入的NOP指oQ是RET可指向的范围
?NOP ?br>├———————┤
??br>?shellcode ?br>??br>├———————┤<—由exploit填入数据的结?br>?…… ?br>├———————┤<—高端内存区?br>

windows下的动态数据除了可存放在栈中,q可以存攑֜堆中。了解C++的朋友都知道QC++可以使用new关键字来动态分配内存。来看下面的C++代码Q?br>
Qi nclude <stdio.h>
Qi nclude <iostream.h>
Qi nclude <windows.h>

void func()
{
char *buffer=new char[128];
char bufflocal[128];
static char buffstatic[128];
printf("0x%08x\n",buffer); //打印堆中变量的内存地址
printf("0x%08x\n",bufflocal); //打印本地变量的内存地址
printf("0x%08x\n",buffstatic); //打印静态变量的内存地址
}

void main()
{
func();
return;
}

E序执行l果为:

0x004107d0
0x0012ff04
0x004068c0

可以发现用new关键字分配的内存即不在栈中,也不在静态数据区。VC~译器是通过windows下的“?heap)”来实现new关键字的内存动态分配。在?#8220;?#8221;之前Q先来了解一下和“?#8221;有关的几个API函数Q?br>
HeapAlloc 在堆中申请内存空?br>HeapCreate 创徏一个新的堆对象
HeapDestroy 销毁一个堆对象
HeapFree 释放甌的内?br>HeapWalk 枚D堆对象的所有内存块
GetProcessHeap 取得q程的默认堆对象
GetProcessHeaps 取得q程所有的堆对?br>LocalAlloc
GlobalAlloc

当进E初始化Ӟpȝ会自动ؓq程创徏一个默认堆Q这个堆默认所占内存的大小?M。堆对象ql进行管理,它在内存中以铑ּl构存在。通过下面的代码可以通过堆动态申请内存空_

HANDLE hHeap=GetProcessHeap();
char *buff=HeapAlloc(hHeap,0,8);

其中hHeap是堆对象的句柄,buff是指向申L内存I间的地址。那q个hHeapI竟是什么呢Q它的值有什么意义吗Q看看下面这D代码吧Q?br>
#pragma comment(linker,"/entry:main") //定义E序的入?br>Qi nclude <windows.h>

_CRTIMP int (__cdecl *printf)(const char *, ...); //定义STL函数printf
/*---------------------------------------------------------------------------
写到q里Q我们顺便来复习一下前面所讲的知识Q?br>(*?printf函数是C语言的标准函数库中函敎ͼVC的标准函数库由msvcrt.dll模块实现?br>由函数定义可见,printf的参C数是可变的,函数内部无法预先知道调用者压入的参数个数Q函数只能通过分析W一个参数字W串的格式来获得压入参数的信息,׃q里参数的个数是动态的Q所以必ȝ调用者来q堆栈Q这里便使用了__cdecl调用规则。BTWQWindowspȝ的API函数基本上是__stdcall调用形式Q只有一个API例外Q那是wsprintfQ它使用__cdecl调用规则Q同printf函数一Pq是׃它的参数个数是可变的~故?br>---------------------------------------------------------------------------*/
void main()
{
HANDLE hHeap=GetProcessHeap();
char *buff=HeapAlloc(hHeap,0,0x10);
char *buff2=HeapAlloc(hHeap,0,0x10);
HMODULE hMsvcrt=LoadLibrary("msvcrt.dll");
printf=(void *)GetProcAddress(hMsvcrt,"printf");
printf("0x%08x\n",hHeap);
printf("0x%08x\n",buff);
printf("0x%08x\n\n",buff2);
}

执行l果为:

0x00130000
0x00133100
0x00133118

hHeap的值怎么和那个buff的值那么接q呢Q其实hHeapq个句柄是指向HEAP首部的地址。在q程的用户区存着一个叫PEB(q程环境?的结构,q个l构中存攄一些有兌E的重要信息Q其中在PEB首地址偏移0x18处存攄ProcessHeap是q程默认堆的地址Q而偏U?x90处存放了指向q程所有堆的地址列表的指针。windows有很多API都用进E的默认堆来存放动态数据,如windows 2000下的所有ANSI版本的函数都是在默认堆中甌内存来{换ANSI字符串到Unicode字符串的。对一个堆的访问是序q行的,同一时刻只能有一个线E访问堆中的数据Q当多个U程同时有访问要求时Q只能排队等待,q样侉K成E序执行效率下降?br>
最后来说说内存中的数据寚w。所位数据对齐,是指数据所在的内存地址必须是该数据长度的整数倍,DWORD数据的内存v始地址能被4除尽QWORD数据的内存v始地址能被2除尽Qx86 CPU能直接访问对齐的数据Q当他试图访问一个未寚w的数据时Q会在内部进行一pd的调_q些调整对于E序来说是透明的,但是会降低运行速度Q所以编译器在编译程序时会尽量保证数据对齐。同样一D代码,我们来看看用VC、Dev-C++和lcc三个不同~译器编译出来的E序的执行结果:

Qi nclude <stdio.h>

int main()
{
int a;
char b;
int c;
printf("0x%08x\n",&a);
printf("0x%08x\n",&b);
printf("0x%08x\n",&c);
return 0;
}

q是用VC~译后的执行l果Q?br>0x0012ff7c
0x0012ff7b
0x0012ff80
变量在内存中的顺序:b(1字节)-a(4字节)-c(4字节)?br>
q是用Dev-C++~译后的执行l果Q?br>0x0022ff7c
0x0022ff7b
0x0022ff74
变量在内存中的顺序:c(4字节)-中间盔R3字节-b(?字节)-a(4字节)?br>
q是用lcc~译后的执行l果Q?br>0x0012ff6c
0x0012ff6b
0x0012ff64
变量在内存中的顺序:同上?br>
三个~译器都做到了数据对齐,但是后两个编译器昄没VC“聪明”Q让一个char占了4字节Q浪费内存哦?br>

基础知识Q?/font>
堆栈是一U简单的数据l构Q是一U只允许在其一端进行插入或删除的线性表。允许插入或删除操作的一端称为栈Ӟ另一端称为栈底,对堆栈的插入和删除操作被UCؓ入栈和出栈。有一lCPU指o可以实现对进E的内存实现堆栈讉K。其中,POP指o实现出栈操作QPUSH指o实现入栈操作。CPU的ESP寄存器存攑ֽ前线E的栈顶指针QEBP寄存器中保存当前U程的栈底指针。CPU的EIP寄存器存放下一个CPU指o存放的内存地址Q当CPU执行完当前的指o后,从EIP寄存器中d下一条指令的内存地址Q然后l执行?

 <br>

堆(HeapQ栈QStackQ?

1、内存分配方面:

    堆:一般由E序?/strong>分配释放Q?若程序员不释放,E序l束时可能由OS回收 。注意它与数据结构中的堆是两回事Q分配方式是cM于链表。可能用到的关键字如下:new?strong>malloc?strong>delete?strong>free{等?

    栈:?strong>~译?/strong>(Compiler)自动分配释放Q存?strong>函数的参数?/strong>Q?strong>局部变?/strong>的值等。其操作方式cM于数据结构中的栈?

2、申h式方面:

    堆:需要程序员自己甌Qƈ指明大小。在c中malloc函数如p1 = (char *)malloc(10)Q在C++中用newq算W,但是注意p1、p2本n是在栈中的。因Z们还是可以认为是局部变量?

    栈:ql自动分配?例如Q声明在函数中一个局部变?int bQ系l自动在栈中为b开辟空间?

3、系l响应方面:

    堆:操作pȝ有一个记录空闲内存地址的链表,当系l收到程序的甌Ӟ会遍历该链表Q寻扄一个空间大于所甌I间的堆l点Q然后将该结点从I闲l点链表中删除,q将该结点的I间分配l程序,另外Q对于大多数pȝQ会在这块内存空间中的首地址处记录本ơ分配的大小Q这样代码中的delete语句才能正确的释放本内存I间。另外由于找到的堆结点的大小不一定正好等于申L大小Q系l会自动的将多余的那部分重新攑օI闲链表中?

    栈:只要栈的剩余I间大于所甌I间Q系l将为程序提供内存,否则报异常提示栈溢出?

4、大限制方面:

    堆:?strong>向高地址扩展的数据结构,?strong>不连l?/strong>的内存区域。这是由于系l是用链表来存储的空闲内存地址的,自然是不q箋的,而链表的遍历方向是由低地址向高地址。堆的大受限于计算机系l中有效的虚拟内?/strong>。由此可见,堆获得的I间比较灉|Q也比较大?

    栈:在Windows? 栈是向低地址扩展的数据结构,是一?strong>q箋的内存的区域。这句话的意思是栈顶的地址和栈的最大容量是pȝ预先规定?/strong>的,在WINDOWS下,栈的大小是固定的Q是一个编译时q定的常数Q,如果甌的空间超q栈的剩余空间时Q将提示overflow。因此,能从栈获得的I间较小?

5、效率方面:

    堆:是由new分配的内存,一般速度比较慢,而且Ҏ产生内存片Q不q用h最方便Q另外,在WINDOWS下,最好的方式是用VirtualAlloc分配内存Q他不是在堆Q也不是在栈是直接在q程的地址I间中保留一快内存,虽然用v来最不方ѝ但是速度快,也最灉|?

    栈:ql自动分配,速度较快。但E序员是无法控制的?

6、存攑ֆҎ面:

    堆:一般是在堆的头部用一个字节存攑֠的大?strong>堆中的具体内ҎE序员安排?/strong>

    栈:在函数调用时W一个进栈的是主函数中后的下一条指令(函数调用语句的下一条可执行语句Q的地址然后是函数的各个参数Q在大多数的C~译器中Q?strong>参数是由叛_左入?/strong>Q然后是函数中的局部变量?注意: 静态变量是不入栈的。当本次函数调用l束后,局部变量先出栈Q然后是参数Q最后栈指针指向最开始存的地址Q也是dC的下一条指令,E序p点l运?/strong>?

7、存取效率方面:

    堆:char *s1 = "Hellow Word"Q是?strong>~译?/strong>q定的Q?

    栈:char s1[] = "Hellow Word"Q?是在q行?/strong>赋值的Q用数组比用指针速度要快一些,因ؓ指针在底层汇~中需要用edx寄存器中转一下,而数l在栈上直接d?/p>
 

Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=1925576



HUYU 2008-01-10 13:22 发表评论
]]>
Variable Parameters Print Examplehttp://www.shnenglu.com/HUUYUU/archive/2007/01/19/17792.htmlHUYUHUYUFri, 19 Jan 2007 09:55:00 GMThttp://www.shnenglu.com/HUUYUU/archive/2007/01/19/17792.htmlhttp://www.shnenglu.com/HUUYUU/comments/17792.htmlhttp://www.shnenglu.com/HUUYUU/archive/2007/01/19/17792.html#Feedback0http://www.shnenglu.com/HUUYUU/comments/commentRss/17792.htmlhttp://www.shnenglu.com/HUUYUU/services/trackbacks/17792.html#include <stdio.h>
#include <string.h>
#include <stdarg.h>

#include "drm_korea_def.h"

#ifdef __KDRM_FSTRACE

#define LOG_BUFFER_SIZE 512
#define LOG_LINE_NUM  16

#ifdef WIN32
#define LOG_FILE     FILE *
#define LOG_OPEN(s, m)   fopen(s, m)
#define LOG_CLOSE(hLog)   fclose(hLog)
#define LOG_READ (hLog, p, x)  fread (p, x, 1, hLog)
#define LOG_WRITE(hLog, p, x) fwrite(p, x, 1, hLog)
#define LOG_PUTC(hLog, c)  fputc(c, hLog)
#define LOG_PUTS(hLog, s)  fputs(s, hLog)
#else
#define LOG_FILE     int32_t
#define LOG_OPEN(s, m)   Fopen((uint8_t *)s, (uint8_t *)m)
#define LOG_CLOSE(hLog)   Fclose(hLog)
#define LOG_READ (hLog, p, x)  Fread (hLog,  p, x)
#define LOG_WRITE(hLog, p, x) Fwrite(hLog, p, x)
#define LOG_PUTC(hLog, c)  Fputc(hLog, c)
#define LOG_PUTS(hLog, s)  Fputs(hLog, (uint8_t *)s)
#endif

static LOG_FILE fpLogfile;
static char logBuffer[LOG_BUFFER_SIZE];

void log_Init(char *logName)
{
 fpLogfile = LOG_OPEN(logName, "w+");

 if(fpLogfile > 0)
 {
  log_Print("\r\n====> Starting ... :%s %s\r\n", __TIME__, __FILE__);
 }
}

void log_Print(char *logFormat, ...)
{
 if(fpLogfile > 0)
 {
  va_list va;
  int len;

  va_start(va, logFormat);
  len = vsprintf(logBuffer, logFormat, va);
  va_end(va);

  logBuffer[len+1] = 0;

  LOG_PUTS(fpLogfile, logBuffer);
 }
}

char Hex2Dec(unsigned char bHex)
{
 bHex &= 0x0F;
 bHex += bHex<10? '0': 'A' - 10;

 return bHex;
}

void log_Dump(const unsigned char  *pCache, int u32Size, bool bBinary)
{
 int i, stride;
 unsigned char *p = (unsigned char  *)pCache;
 char cTmp;

 if(fpLogfile < 0)
  return;

 if(bBinary)
 {
  for(; p<pCache+u32Size; p+=LOG_BUFFER_SIZE)
  {
   stride = (p+LOG_BUFFER_SIZE <= pCache+u32Size)? LOG_BUFFER_SIZE: u32Size%LOG_BUFFER_SIZE;
   LOG_WRITE(fpLogfile, p, stride);
  }
 }
 else
 {
  for(; p<pCache+u32Size; p+=LOG_LINE_NUM)
  {
   stride = (p+LOG_LINE_NUM <= pCache+u32Size)? LOG_LINE_NUM:u32Size%LOG_LINE_NUM;

   for(i=0; i<stride; i++)
   {
    cTmp = Hex2Dec((p[i]&0xF0) >> 4);
    LOG_PUTC(fpLogfile, cTmp);
    cTmp = Hex2Dec(p[i]&0x0F);
    LOG_PUTC(fpLogfile, cTmp);
    LOG_PUTC(fpLogfile, ' ');
    if(i== (LOG_LINE_NUM/2 - 1))
    {
     LOG_PUTC(fpLogfile, '-');
     LOG_PUTC(fpLogfile, ' ');
    }
   }

   LOG_PUTC(fpLogfile, '\n');
  }
 }
}

void log_Terminate(void)
{
 if(fpLogfile > 0)
 {
  log_Print("<==== Stopping ... :%s\r\n", __TIME__);
  LOG_CLOSE(fpLogfile);
 }
}

#endif //__KDRM_FSTRACE



HUYU 2007-01-19 17:55 发表评论
]]>
FreeType2研究 http://www.shnenglu.com/HUUYUU/archive/2006/11/10/14985.htmlHUYUHUYUFri, 10 Nov 2006 15:00:00 GMThttp://www.shnenglu.com/HUUYUU/archive/2006/11/10/14985.htmlhttp://www.shnenglu.com/HUUYUU/comments/14985.htmlhttp://www.shnenglu.com/HUUYUU/archive/2006/11/10/14985.html#Feedback5http://www.shnenglu.com/HUUYUU/comments/commentRss/14985.htmlhttp://www.shnenglu.com/HUUYUU/services/trackbacks/14985.html FreeType2研究

最q学习状态不佻I感觉什么都惛_却什么也做不下去QQw之极。大的库一下子研究不下来,索性找一下小库来看看?br />游戏里面一般都涉及到文本、压~、图像、脚本的概念Qؓ了将来有Z研究游戏所以先下手q些库Q不求甚解只求用好?br />
先从字体着手,FreeType字体作ؓ一U字体文件编E开发包Q广泛易用在游戏里面。网上汉语资料比较少Q只能看它的faq。翻译了部分如下Q?br />

FreeType 2 Library

FAQ

Q当前下载地址Q?/span> http://sourceforge.net/project/showfiles.php?group_id=3157 版本 2.2.1 Q?/span>

1?span style="FONT: 7pt 'Times New Roman'">  FreeType2 是什么?

它是一个ؓ各种应用E序提供通用的字体文件访问的软g包。尤其值得注意的以下特性:

l         提供l一的字体文件访问接口。支持位囑֒向量格式Q包?/span> TrueType ?/span> OpenType ?/span> Typel ?/span> CID ?/span> CFF ?/span> Windows FON/FNT ?/span> X11 PCF ?/span>

l         提供高效反走LZ 256 灰度U的位图字Ş的生产?/span>

l         模块清晰Q每U字体格式对于一个模块。类库的构徏可以按照你需要支持的格式q行裁减以减代码尺寸。(最的反走?/span> FreeType ?/span> <30Kb Q?/span>

2?span style="FONT: 7pt 'Times New Roman'">  FreeType2 能做什么?

FT2 已经易用于许多领域。例如:

l         囑Ş子系l和文本昄?/span>

l         文本排版Q布局、分c渲染)

l         字体识别和{换工?/span>

一般来_该库使得你能L的操U字体文件?/span>

3?span style="FONT: 7pt 'Times New Roman'">  FreeType2 不能做什么?

FT2 q不包含大量丰富的高U特性,它只定位于出色的字体服务。也是说下面的一些特?/span> FT2 cdq不直接提供支持Q然而你可以以它为基在上层进行实玎ͼ

l         L表面的文字渲?/span>

FT2 不是囑Ş库所以它仅支持两U象素格式的文本渲染Q?/span> 1-bit 的单色位囑֒ 8-bit 的灰度象素?/span>

如果你需要绘制其它格式的表面Q例?/span> 24-bit RGB 象素Q,你就得选择其它你喜q囑Ş库来做?/span>

注意Qؓ了渲染向量轮廓文本而不是放走样的象素,应用E序可以提供自己的渲染回调以l制或者直接组合反走样文本CQ意目标表面?/span>

l         文本~存

每次从字体中h文本图象Q?/span> FT2 都要解析字体文g / 相关部分,通过它的字体格式q行解释。对于某些特D格式可能会很慢包括?/span> TrueType Q或?/span> Type1 Q这L向量字体?/span>

注意Q自?/span> 2.0.1 版本开?/span> FT2 提供了一?/span> beta 版本的缓存子pȝ。当然你q是可以写自q~存来满xU特D需求?/span>

l         文本布局

不支持文本布局操作。高U操作例如文本替换、字距调整、两端调整等都不属于字体服务本n职责?/span>

4?span style="FONT: 7pt 'Times New Roman'">  FreeType2 可移植性?

FT2 源码可移植性很好由于以下原因:

l         代码书写遵@ ANSI C 标准

l         对于各种~译警告我们都}慎的避免。当前代码在很多~译器上~译通过且没有生一条警告?/span>

l         库没有用Q何硬~码Q是嵌入式系l开发的一个好的选择。(例如它能够直接在 ROM 中运行)

同时Q我们尽最大努力确保库的高效、紧凑和友好性?/span>

5?span style="FONT: 7pt 'Times New Roman'">  FreeType2 ?/span> FreeType1.x 的区别?

最大的区别是Q?/span>

l         FT1 仅支?/span> TrueType 格式Q?/span> FT2 支持很多格式?/span>

l         FT2 APIs ?/span> FT1 APIs 单且强大?/span>

l         FT1 包括 OpenType 文本布局处理扩展Q?/span> FT2 中则不包括而是Ud独立的工E里面―?/span> FreeType Layout 。( FT 布局目前无法获取Q?/span>

6?span style="FONT: 7pt 'Times New Roman'">  FreeType2 是否兼容 FreeType 1.x Q?/span>

FreeType2 不直接兼?/span> FreeType 1.x Q但是我们可以提供一个二q制兼容层得应用程序重链接到新版本。我们最l放弃了q种x因ؓ两个版本可以共存在一个系l中。(没有命名冲突Q?/span>

FT2 API ?/span> 1.x 单且强大Q所以我们鼓׃采用新版本,q样可以使你减少很多不必要的工作?/span>

7?span style="FONT: 7pt 'Times New Roman'">  是否可以使用 FreeType2 ~辑字体或者创建新字体Q?/span>

{案是明的Q不可以。因库设计明,用较代码和内存d字体文g。所以我们不打算以Q何方式在字体引擎里面支持~辑或者创建功能,因ؓq样导致整个代码重写。这q不意味我们来不会引入字体~辑 / 创徏功能库,q取决于需求(或者说有多h愿意为此买单Q?/span>

在我们正式发布前不要在这斚wq行揣测Q对我们而言q个目存在其他一些更重要的部分需要解冻I像文字布局、文本缓存)?/span>

~译 & 配置

1?span style="FONT: 7pt 'Times New Roman'">  如何~译 FreeType2 库?

可以采取多种~译方式Q在 freetype2/docs/build 下有详细说明文档?/span>

q里介绍最单的Z VS IDE 的编译方式?/span> freetype\builds\win32\visualc 下有 VC6 ?/span> VC7.1 的工作区文g?/span> VC6 打开后直接编译,有几个警告?br />


光看或许无法到感性认识,于是来两个demo。网上比较少Q我是参考nehe教程写的。M来说会简单用了Q如果想深入了解怕是非看他的document不可?br />单用示?/span>

FT_Library    pFTLib         =  NULL;
    FT_Face        pFTFace        
=  NULL;
    FT_Error    error        
=   0 ;
    
//  Init FreeType Lib to manage memory
    error  =  FT_Init_FreeType( & pFTLib);
    
if (error)
    
{
        pFTLib 
=   0 ;
        printf(
" There is some error when Init Library " );
        
return   - 1 ;
    }


    
//  create font face from font file
    error  =  FT_New_Face(pFTLib,  " C:\\WINDOWS\\Fonts\\arial.ttf " 0 & pFTFace);
    
if ( ! error)
    
{
        FT_Set_Char_Size(pFTFace, 
16 << 6 16 << 6 300 300 );
        FT_Glyph    glyph;
        
//  load glyph 'C'
        FT_Load_Glyph(pFTFace, FT_Get_Char_Index(pFTFace,  67 ), FT_LOAD_DEFAULT);
        error 
=  FT_Get_Glyph(pFTFace -> glyph,  & glyph);
        
if ( ! error)
        
{
            
//  convert glyph to bitmap with 256 gray
            FT_Glyph_To_Bitmap( & glyph, ft_render_mode_normal,  0 1 );
            FT_BitmapGlyph    bitmap_glyph 
=  (FT_BitmapGlyph)glyph;
            FT_Bitmap
&     bitmap  =  bitmap_glyph -> bitmap;
            
for ( int  i = 0 ; i < bitmap.rows;  ++ i)
            
{
                
for ( int  j = 0 ; j < bitmap.width;  ++ j)
                
{
                    
//  if it has gray>0 we set show it as 1, o otherwise
                    printf( " %d " , bitmap.buffer[i * bitmap.width + j] ? 1 : 0 );
                }

                printf(
" \n " );
            }

            
//  free glyph
            FT_Done_Glyph(glyph);
            glyph 
=  NULL;
        }

        
//  free face
        FT_Done_Face(pFTFace);
        pFTFace 
=  NULL;
    }


    
//  free FreeType Lib
    FT_Done_FreeType(pFTLib);
    pFTLib 
=  NULL;


HUYU 2006-11-10 23:00 发表评论
]]>
从笑话中悟出C++开发管理之"? http://www.shnenglu.com/HUUYUU/archive/2006/10/30/14352.htmlHUYUHUYUMon, 30 Oct 2006 00:49:00 GMThttp://www.shnenglu.com/HUUYUU/archive/2006/10/30/14352.htmlhttp://www.shnenglu.com/HUUYUU/comments/14352.htmlhttp://www.shnenglu.com/HUUYUU/archive/2006/10/30/14352.html#Feedback0http://www.shnenglu.com/HUUYUU/comments/commentRss/14352.htmlhttp://www.shnenglu.com/HUUYUU/services/trackbacks/14352.html1. E序员写认ؓ没有Bug的代码?

2. 软g试Q发C20个Bug?

3. E序员修改了10个BugQƈ告诉试l另?0个不是Bug?

4. 试l发现其?个改动根本无法工作,同时又发C15个新Bug?

5. 重复3ơ步?和步??

6. 鉴于市场斚w的压力,Z配合当初制定的过分乐观的发布旉表,产品l于上市了?

7. 用户发现?37个新Bug?

8. 已经领了目奖金的程序员不知跑到哪里M?

9. 新组建的目l修正了差不多全?37个BugQ但又发C456个新Bug?

10. 最初那个程序员从斐给饱受拖欠工资之苦的测试组寄来了一张明信片。整个测试组集体辞职.

11. 公司被竞争对手恶意收购。收购时QY件的最l版本包?83个Bug?

12. 新CEO走马上Q。公叔R了一名新E序员重写该软g?

13. E序员写认ؓ没有Bug的代码?

  要我_如果真有q样的公司,不倒闭对不起h民?

 q个W话从程序员开始,到程序员l束Q从头到N在说E序员的不是。但是我要说的是Q这完全是管理者的p|Q从整个q程中,看不CQ何管理工作。这U管理者不但无知无能,q很无耠Z—将自己的失败责Ll程序员?

 1、程序员凭什么证明他的代码没有BUGQ有Test case吗?有Code review吗?q个环节理~失?

 2、测试发现BUG有进行BUG理吗?有跟t吗Q这个环节管理缺失?br /> 3、凭什么证明程序员已经把那10个BUG修改好了Q另10个又Z么不是BUGQBUG的评h准难道是E序员说了算Q这个环节管理缺失?

 4?个不能工作的BUG修改问题有没有追I责任?增加新BUG是修改过E中不可避免的事情,但是如果有有效的单元试机制Q可以大大减这U情c这个环节管理缺失?

 5、P代是正常的,但是问题处理于发散而不是收敛发展,可见没有有效的管理调控。这个环节管理缺失?

 6、过于乐观的旉表和不可能达到的最后期限,都表现出理者的无知和无能。而在q样的情况下推出产品Q那是无知者无畏了?

 7、这是对用户的不负责任,理者要负最大的责Q?

 8、这L情况q能发项目奖金,只能说管理者不是一般的愚蠢?

 9、管理工作没有Q何的改进Q问题仍然处于发散P代状态。管理工作依然没有到位?

 10、拖Ơ测试部门工资体现出理者对质量理工作的忽视以及对人力资源理斚w一无所知?

 11、送被收购者两个字Q活该。送收购者两个字Q瞎眹{?

 12、可见新理者与原管理者半斤八两,都没有认识到问题的根本所在。不q也只有q样的管理者才会作出收购这U公司的决策?

 13、历史的重演是必然的?

 一个正常的企业或是目Q其q作必须应该是@环向上进行的。而保障这U运行的工作是理。而管理工作的主要内容是控制Q包括控制@环的节奏——不能太快也不能太慢Q控制发展的方向——只能向上不能向下,控制q作的稳定——不能大起大落或时聚时散{?br /> 而这一切,在这个例子中都看不到?

 在这个笑话的例子中,一切都是以开发工作在驱动Q这首先是一个方向性错误,产品是ؓ用户服务的,当然应该是以用户和市Z为驱动,q且l合自n的能力最l?定工作的重炏V这一错误折射出管理者对被管理的内容很不了解Q只好Q由比较了解的E序员摆布——事实上他们除了技术,q不会了解更多?

 一个管理者如果对自己所理的内容不了解Q他׃可能理得好?

 q是一件毫无疑问的事,可是国内的Y件业gL不相信这一炏V中国Y件业中流毒最q谎言之一是Q?

 理者只要懂理可以,不需要懂技术?

其实q不q是那些无知无能无ȝ理者ؓ了骗p编出来的,怿q句话的人必付出金q代h?

 其次是质量管理。基本的质量理常识告诉我们Q每ơ@环结束前Q最重的工作是ȝ改进。只有这h能保证@环运作是向上发展Q而不是失L制地向下发展?也只有有效的质量理Q才能保证P代过E是收敛发展Qƈ最l达到目标。但在这个例子中Q这个部分显然是~失的——其中虽然有试部门Q但是他们的作用仅仅 是质量管理中的质量检环节,理部分q是~失的?

 然后是h力资源管理。Y件开发是一劳动密集型的工作,虽然q是脑力力_Q但同样意味着人在因素在其中占有决定性的C。而例子中未改完BUG的程 序员拿到目奖金Q而同栯苦工作的试人员却被拖欠薪资Q除了表现出理者对他们的工作内容的不了解,以及对质量管理工作的不重视以外,q表现出理?完全不会hQ这是一U谋杀团队的行为——谋杀一个团队远比徏设要Ҏ得多?

 最后,q个p|的管理者把他的l历~成q个W话Q让大家看到他被E序员们宛_多惨Q把E序员妖化Z骗子。但只要E懂理的h单分析一下就可以看出来,只不q是q个人的无知和无能造成了他现在的结果,而把责Q推给别h的行为更是表现出他的无者R?

 作ؓw居高位的管理者,如果q应该承担的责Q都要推卸Q他们还能胜M么事情呢?



HUYU 2006-10-30 08:49 发表评论
]]>
x对TinyXML的应?/title><link>http://www.shnenglu.com/HUUYUU/archive/2006/10/13/13638.html</link><dc:creator>HUYU</dc:creator><author>HUYU</author><pubDate>Fri, 13 Oct 2006 05:56:00 GMT</pubDate><guid>http://www.shnenglu.com/HUUYUU/archive/2006/10/13/13638.html</guid><wfw:comment>http://www.shnenglu.com/HUUYUU/comments/13638.html</wfw:comment><comments>http://www.shnenglu.com/HUUYUU/archive/2006/10/13/13638.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.shnenglu.com/HUUYUU/comments/commentRss/13638.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/HUUYUU/services/trackbacks/13638.html</trackback:ping><description><![CDATA[x对TinyXML的应?br /><a ><font color="#3f3f9f">http://sourceforge.net/projects/tinyxml/<br /></font></a><img src ="http://www.shnenglu.com/HUUYUU/aggbug/13638.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/HUUYUU/" target="_blank">HUYU</a> 2006-10-13 13:56 <a href="http://www.shnenglu.com/HUUYUU/archive/2006/10/13/13638.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>strlen & strcmphttp://www.shnenglu.com/HUUYUU/archive/2006/10/04/13288.htmlHUYUHUYUTue, 03 Oct 2006 16:02:00 GMThttp://www.shnenglu.com/HUUYUU/archive/2006/10/04/13288.htmlhttp://www.shnenglu.com/HUUYUU/comments/13288.htmlhttp://www.shnenglu.com/HUUYUU/archive/2006/10/04/13288.html#Feedback0http://www.shnenglu.com/HUUYUU/comments/commentRss/13288.htmlhttp://www.shnenglu.com/HUUYUU/services/trackbacks/13288.htmlunsigned int strlenW(const wchar_t *wcs)
{
 const wchar_t *eos = wcs;

 while (*eos)
     ++eos;

 return eos-wcs;
}


int strcmpW(const wchar_t *pwc1, const wchar_t *pwc2)
{
 int ret = 0;

 while ( !(ret = *pwc1 - *pwc2) && *pwc2)
  ++pwc1, ++pwc2;
 return ret;
}



HUYU 2006-10-04 00:02 发表评论
]]>
如何识别字符串的~码Q?/title><link>http://www.shnenglu.com/HUUYUU/archive/2006/10/04/13287.html</link><dc:creator>HUYU</dc:creator><author>HUYU</author><pubDate>Tue, 03 Oct 2006 16:01:00 GMT</pubDate><guid>http://www.shnenglu.com/HUUYUU/archive/2006/10/04/13287.html</guid><wfw:comment>http://www.shnenglu.com/HUUYUU/comments/13287.html</wfw:comment><comments>http://www.shnenglu.com/HUUYUU/archive/2006/10/04/13287.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.shnenglu.com/HUUYUU/comments/commentRss/13287.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/HUUYUU/services/trackbacks/13287.html</trackback:ping><description><![CDATA[ <div id="l93vn99" class="postbody">如果哪一天你的程序收CD不明编码的字符Ԍ或者别人给了一个你看不懂的文本文gQ你应该如何去识别字W串的编码呢Q?br /><br />一U是E序中用的方法,可以使用ICU之类的库来帮你识别,如果你的字符串越长,它所能猜到的概率p大?br /><br />另外一U方法是使用IE来帮助你查看。用IE打开不明~码的文Ӟ然后选择EncodingQ不停的切换~码Q基本上看v来像文字的时候,是那个~码?).q个Ҏ很简单,比较实用?br /><br />另外对于unicode的编码,观察其BOMQ也有助于你ȝ编码?br />UTF-8: <strong>EF BB BF</strong> E6 B5 8B E8 AF 95 31 32 33 34<br />UTF-16: <strong>FF FE</strong> 4B 6D D5 8B 31 00 32 00 33 00 34 00<br />UTF-16 Big endian : <strong>FE FF</strong> 6D 4B 8B D5 00 31 00 32 00 33 00 34<br /><br /><br />最后附上两个小工具Q能帮你生成各种文字的字W和识别字符在不同code page下的~码。just have fun<br /><br /><a href="/Files/sandy/encoding_tools.rar">http://www.shnenglu.com/Files/sandy/encoding_tools.rar</a><br /></div> <img src ="http://www.shnenglu.com/HUUYUU/aggbug/13287.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/HUUYUU/" target="_blank">HUYU</a> 2006-10-04 00:01 <a href="http://www.shnenglu.com/HUUYUU/archive/2006/10/04/13287.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>c++中的string用法(?http://www.shnenglu.com/HUUYUU/archive/2006/09/04/12018.htmlHUYUHUYUMon, 04 Sep 2006 10:49:00 GMThttp://www.shnenglu.com/HUUYUU/archive/2006/09/04/12018.htmlhttp://www.shnenglu.com/HUUYUU/comments/12018.htmlhttp://www.shnenglu.com/HUUYUU/archive/2006/09/04/12018.html#Feedback0http://www.shnenglu.com/HUUYUU/comments/commentRss/12018.htmlhttp://www.shnenglu.com/HUUYUU/services/trackbacks/12018.html阅读全文

HUYU 2006-09-04 18:49 发表评论
]]>
ձWVһһþ㽶| һaƬþëƬ| Ʒݾþþþø| ƷžžþƵ| þԭƷ| 㽶þþþþúݺɫ| պĻþ| þۺ϶㼤þ| ޾Ʒþþþþþþþþþ | պ޹ۺϾþþ| þ޾ƷƷ| ˾ƷѾþþþ| պŷ޹ƷĻþþ| þþƷAV͵| þó18վ| vĻþ| þþþƷ޳18վ | LƷþ| þþƷަvDz| ɫþþ99Ʒ91| ޾ƷҾþþþþ| þƵ| þþþþྫƷֱ| 77777ҹþö| þAV뾫Ʒ| þоƷƵ| 9þ9þþƷ| þþž޾Ʒ| þþƵ| 2022Ʒþþþ | þþžžƷ99Ʒ| ޹Ʒľþþ| þþƷƷƾ| þúݺһƷۺ| ƷѾþþþӰԺ| Ʒþþþ9999| AAAþþþƷƬ| žžþȻ㽶ͼƬ| þþƷƷëƬ| ŷ޾ƷþþavӰ| Ըߺþþþþþþ|