这里举个例子查看内存,

环境为:vs 2017 测试为strcpy【因为测试老api,需要在 预处理中 添加 _CRT_SECURE_NO_WARNINGS 】

测试问题:内存溢出

源码:

#include <iostream>
#include <stdlib.h>
#include <string>

#define MY_STR "hello"
#define YOUR_STR "boom"
#define NUMBERS "0123456789"
#define MAX_LENGTH 12
using namespace std;

void changed_str(char *szArry,const char *Data)
{
cout << "before copy data " << endl;
strcpy(szArry, Data);
cout << "after copy data " << endl;
}
int main()
{

char Arry[MAX_LENGTH] = { 0 };

/*
changed_str(Arry, MY_STR);

cout << Arry << endl;

memset(Arry,0,strlen(Arry));

changed_str(Arry, YOUR_STR);

cout << Arry << endl;

*/
strcpy(Arry, NUMBERS);

strcpy(Arry+3, Arry);
for (int i=0;i<sizeof(Arry);i++)
  cout << Arry[i] << endl;

system("pause");
return 0;
}

现在是给足长度的数组,然后进行拷贝,成功拷贝字符串,并没有发现问题。

C++  浅析调试,内存重叠查看-LMLPHP

现对比,长度不够,然后拷贝字符串:

内存溢出如果没有踩内存是没有蹦的

C++  浅析调试,内存重叠查看-LMLPHP

接下来是查看内存重叠strcpy

C++  浅析调试,内存重叠查看-LMLPHP

为了方便做对比先列下strcpy原理【非常暴力毫无安全可言,旧版本的,现在新版本的估计已经替换了】:

甚至没有做校验assert,直接拿来测试会死循环

void strcpy( char *strDest, char *strSrc )   

 {   

  while( (*strDest++ = * strSrc++) != ‘\0’ );   

 }

strcpy(a+3, a); 内存重叠

开始拷贝:

a[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}  //注意这里a的长度是12

{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}

直到第六次拷贝:

a[7] = a[4] // a[4]值为 1

a[] = {0, 1, 2, 0, 1, 2, 3, 7, 8, 9}

{0, 1, 2, 0, 1, 2, 3, 7, 8, 9}

a[9] = a[6] // a[6]值为 3

a[] = {0, 1, 2, 0, 1, 2, 3, 1, 2, 3}

{0, 1, 2, 0, 1, 2, 3, 7, 8, 9}

a[10] = a[7] // a[7]值为 7

a[] = {0, 1, 2, 0, 1, 2, 3, 1, 2, 3, 7}

{0, 1, 2, 0, 1, 2, 3, 7, 8, 9}

a[11] = a[8] // a[8]值为 2 为什么这里数组a[8]刷新了? 同步了上面

a[] = {0, 1, 2, 0, 1, 2, 3, 1, 2, 3, 7}

{0, 1, 2, 0, 1, 2, 3, 7, 2, 9}

a[12]  = a[9] // a[9] 值为 3

a[] = {0, 1, 2, 0, 1, 2, 3, 1, 2, 3, 7, 2, 3}

{0, 1, 2, 0, 1, 2, 3, 1, 2, 3, 7, 2, 3}

a[13]  = a[10] // a[9] 值为 7

a[] = {0, 1, 2, 0, 1, 2, 3, 1, 2, 3, 7, 2, 3, 7}

{0, 1, 2, 0, 1, 2, 3, 1, 2, 3, 7, 2, 3, 7}//这里长度应该跟上面一样的

同一个数组踩内存这里不会崩溃,也不会出现其他问题,还可以正常输出,如果是不同的变量,可能会引起程序崩溃,

所以建议使用strcpy_s安全版本拷贝,或者使用strcpy的时候自己增加外部校验判断参数合法性。

此处只做总结分享。

05-11 22:52