假设:
int a = 1;
int *p = &a;
int b = -1;
*++p = 2;
是否存在阻止b从-1写入2的事情,如果在明显不太可能的事件中,两个a和b在内存中彼此相邻写入?
答案 0 :(得分:9)
C如何保护指针内存?
它没有。
是否存在阻止b从-1写入2的任何内容 如果在不太可能的情况下,两个a和b都写在每个旁边 其他在记忆中?
没有
这两个变量在内存中彼此相邻"根本不可能。
C给你力量引起很多问题,你不小心。
答案 1 :(得分:5)
假设你的最后一行是*++p = 2
,不,没有什么可以保护指针内存。修改指向它(最初)指向的对象之外的指针然后取消引用它会导致未定义的行为,并且可能发生任何事情。
在编写的代码中,*(a++)
将解引用运算符应用于非指针类型,这是一种约束违规,因此需要生成编译时诊断而不是编译...
答案 2 :(得分:1)
*++p = 2;
C表示它无效,并且该语句调用未定义的行为。如果编译器检测到错误,则允许编译器停止转换但是没有要求C检测到这种错误(这实际上很难检测到)。
答案 3 :(得分:1)
不,没有什么能阻止你这样做。指针算法定义明确,这意味着您可以将指针向任何方向移动以指向另一个位置。但是使用此设置,您无法确定实际修改的是哪个内存。因为在编译期间,优化器可以将您的变量移动到不同的位置。
与您的情况一样,假设一切都是精简和直接的。您声明变量的顺序是a,p和b。假设(a和b)得到x和p得到y字节的内存,具体取决于你的机器架构和操作系统。
你的记忆应该是这样的:
-ArgumentList
这意味着,++ p将评估为p + sizeof(p)。如果'p'指向'a'的开始,则这意味着将其递增(y)字节将在'y'存储区域中假定'p'(假设y> = x)或否则在'x'中。所以你实际上是修改p的内存而不是b。
P.S:C提供的功能最好留给有经验的C程序员。答案 4 :(得分:0)
如果您将a
,b
个变量放入单独的页面(例如,使用mmap
),则可以使用mprotect
调用来设置PROT_READ
保护在包含变量b
。
答案 5 :(得分:0)
在您的示例中,b
可能会被覆盖。
对我来说,使用GDB
我得到两个变量在内存中相互放置:
(gdb) x &a
0xffffcb80: 0x00000001
(gdb) x &b
0xffffcb84: 0x00000002
然而,这不能保证。
由于递增int *
会将地址增加sizeof(int)
,我们会到达下一个int
,对我来说已经包含b
。
代码......
int a = 1;
int *p = &a;
int b = -1;
*++p = 2;
printf("b: %i\n", b);
因此打印:
b: 2
C
对自己的进程内存没有内存保护。你可以编写这样的代码,但是你可能会遇到麻烦:只要你增加int *
undefined behavior
,就会导致{{1}},因为你保留了变量的实际大小。你不应该对这样的变量位置做出假设,因为它可能不成立,所以任何事情都可能发生,你不会喜欢它带来的不稳定性。