$ cat x.c
#include<stdio.h>
void main()
{
int *x,q;
int *y,w;
x=0x7fffffffe2bc;
y=0x7fffffffe3bc;
*x=3;*y=4;
printf("%d",(*x)/(*y));
}
在运行时产生分段错误(没有编译时警告/错误)
编辑 :(警告:谢谢@KeithThompson)
x.c:在函数'main'中:
x.c:6:警告:赋值使用整数而不使用强制转换
[ 8626.812415] x[3198]: segfault at 7fffffffe2bc ip 000000000040054c sp 00007fff66a1dd70 error 6 in x[400000+1000]
但是当我将x,y分配给q时,w为此
$ cat x.c
#include<stdio.h>
void main()
{
int *x,q;
int *y,w;
x=&q;
y=&w;
*x=3;*y=4;
printf("%d",(*x)/(*y));
}
获取输出0
。我甚至从gdb检查了q和w的地址,我得到0x7fffffffe2bc
的q
为什么我不能强制指针指向特定位置并为其提供要存储的值?
修改 地址0x7fffffffe2bc不是未分配。 这是来自gdb的q的地址
Breakpoint 1, main () at x.c:10
10 *x=3;*y=4;
(gdb) p q
$1 = 0
(gdb) p &q
$2 = (int *) 0x7fffffffe2bc
(gdb)
我理解这种编写代码的方式很糟糕,如果不是错误的话。我只是写了这个,看看地址的明确分配是否有效。我永远不会浪费时间明确地分配地址。做这样的事情实际上听起来非常迟钝:)
$ gdb -q ./a.out
Reading symbols from /home/eknath/needed2/a.out...done.
(gdb) r
Starting program: /home/eknath/needed2/a.out
0
Program exited normally.
(gdb) q
答案 0 :(得分:3)
因为您没有为数据分配内存,只需指针。你最好捣乱内存,最坏的情况是打一个未分配的内存段。无法知道要使用的地址 - 每次运行应用程序时,它们都可能不同。
如果要动态分配变量(即在您自己的控制下),请使用malloc:
int *x = (int*) malloc( sizeof(int) );
*x = 2;
// when done, free the memory
free( (void*) x );
答案 1 :(得分:1)
此代码:
int *x,q;
...
x=0x7fffffffe2bc;
无效。这是一种约束违规,这意味着需要任何符合标准的编译器来发出诊断消息。您说“编译此程序时没有警告/错误”,这意味着您使用的是旧编译器,或者您正在使用新的编译器。
x
的类型为int*
; 0x7fffffffe2bc
是某种整数类型。没有从整数类型到int*
的隐式转换(除了0
的特殊情况,空指针常量)。
你可以合法地写下这样的内容:
x = (int*)0x7fffffffe2bc;
但这是一个非常糟糕的主意。它使您的程序非常不可移植。它可能(或可能不)恰好在您的特定系统上工作。
无论你想要完成什么,这都不是实现目标的方法。你无法知道0x7fffffffe2bc
(当转换为int*
时)是一个有效的地址 - 即使它是一个有效的地址,它也不会是你在一个偶数运行程序时环境略有不同。
修改强>:
我尝试通过打印q
和w
的地址然后将地址硬连接到代码中来尝试在我的系统上复制程序(地址完全不同)。每次执行程序时实际地址都会更改,即使我不更改或重新编译程序本身也是如此。我认为有些系统会故意这样做,作为安全功能。 (我看到dmckee的回答已经提到了这一点。)
打印变量的地址,或者使用gdb查看变量,只会告诉您该变量在该特定程序执行中的地址。一旦程序运行完毕,该信息无用,即使您重新运行相同的程序而没有任何更改。
如果您想要q
的地址,那么获取该地址的方式为&q
。
答案 2 :(得分:0)
这种事情完全取决于实现/环境(并且通常是未定义的行为),但它确实在嵌入式系统和其他环境中占有一席之地,在这些环境中,您与绝对一切之间没有操作系统层。< / p>
许多完整服务操作系统随机化堆栈和/或堆的起始地址,以便使攻击更加困难,如果是这种情况,您将无法执行任何可靠的技巧。
答案 3 :(得分:0)
问题既不在代码中,也不在编译器/链接器中。这两个程序都像你期望的那样工作。只有一个很大的但: 仅仅因为你可以指向内存并不意味着你将被MMU 允许访问(假设是操作系统)。
让我澄清一下: 通常你只能访问你“拥有”的内存(堆栈/堆)。在这两种情况下,对x和y的赋值都是有效的。棘手的部分是当你访问内存(读或写)时。在第一种情况下,您为指针指定了一些随机值,因此该位置不太可能在程序的范围内(==无法触及此位置)。虽然,在第二种情况下,您正在访问可能拥有的变量的内存位置。
为什么会这样?因为对变量进行优化,q和w将被优化掉,因为它们从未被使用过。
请记住:从不引用未初始化的变量,除非您喜欢问题
答案 4 :(得分:0)
void myFunction(char *addr)
{
#ifdef UMEM_DEBUG
if (addr == (char *) 0xdeadbeefdeadbeef)
{
return;
}
#endif
...
}
这是有效的,并且是您想要这样做的一个很好的例子。只需根据addr的类型获得正确的类型转换