c++字符串拷贝和内存问题?
来源:网络整理 网络用户发布,如有版权联系网管删除 2018-09-04
参考答案如下:
首先来看这段代码:
char *p = "abcd";char a[] = "abcd";p[2] = 'h'; // 1a[2] = 'h'; // 2
| | +-----+ | 'a' | 0xA0 <-+ +-----+ | | 'b' | 0xA1 | +-----+ | | 'c' | 0xA2 | +-----+ | | 'd' | 0xA3 | +-----+ | | 0 | 0xA4 | +-----+ | | | | . . | . . | . . | | | | +-----+ | | 'a' | 0xC0 | ` +-----+ | | | 'b' | 0xC1 | | +-----+ | | | 'c' | 0xC2 | | 变量 a +-----+ | | | 'd' | 0xC3 | | +-----+ | | | 0 | 0xC4 | / +-----+ | |0xA0 | 0xC5 --+ | 变量 p +-----+ | |
- p[2] 即 0xA0 + 2 = 0xA2,即试图去修改所谓「常量区」的东西。
- a[2] 即 0xC0 + 2 = 0xC2,即试图区修改栈上的内容。
而后的代码:
char *p = new char(7);p = "abcdef";p[2] = 'h';delete[] p;
- 申请一个字节的内存,将内容赋值为 0x07。将 p 的内容置为申请到的内存地址。
- 将 p 的内容置为「常量区」字符串常量 "abcdef" 的地址。
- 把地址为 p 的内容 + 2 处的 char 赋值为 'h'。
- 释放地址为 p 的内容的内存块。
「诡异」的其实是你的代码。看出来了吗?
- 你只申请了 1 个字节的内存,而不是 7 个
- 得到申请到的内存后,没有使用就直接丢掉了(把 p 赋值成了「常量区」的地址)
- 核心错误依旧在于修改「常量区」的内容
- 试图释放常量区的内存
- 没有释放申请到的内存
p.s. 这真不是一个 C++ 问题,这是一个 C 语言问题。
参考答案如下:
char* p = "abcd";// line 1
这line 1,确实将p指向了常量区。
char p [] = "abcd";//line 2
这line 2,才是你所说的,在栈里开辟了数组空间。
因此,题主的第一个问题,“既然*p不能改是因为指向了常量区”,这句话是没错的。
而题主的第二个问题,先不说new 的时候char(7)和char[7]的问题,
char * p = new char[7];// line 3
line 3,开辟了一个长度为7的字符数组,然后p作为一个指针,指向了这个数组的第0位。目前为止是没有错误的。然后
p = "abcd";//line 4
line 4的效果等同于line 1,执行之后p指向了常量区。而你刚才new出来的数组呢?呵呵,其实已经永远找不回来了!!!也就是说,内存泄露了。此刻,你再
delete []p;//line 5
至于line 5,很遗憾,此刻你要析构常量区?妥妥的报错!我不明白题主的程序为什么没有崩溃,至少我这里是崩溃了的。
环境VS,WIN7
----------------------------------------------我是分割线你看不粗来么---------------------------------
好,现在我们跑到Ubuntu上去试一试gcc怎么说
针对
char * p = "abcdabcdabcd";//line 6
char p[] = "abcdabcdabcd";//line 7
上述line6和line7这两种情况,我们分别
gcc -m32 -O0 main.c
之后,来看一看它们汇编的区别:
80483c1: c7 45 f8 b0 84 04 08 movl $0x80484b0,-0x8(%ebp)
这是第一种情况,很显然,把某个地址赋给了程序栈,好,那我们具体来看一看这个$0x80484b0是什么鬼。
80484b0: 61
80484b1: 62 63 64
80484b4: 61
80484b5: 62 63 64
80484b8: 61
80484b9: 62 63 64
很明显了,这不就是abcd这一串东西的ASCII么(当然,是16进制,0x61=97='a')
于是得到结论,line6这种情况,是栈里有个指针,然后指针指向了常量区。
好了,回过头来看line7这种情况:
8048421: c7 44 24 0e 61 62 63 movl $0x64636261,0xe(%esp)
8048428: 64
8048429: c7 44 24 12 61 62 63 movl $0x64636261,0x12(%esp)
8048430: 64
8048431: c7 44 24 16 61 62 63 movl $0x64636261,0x16(%esp)
8048438: 64
真的在栈里把abcd这群东西写进去了好么!
查看评论 回复