当前时区为 UTC + 8 小时



发表新帖 回复这个主题  [ 13 篇帖子 ] 
作者 内容
1 楼 
 文章标题 : 这段C++代码内存是怎么分配的?
帖子发表于 : 2008-11-10 15:37 
头像

注册: 2007-10-06 20:49
帖子: 98
地址: 中国,天津(Tianjin China)
送出感谢: 0 次
接收感谢: 0 次
简化的代码:在程序段内先后声明下面这些变量,就是他们在内存中是怎么存放的弄不懂!
int i = 5;
float f = 2.00;
char str1[] = "Hello";
char str2[10] = "HeyDude";
char *str3 = str1;
const char *str4 = "World";

希望大侠能耐心地详细地解释一下他们在内存中是如何排列的。
我就弄不明白str1的地址怎么和在它上一行定义的float f的地址相差的字节数怎么是 0xbfc33444 - 0xbfc33432
谢谢 :em01

/*******************************
/*******************************/

原代码如下:
#include <iostream>
#include <stdlib.h>
#include <stdio.h>
#include <string>

using namespace std;

int main(){
int i = 5;
float f = 2.00;
cout << "i = " << i << "; " << "address i = " << &i << endl;
cout << "f = " << f << "; " << "address f = " << &f << endl;
cout << endl;

char str1[] = "Hello"; //!note: the type of str1 is char[6], not char*
cout << "str1 = " << str1 << "; "
<< "address str1 = " << &str1 << "; "
<< *str1 << endl;
cout << "----elements in str1:" << endl;
for(int i = 0; i < 6; i++)
cout << " str[" << i << "] = " << str1[i] << "; " << endl;
cout << "change 'H' in \"Hello\" with 'W'" << endl;
str1[0] = 'W'; //!note:OK, cos' "Hello\0" which pointed by str1 is not const,
// besides it's stored in STACK
cout << "size of str1 = " << sizeof str1 << endl; //note!: sizeof str1 is the same as "Hello\0"
cout << endl;

char str2[10] = "HeyDude";
cout << "size of str2 is " << sizeof str2 << endl;
cout << endl;

char *str3 = str1;
cout << "str3 = " << str3 << "; "
<< "address str3 = " << &str3 << "; "
<< "the value str3 point to is: " << *str3 << endl;
cout << endl;

const char *str4 = "World"; //!note:the type of str3 is char*
//!error: str4[0] = 'P'; //!note:the string--"World\0" pointed by str3 is stored
// is stored in read-only location
cout << "str4 = " << str4 << "; "
<< "address str4 = " << &str4 << "; "
<< "the value str4 point to is: " << *str4 << endl;
cout << "size of str4 is " << sizeof(str4) << endl; //the size of pointer
return 0;
}

输出如下:
/**************************************
**************************************/
i = 5; address i = 0xbfc33448
f = 2; address f = 0xbfc33444

str1 = Hello; address str1 = 0xbfc33432; H
----elements in str1:
str[0] = H;
str[1] = e;
str[2] = l;
str[3] = l;
str[4] = o;
str[5] =
change 'H' in "Hello" with 'W'
size of str1 = 6

size of str2 is 10

str3 = Wello; address str3 = 0xbfc3343c; the value str3 point to is: W

str4 = World; address str4 = 0xbfc33438; the value str4 point to is: W
size of str4 is 4


页首
 用户资料  
 
2 楼 
 文章标题 : Re: 这段C++代码内存是怎么分配的?
帖子发表于 : 2008-11-10 21:36 
头像

注册: 2008-06-18 22:02
帖子: 186
送出感谢: 0 次
接收感谢: 1
the memory layout depends on your compiler implement. so when you come across some puzzle, refer to the compiler document


页首
 用户资料  
 
3 楼 
 文章标题 : Re: 这段C++代码内存是怎么分配的?
帖子发表于 : 2008-11-10 22:12 
头像

注册: 2008-10-06 23:03
帖子: 69
地址: 青岛
送出感谢: 0 次
接收感谢: 0 次
那个内存的分配不一定是连续的
这个最好的解释就是 《数据结构》


_________________
把你的脸迎向阳光,那就不会有阴影
-----------------------------------------------


页首
 用户资料  
 
4 楼 
 文章标题 : Re: 这段C++代码内存是怎么分配的?
帖子发表于 : 2008-11-11 10:09 
头像

注册: 2007-10-06 20:49
帖子: 98
地址: 中国,天津(Tianjin China)
送出感谢: 0 次
接收感谢: 0 次
wenstream 写道:
the memory layout depends on your compiler implement. so when you come across some puzzle, refer to the compiler document

Thanks, I'm using gcc4.2.4
I'll look into the docs of gcc, but where can I get it? :em01


页首
 用户资料  
 
5 楼 
 文章标题 : Re: 这段C++代码内存是怎么分配的?
帖子发表于 : 2008-11-11 10:11 
头像

注册: 2007-10-06 20:49
帖子: 98
地址: 中国,天津(Tianjin China)
送出感谢: 0 次
接收感谢: 0 次
smallqiu@126.com 写道:
那个内存的分配不一定是连续的
这个最好的解释就是 《数据结构》

能说的在详细一点儿吗?谢谢啦 呵呵


页首
 用户资料  
 
6 楼 
 文章标题 : Re: 这段C++代码内存是怎么分配的?
帖子发表于 : 2008-11-11 22:31 
头像

注册: 2008-09-20 4:47
帖子: 46
地址: Tampere
送出感谢: 0 次
接收感谢: 0 次
简单的说,就是所有变量(指针本身也是)的空间都是在栈内分配的,malloc出来的东西在堆上分配的内存,至于常量则看编译器了


_________________
匿名安全通信
http://xizhizhu.blogspot.com/
xizhi.zhu@tut.fi


页首
 用户资料  
 
7 楼 
 文章标题 : Re: 这段C++代码内存是怎么分配的?
帖子发表于 : 2008-11-14 21:16 
头像

注册: 2006-07-02 11:16
帖子: 12522
地址: 廣州
送出感谢: 0 次
接收感谢: 8
万恶的对齐?


_________________
^_^ ~~~
要理解递归,首先要理解递归。

地球人都知道,理论上,理论跟实际是没有差别的,但实际上,理论跟实际的差别是相当大滴。


页首
 用户资料  
 
8 楼 
 文章标题 : Re: 这段C++代码内存是怎么分配的?
帖子发表于 : 2008-11-15 10:36 
头像

注册: 2007-10-06 20:49
帖子: 98
地址: 中国,天津(Tianjin China)
送出感谢: 0 次
接收感谢: 0 次
BigSnake.NET 写道:
万恶的对齐?

字符数组是看作一个整体还是只看作是几个字符--来决定对其方式


页首
 用户资料  
 
9 楼 
 文章标题 : Re: 这段C++代码内存是怎么分配的?
帖子发表于 : 2008-11-15 10:38 
头像

注册: 2007-10-06 20:49
帖子: 98
地址: 中国,天津(Tianjin China)
送出感谢: 0 次
接收感谢: 0 次
xizhi.zhu 写道:
简单的说,就是所有变量(指针本身也是)的空间都是在栈内分配的,malloc出来的东西在堆上分配的内存,至于常量则看编译器了

我就弄不明白str1的地址怎么和在它上一行定义的float f的地址相差的字节数怎么是 0xbfc33444 - 0xbfc33432
希望能解答


页首
 用户资料  
 
10 楼 
 文章标题 : Re: 这段C++代码内存是怎么分配的?
帖子发表于 : 2008-11-18 16:54 
头像

注册: 2008-06-18 22:02
帖子: 186
送出感谢: 0 次
接收感谢: 1
一般来说,编写C/C++程序并不需要知悉编译器分配内存的细节,如zizhi.zhu所言,了解堆栈(stack),堆(heap)这两者的概念与区别就足够了,除非你是编译器实现者,或者开发嵌入式系统(由于资源相对有限,对内存的使用有苛刻的要求)等其他情况,另当别论,不过如果有兴趣,深入了解多些也好的
在c/c++编译器的设计上,有一个内存数据对齐(也称字节对齐)的原则,用于优化CPU的存取性能,可能会浪费一些内存。lz可以了解一下相关的内容,这里就不详述了

内存的具体布局,基于编译器的实现各异。就字节对齐这一点上,有的编译器优化得好一些,有比较好的算法调整变量间的内存分配布局,有的编译器则相反,浪费的内存会多一些。具体这个编译器的实现就只能参照编译器文档了。
哪里可以弄到这种文档呢,gcc的官网应该有吧。不过我只找到了使用手册,而没有找到实现的描述,又不想掉进“源代码的海”里,如果lz找到实现原则或细节描述的文档,请共享一下。

不过细看上面的程序,lz的问题,我看可以作一个粗浅的解释
引用:
str1的地址和在它上一行定义的float f的地址相差的字节数怎么是 0xbfc33444 - 0xbfc33432

从"上一行"这个词来看,lz貌似认为,给出一组相邻定义的变量,编译器肯定会在分配内存时也会严格按定义的次序分配相邻的内存区,事实上,这并非绝对(很多情况都不严格按定义的次序分配内存,不说太远,只考虑上面所说的为字节对齐作的布局优化,分配内存就要进行变量内存区的次序调整),不过一般来说相同类型的变量是相邻存放的
lz的程序我简化如下:
代码:
#include <iostream>
using namespace std;

int main(){
   int i = 5;
   float f = 2.00;
   cout << " i:   address = " << &i << " size "<< sizeof i << endl;
   cout << " f:   address = " << &f << " size "<< sizeof f << endl;

   char str1[] = "Hello";
   cout << "str1: address = " << &str1 << " size "<< sizeof str1 << endl;

   char str2[10] = "HeyDude";
   cout << "str2: address = " << &str2 << " size " << sizeof str2 << endl;

   char *str3 = str1;
   cout << "str3: address = " << &str3 << " size "<< sizeof str3 << endl;

   const char *str4 = "World";
   cout << "str4: address = " << &str4 << " size " << sizeof str4 << endl;
   
   return 0;
}

我用的是 g++ (GCC) 4.2.4 (Ubuntu 4.2.4-1ubuntu3)编译,与lz所用的应该是同一个版本的编译器吧,运行情况如下:
代码:
stream@stream:~/program/c.cpp/cpp/workspace$ ./memlayout
 i:   address = 0xbffd0ca0 size 4
 f:   address = 0xbffd0c9c size 4
str1: address = 0xbffd0c8e size 6
str2: address = 0xbffd0ca6 size 10
str3: address = 0xbffd0c98 size 4
str4: address = 0xbffd0c94 size 4
stream@stream:~/program/c.cpp/cpp/workspace$

我们知道堆栈分配有 "从高位到低位" 和 "从低位到高位" 两种方式,从str2与i的地址来看,这里应该是后者。综而观之,这段代码中的变量在内存中的布局应该是这样的:
附件:
memlayout.jpg
memlayout.jpg [ 33.21 KiB | 被浏览 573 次 ]


图中方框中变量后的数字表示此变量所占用的字节大小,如str1占用6个字节,标为6。方框间隔线下方为对应的内存地址值。(图中特别标出变量 i 后面有2个字节,不知道作何用处呢?)
如果单从变量f与str1的地址上看,0xbffd0c9c与0xbffd0c8e中间相差14个字节,无论f与str1都并非14个字节,这段内存是怎么分配的当然就比较令人费解,但是从整个程序的变量内存分配来看,这个内存分配的布局是不难理解的。

上面lz结出的代码与运行结果地址值可以作类似的分析。


页首
 用户资料  
 
11 楼 
 文章标题 : Re: 这段C++代码内存是怎么分配的?
帖子发表于 : 2008-11-18 23:29 
头像

注册: 2007-10-06 20:49
帖子: 98
地址: 中国,天津(Tianjin China)
送出感谢: 0 次
接收感谢: 0 次
wenstream 写道:
一般来说,编写C/C++程序并不需要知悉编译器分配内存的细节,如zizhi.zhu所言,了解堆栈(stack),堆(heap)这两者的概念与区别就足够了,除非你是编译器实现者,或者开发嵌入式系统(由于资源相对有限,对内存的使用有苛刻的要求)等其他情况,另当别论,不过如果有兴趣,深入了解多些也好的
在c/c++编译器的设计上,有一个内存数据对齐(也称字节对齐)的原则,用于优化CPU的存取性能,可能会浪费一些内存。lz可以了解一下相关的内容,这里就不详述了

内存的具体布局,基于编译器的实现各异。就字节对齐这一点上,有的编译器优化得好一些,有比较好的算法调整变量间的内存分配布局,有的编译器则相反,浪费的内存会多一些。具体这个编译器的实现就只能参照编译器文档了。
哪里可以弄到这种文档呢,gcc的官网应该有吧。不过我只找到了使用手册,而没有找到实现的描述,又不想掉进“源代码的海”里,如果lz找到实现原则或细节描述的文档,请共享一下。

不过细看上面的程序,lz的问题,我看可以作一个粗浅的解释
引用:
str1的地址和在它上一行定义的float f的地址相差的字节数怎么是 0xbfc33444 - 0xbfc33432

从"上一行"这个词来看,lz貌似认为,给出一组相邻定义的变量,编译器肯定会在分配内存时也会严格按定义的次序分配相邻的内存区,事实上,这并非绝对(很多情况都不严格按定义的次序分配内存,不说太远,只考虑上面所说的为字节对齐作的布局优化,分配内存就要进行变量内存区的次序调整),不过一般来说相同类型的变量是相邻存放的
lz的程序我简化如下:
代码:
#include <iostream>
using namespace std;

int main(){
   int i = 5;
   float f = 2.00;
   cout << " i:   address = " << &i << " size "<< sizeof i << endl;
   cout << " f:   address = " << &f << " size "<< sizeof f << endl;

   char str1[] = "Hello";
   cout << "str1: address = " << &str1 << " size "<< sizeof str1 << endl;

   char str2[10] = "HeyDude";
   cout << "str2: address = " << &str2 << " size " << sizeof str2 << endl;

   char *str3 = str1;
   cout << "str3: address = " << &str3 << " size "<< sizeof str3 << endl;

   const char *str4 = "World";
   cout << "str4: address = " << &str4 << " size " << sizeof str4 << endl;
   
   return 0;
}

我用的是 g++ (GCC) 4.2.4 (Ubuntu 4.2.4-1ubuntu3)编译,与lz所用的应该是同一个版本的编译器吧,运行情况如下:
代码:
stream@stream:~/program/c.cpp/cpp/workspace$ ./memlayout
 i:   address = 0xbffd0ca0 size 4
 f:   address = 0xbffd0c9c size 4
str1: address = 0xbffd0c8e size 6
str2: address = 0xbffd0ca6 size 10
str3: address = 0xbffd0c98 size 4
str4: address = 0xbffd0c94 size 4
stream@stream:~/program/c.cpp/cpp/workspace$

我们知道堆栈分配有 "从高位到低位" 和 "从低位到高位" 两种方式,从str2与i的地址来看,这里应该是后者。综而观之,这段代码中的变量在内存中的布局应该是这样的:
附件:
memlayout.jpg

图中方框中变量后的数字表示此变量所占用的字节大小,如str1占用6个字节,标为6。方框间隔线下方为对应的内存地址值。(图中特别标出变量 i 后面有2个字节,不知道作何用处呢?)
如果单从变量f与str1的地址上看,0xbffd0c9c与0xbffd0c8e中间相差14个字节,无论f与str1都并非14个字节,这段内存是怎么分配的当然就比较令人费解,但是从整个程序的变量内存分配来看,这个内存分配的布局是不难理解的。

上面lz结出的代码与运行结果地址值可以作类似的分析。


谢谢wenstream了,这些变量在内存里面排放的位置应该是在编译是就确定的吧?没有顺序排放应该是编译器的原因?
我再找找...... 还有那个2 很诡异


页首
 用户资料  
 
12 楼 
 文章标题 : Re: 这段C++代码内存是怎么分配的?
帖子发表于 : 2008-11-19 0:42 
头像

注册: 2007-10-14 0:50
帖子: 306
地址: GUCAS
送出感谢: 0 次
接收感谢: 1
用objdump查看一下反汇编的结果,不就什么都清楚了!这与编译器有关的。


_________________
OS: Debian GNU/Linux
Version: lenny
Kernel: 2.6.36
Xorg: 1.4.2
CPU: Intel(R) Core(TM)2 Duo CPU E8400 @ 3.00GHz
HD: 320G SATA
Memory: 2G DDRIII
Graphics:Mobility Radeon HD 3450


页首
 用户资料  
 
13 楼 
 文章标题 : Re: 这段C++代码内存是怎么分配的?
帖子发表于 : 2008-11-20 14:29 
头像

注册: 2008-05-03 23:05
帖子: 383
送出感谢: 0 次
接收感谢: 0 次
:em11 wenstream


页首
 用户资料  
 
显示帖子 :  排序  
发表新帖 回复这个主题  [ 13 篇帖子 ] 

当前时区为 UTC + 8 小时


在线用户

正在浏览此版面的用户:没有注册用户 和 1 位游客


不能 在这个版面发表主题
不能 在这个版面回复主题
不能 在这个版面编辑帖子
不能 在这个版面删除帖子
不能 在这个版面提交附件

前往 :  
本站点为公益性站点,用于推广开源自由软件,由 DiaHosting VPSBudgetVM VPS 提供服务。
我们认为:软件应可免费取得,软件工具在各种语言环境下皆可使用,且不会有任何功能上的差异;
人们应有定制和修改软件的自由,且方式不受限制,只要他们自认为合适。

Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group
简体中文语系由 王笑宇 翻译