【发布时间】:2012-12-15 20:44:33
【问题描述】:
我一直在深入研究 Linux 和 C,我很好奇函数是如何存储在内存中的。 我有以下功能:
void test(){
printf( "test\n" );
}
足够简单。当我在具有此功能的可执行文件上运行 objdump 时,我得到以下信息:
08048464 <test>:
8048464: 55 push %ebp
8048465: 89 e5 mov %esp,%ebp
8048467: 83 ec 18 sub $0x18,%esp
804846a: b8 20 86 04 08 mov $0x8048620,%eax
804846f: 89 04 24 mov %eax,(%esp)
8048472: e8 11 ff ff ff call 8048388 <printf@plt>
8048477: c9 leave
8048478: c3 ret
这一切看起来都不错。 有趣的是当我运行以下代码时:
int main( void ) {
char data[20];
int i;
memset( data, 0, sizeof( data ) );
memcpy( data, test, 20 * sizeof( char ) );
for( i = 0; i < 20; ++i ) {
printf( "%x\n", data[i] );
}
return 0;
}
我得到以下信息(不正确):
55
ffffff89
ffffffe5
ffffff83
ffffffec
18
ffffffc7
4
24
10
ffffff86
4
8
ffffffe8
22
ffffffff
ffffffff
ffffffff
ffffffc9
ffffffc3
如果我选择忽略 memset(data, 0, sizeof(data));行,则最右边的字节是正确的,但其中一些仍然具有前导 1。
有没有人解释一下原因
A) 使用 memset 清除我的数组会导致函数表示不正确(编辑:不准确),并且
解决方案:是由于使用了 memset(data, 0, sizeof(data)),而不是 memset(data, 0, 20 * sizeof(unsigned char))。内存没有完全设置,因为它只查看指针的大小而不是整个数组的大小。
B) 这个字节存储在内存中是什么?整数?字符?我不太明白这里发生了什么。 (澄清:我将使用什么类型的指针来遍历内存中的此类数据?)
解决方案:我很笨。我忘记了 unsigned 关键字,这就是整个问题的来源:(
任何帮助将不胜感激 - 我在四处搜索时找不到任何东西。
尼尔
PS:我的直接想法是,这是由于 x86 的指令不以字节或半字节边界结束。但这没有多大意义,也不应该造成任何问题。
感谢 Will 指出我的 char 类型错误。它应该是无符号字符。不过,我仍然对如何访问单个字节感到好奇。
【问题讨论】:
标签: c linux function memory objdump