最近太忙,博客也好久没有打理了,主要是没有东西可写,呵呵~
写代码的时候,在delete的时候遇到一个错误,提示“T.exe 中的 0x002a1614 处未处理的异常: 0xC0000005: 读取位置 0xfeeefeee 时发生访问冲突”,立刻就被其中的0xFEEEFEEE吸引住了,显然,这样的地址在用户空间(User Space)是不可能用到的,刚好前不久看到一条微博说调试器也有Magic Number,利用16进制构造出一些很有意思的数据,于是马上Google了一下0xFEEEFEEE,果然,Windows上的堆管理器会给delete掉后的内存空间填充0xFEEEFEEE,也就是说,在出现这个异常的时候,已经是第二次delete了。
平时写代码的时候,我并没有给delete之后的指针再次赋值为NULL的习惯,但是这次,加上这个动作也不行了,后来仔细一看,还是指针参数传递造成的一个误区。先看代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 | #include <iostream> #include <stdio.h> #include <string.h> #include <stdlib.h> using namespace std; const int nMaxSize = 26; struct Node { Node *next[nMaxSize]; Node() { for (int i = 0; i < nMaxSize; ++i) { next[i] = NULL; } } }; Node root; void Insert(char *pStr) { Node *p = &root; for (int i = 0; i < strlen(pStr); ++i) { int id = pStr[i] - 'a'; if (p->next[id] != NULL) { printf("test log\n"); } else { p->next[id] = new Node(); } } } void Delete(Node *p) { if (p == NULL) return ; for (int i = 0; i < nMaxSize; ++i) { Delete(p->next[i]); } if (p == &root) return ; delete p; p = NULL; } int main(int argc, char **argv) { printf("Insert a string\n"); Insert("a"); Delete(&root); printf("Insert the same string again\n"); Insert("a"); Delete(&root); return 0; } |
示例代码,大概意思是建立了一个字典树(无关的代码都省了),然后在main中插入一个字符串”a”,接着删除字典树,再次插入字符串”a”,再次删除的时候,调用Delete函数,就会触发异常了。
异常分析:给字典树插入字符串的时候,根节点的26个子节点都是NULL,这时候插入a,将在第0个节点分配一块内存。删除的时候通过将根节点的地址传递给Delete()函数,确实是将分配的内存delete掉了。然后你还看到我特意加了一句空指针赋值(第47行代码),值得注意的时候,这一句并没有起到我想要的作用。以至于在第二次插入字符串a的时候,第0个节点并不是NULL,所以我们看到执行了printf输出log,也没有去分配新的内存了。
明明在第47行进行了NULL赋值,为什么进入了第27行的if语句?因为通过Delete()函数传入的指针只不过是一个临时变量而已,之所以能通过delete删除内存块,是因为他确确实实指向了用new分配的节点内存块,但是他不是root节点的成员(也就是next数组中的第一个元素),所以我们只是讲一个临时的指针指向了NULL,毫无意义。
接下来,就是奇迹发生的时刻了。因为root的next数组第一个成员仍然指向内存块(最主要的是这个内存块已经被delete掉了),自然就通过了if语句的非空判断,这里就没有继续分配内存了,只是因为这里并没有对这个指针进行读写操作,所以直到delete的时候才发生了异常。
我的解决方法是,调用Delete()之后,通过memset对root进行清零操作。
奇葩的错误到此为止,下面进入文章的主题,调试器也有MagicNumer:
Many computer processors, operating systems, and debuggers make use of magic numbers, especially as a magic debug value. 0x0000000FF1CE ("office") is used as the last part of product codes (guid) for Microsoft Office components (visible in registry under HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall registry key). 0x00BAB10C ("oo-ba-block") is used as the magic number for the ZFS uberblock. 0x8BADF00D ("ate bad food") is used by Apple in iOS crash reports, when an application takes too long to launch, terminate, or respond to system events.[1] 0x1BADB002 ("1 bad boot"[2]) Multiboot header magic number.[3] 0x1CEB00DA ("ice buddha") was used as the origin for the binary file parser IceBuddha.[4] 0xB16B00B5 ("big boobs") was required by Microsoft's Hyper-V hypervisor to be used by Linux guests as their "guest signature".[5] This offending code was later changed to 0x0DEFACED ("defaced").[6] 0xBAADF00D ("bad food") is used by Microsoft's LocalAlloc(LMEM_FIXED) to indicate uninitialised allocated heap memory when the debug heap is used.[7] 0xBADDCAFE ("bad cafe") is used by Libumem to indicate uninitialized memory area C15C:0D06:F00D ("cisco dog food") used in the IPv6 address of www.cisco.com on World IPv6 Day. "Dog food" refers to Cisco eating its own dog food with IPv6. 0xCAFEBABE ("cafe babe") is used by Mach-O to identify Universal object files, and by the Java programming language to identify Java bytecode class files.[8] 0xCAFED00D ("cafe dude") is used by Java as a magic number for their pack200 compression.[9] 0xCEFAEDFE ("face feed") is used by Mach-O to identify flat (single architecture) object files. In little endian this reads FEEDFACE, "Feed Face". 0xD15EA5E ("disease") is a flag that indicates regular boot on the Nintendo GameCube and Wii consoles.[10][11] 0xDABBAD00 ("dabba doo") is the name of a blog on computer security.[12] 0xDEADBABE ("Dead Babe") is used by IBM Jikes RVM as a sanity check of the stack of the primary thread [13] 0xDEADBEAF ("dead beaf") is part of the signature code of Jazz Jackrabbit 2 tileset files.[14] Level files have less room for their signatures and use 0xBABE ("babe") instead.[15] 0xDEADBEEF ("dead beef") is frequently used to indicate a software crash or deadlock in embedded systems. DEADBEEF was originally used to mark newly allocated areas of memory that had not yet been initialized -- when scanning a memory dump, it is easy to see the DEADBEEF. It is used by IBM RS/6000 systems, Mac OS on 32-bit PowerPC processors and the Commodore Amiga as a magic debug value. On Sun Microsystems' Solaris, it marks freed kernel memory. On OpenVMS running on Alpha processors, DEAD_BEEF can be seen by pressing CTRL-T. The DEC Alpha SRM console has a background process that traps memory errors, identified by PS as "BeefEater waiting on 0xdeadbeef".[16] 0xDEADC0DE ("dead code") is used as a marker in OpenWrt firmware to signify the beginning of the to-be created jffs2 filesystem at the end of the static firmware. 0xDEADDEAD ("dead dead") is the bug check (STOP) code displayed when invoking a Blue Screen of Death either by telling the kernel via the attached debugger, or by using a special keystroke combination.[17] This is usually seen by driver developers, as it is used to get a memory dump on Windows NT based systems. An alternative to 0xDEADDEAD is the bug check code 0x000000E2,[18] as they are both called MANUALLY_INITIATED_CRASH as seen on the Microsoft Developer Network. 0xDEADD00D ("dead dude") is used by Android in the Dalvik virtual machine to indicate a VM abort. 0xDEADFA11 ("dead fall") is used by Apple in iOS crash reports, when the user force quits an application.[1] 0xDEAD10CC ("dead lock") is used by Apple in iOS crash reports, when application holds on to a system resource while running in the background.[1] 0xDEFEC8ED ("defecated") is the magic number for OpenSolaris core dumps.[19] 0xE011CFD0 is used as magic number for Microsoft Office files. In little endian this reads D0CF11E0, "docfile0".[20] face:b00c ("facebook") used in the IPv6 address of www.v6.facebook.com 0xFACEFEED ("face feed") is used by Alpha servers running Windows NT. The Alpha Hardware Abstraction Layer (HAL) generates this error when it encounters a hardware failure.[21] 0xFEE1DEAD ("feel dead") is used as a magic number in the Linux reboot system call.[22] 0xDEADBAAD ("dead bad") is used by the Android libc abort() function when native heap corruption is detected. deadbeef-dead-beef-dead-beef00000075("dead beef") is the GUID assigned to hung/dead virtual machines in Citrix Xenserver
第二个表格:
..FACADE "Facade", Used by a number of RTOSes 1BADB002 "Bad booze", Multiboot header magic number A5A5A5A5 Used in embedded development because the alternating bit pattern (1010 0101) creates an easily recognized pattern on oscilloscopes and logic analyzers. A5 Used in FreeBSD's PHK malloc(3) for debugging when /etc/malloc.conf is symlinked to "-J" to initialize all newly allocated memory as this value is not a NULL pointer or ASCII NUL character. ABABABAB Used by Microsoft's HeapAlloc() to mark "no man's land" guard bytes after allocated heap memory ABADBABE "A bad babe", Used by Apple as the "Boot Zero Block" magic number ABADCAFE "A bad cafe", Used to initialize all unallocated memory (Mungwall, AmigaOS). 0DEFACED "Defaced", Required by Microsoft's Hyper-V hypervisor to be used by Linux guests as their "guest signature", after changing from original 0xB16B00B5 BAADF00D "Bad food", Used by Microsoft's LocalAlloc(LMEM_FIXED) to mark uninitialized allocated heap memory BADBADBADBAD "Bad bad bad bad", Burroughs large systems "uninitialized" memory (48-bit words) BADC0FFEE0DDF00D "Bad coffee odd food", Used on IBM RS/6000 64-bit systems to indicate uninitialized CPU registers BADDCAFE "Bad cafe", On Sun Microsystems' Solaris, marks uninitialised kernel memory (KMEM_UNINITIALIZED_PATTERN) BBADBEEF "Bad beef", Used in WebKit[clarification needed] BEEFCACE "Beef cake", Used by Microsoft .NET as a magic number in resource files CAFED00D "Cafe dude", Used by Java for their pack200 compression CAFEFEED "Cafe feed", Used by Sun Microsystems' Solaris debugging kernel to mark kmemfree() memory CCCCCCCC Used by Microsoft's C++ debugging runtime library and many DOS environments to mark uninitialized stack memory. CC resembles the opcode of the INT 3 debug breakpoint interrupt on x86 processors. CDCDCDCD Used by Microsoft's C++ debugging runtime library to mark uninitialized heap memory D15EA5E "Disease", Used as a flag to indicate regular boot on the Nintendo GameCube and Wii consoles DDDDDDDD Used by MicroQuill's SmartHeap and Microsoft's C++ debugging heap to mark freed heap memory DEADBABE "Dead babe", Used at the start of Silicon Graphics' IRIX arena files DEADBEEF "Dead beef", Famously used on IBM systems such as the RS/6000, also used in the original Mac OS operating systems, OPENSTEP Enterprise, and the Commodore Amiga. On Sun Microsystems' Solaris, marks freed kernel memory (KMEM_FREE_PATTERN) DEADC0DE "Dead code", Used as a marker in OpenWRT firmware to signify the beginning of the to-be created jffs2 file system at the end of the static firmware DEADF00D "Dead food", Used by Mungwall on the Commodore Amiga to mark allocated but uninitialized memory [13] DEFEC8ED "Defecated", Used for OpenSolaris core dumps EBEBEBEB From MicroQuill's SmartHeap FADEDEAD "Fade dead", Comes at the end to identify every AppleScript script FDFDFDFD Used by Microsoft's C++ debugging heap to mark "no man's land" guard bytes before and after allocated heap memory FEE1DEAD "Feel dead", Used by Linux reboot() syscall FEEDFACE "Feed face", Seen in PowerPC Mach-O binaries on Apple Inc.'s Mac OS X platform. On Sun Microsystems' Solaris, marks the red zone (KMEM_REDZONE_PATTERN) FEEEFEEE "Fee fee", Used by Microsoft's HeapFree() to mark freed heap memory
可能显示效果不是很好,请点击链接去WikiPedia查看:
Hexspeak Notable magic numbers
Magic_number_(programming) Magic_debug_values
===============华===丽===的===分===割===线===============
在人人网上看到一个同学上传的照片,看到我就笑了。
2^32 = 4294967296
奇葩的,是这位程序员使用unsigned int存储数据,然后除以100,得到想要的浮点数(两个零头):
1 2 3 4 5 6 7 8 9 10 11 12 13 | #include <stdio.h> #include <string.h> #include <stdlib.h> int main(int argc, char **argv) { char szBuffer[16]; unsigned int nTmp = 0; sprintf(szBuffer, "0x%X", -20); nTmp = strtoul(szBuffer, NULL, 16); printf("%u\n", nTmp); return 0; } |
===============华===丽===的===分===割===线===============
展昭:“包大人,你额头的月牙是怎么弄的?”
包大人:“天生的。”
展昭:“揭得下来吗?”
包大人:“天生的。揭不下来。”
展昭:“如果揭下来呢?”
包大人:“揭下来……就是见证奇迹的时刻……”
另外,Google宣布Google Reader大限将至,不知道大家有没有好的替代品,以前用过鲜果,发现不支持本博客的代码高亮输出,另外网易有道阅读器也一样,代码乱得一团糟。最好是Web阅读器,到哪都可以看。
本博客很少转载他人文章,如未特别标明,均为原创,转载请注明出处:
本文出自程序人生 >> 调试器也有MagicNumer——从一个奇葩的错误说起
作者:代码疯子