对内存字节的理解
Posted strive-sun
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了对内存字节的理解相关的知识,希望对你有一定的参考价值。
为了加强自己的记忆,我决定用文字记录下来。
这是源代码,主要是输出环境变量,具体可以参考CreateEnvironmentBlock函数
1 #include <Windows.h> 2 #include <UserEnv.h> 3 #include <assert.h> 4 #include <stdio.h> 5 #pragma comment(lib, "userenv.lib") 6 #pragma warning(disable : 4996) 7 8 int main() 9 10 HANDLE hToken = NULL; 11 BOOL ok = OpenProcessToken(GetCurrentProcess(), TOKEN_READ, &hToken); 12 /*assert(ok); 13 14 wchar_t* penv = NULL; 15 ok = CreateEnvironmentBlock((void**)&penv, hToken, TRUE); 16 assert(ok); 17 18 while (*penv) 19 printf("%ls\\n", penv); 20 penv += wcslen(penv) + 1; 21 */ 22 wchar_t* wnext = NULL; 23 LPVOID pEnvironment = NULL; 24 ok = CreateEnvironmentBlock(&pEnvironment, 25 hToken, 26 FALSE); 27 if (!ok) 28 29 // handle error 30 31 32 wchar_t* wtemp = (wchar_t*)pEnvironment; 33 34 do 35 36 wnext = wtemp + wcslen(wtemp) + 1; 37 int m = wcslen(wtemp); 38 if (*(wnext+1) == L‘\\0‘) // Crashes here 39 40 break; 41 42 else 43 44 wtemp = wnext; 45 printf("%ls\\n", wtemp); 46 47 while (1); 48 49 return 0; 50
注释部分可以不用看,主要注意 if (*(wnext+1) == L‘\\0‘) 这行
下面两张图分别是控制台输出结果和内存字节
从第二张图可以看到控制台打印到windir=C:\\WINDOWS之后,下面就会打印空行,再然后就会进入break,这是为什么呢?
我们已知宽字节占两个字节,所以一次会跳过2个点,包括r. s. 等等,我们在执行wnext = wtemp + wcslen(wtemp)+1这行代码时,实际上是相当于wtemp地址往后移动 wcslen(wtemp)+1个地址位,而我们在往后移动 wcslen(wtemp)时,我们其实到达了C.:.\\.W.I.N.D.O.W.S.的S.的位置,再+1就相当于到C.:.\\.W.I.N.D.O.W.S...的位置,+1的原因是为了跳过\\0的字符串结束位,到这边是将(..)这个空的赋给wnext,而在执行到下一行代码if (*(wnext+1) == L‘\\0‘),地址相当于又往后面移动一个宽字节,也就是C.:.\\.W.I.N.D.O.W.S.....,然后我们判断这之后的(\\.),把它与L‘\\0‘进行比较,发现它不为0,然后代码跳到else上面。
重点来了,wtemp = wnext;这行代码其实是把C.:.\\.W.I.N.D.O.W.S...后面的(..)这个空的内存字节赋给wtemp,打印为空,并不是C.:.\\.W.I.N.D.O.W.S.....,因为C.:.\\.W.I.N.D.O.W.S.....这个只是后面用于比较的,然后到wnext = wtemp + wcslen(wtemp) + 1这行代码,之前wtemp为空,所以wcslen(wtemp) = 0, 再+1,往后面移一个地址,就到了C.:.\\.W.I.N.D.O.W.S.....上的最后一个点的位置,接着执行到下一行代码if (*(wnext+1) == L‘\\0‘),地址上再+1,相当于跳过了(\\.),我们需要比较(\\.)后面的值,也就是(..),可以看到是空,然后与L‘\\0‘相同,到了break,跳出while循环,程序结束。
这段代码的正确输出要把if (*(wnext+1) == L‘\\0‘)中的+1去除,这样避免指针指向未知的内存区域。
可能写的有点乱,仅供参考吧,我也是第一次接触,很多术语都没怎么明白。
以上是关于对内存字节的理解的主要内容,如果未能解决你的问题,请参考以下文章