以下代码抛出EXC_BAD_ACCESS错误(特别是一般保护错误错误),我想知道为什么你不能错位一个块指针并执行它。
#include <stdio.h>
int main(int argc, const char * argv[])
{
void (^blocky)() = ^{
printf("Hello!\n");
printf("Hello Again!\n");
};
blocky = *(&blocky+1);
blocky = *(&blocky-1);
blocky();
return 0;
}
但是以下工作:
#include <stdio.h>
int main(int argc, const char * argv[])
{
void (^blocky)() = ^{
printf("Hello!\n");
printf("Hello Again!\n");
};
blocky = *(&blocky+1-1);
blocky();
return 0;
}
编辑(回答未对齐的代码块):
如果将块视为结构,则可以发现指向内存中可执行代码的值与块的起始位置相差16个字节,长度为8个字节。
您可以有效地将此值指向内存中的另一个位置。一般来说,这会崩溃。
假设您知道内存中的另一段可执行代码的具体地址,您可以将其指向那里。
为什么这很有用: 事实并非如此。永远不要这样做。真。从不。
答案 0 :(得分:2)
第一个例子中的指针操作是错误的。试试这个:
#include <stdio.h>
typedef void (^blocky_t)();
int main(int argc, const char * argv[])
{
blocky_t blocky = ^{
printf("Hello!\n");
printf("Hello Again!\n");
};
printf("blocky=%p\n", blocky);
blocky = (blocky_t)((char *)blocky + 1);
printf("blocky=%p\n", blocky);
blocky = (blocky_t)((char *)blocky - 1);
printf("blocky=%p\n", blocky);
blocky();
return 0;
}
$ clang -o blocky blocky.c
$ ./blocky
blocky=0x10574d040
blocky=0x10574d041
blocky=0x10574d040
Hello!
Hello Again!
当我运行你的代码时,我得到了:
blocky=0x10e0ba040
blocky=0x7fff51b46c10
blocky=0x1300000000
其中:
__TEXT
段内。答案 1 :(得分:1)
你的问题确实与积木无关。你只是以一种没有意义的方式操纵指向局部变量的指针。
首先,您永远不会使用分配给blocky
的块指针。您获取堆栈上的局部变量blocky
的地址,然后向其中添加一个单词,并取消引用它。根据体系结构,堆栈可能会向下增长,这意味着它位于堆栈帧上的所有变量之前,并且可能是当前堆栈帧的返回地址。或者它可能是别的东西。然后,将此值分配给blocky
。
然后,再次获取堆栈中局部变量blocky
的地址,然后从中减去一个单词,并取消引用它。同样,假设堆栈增长,这可能会超过当前堆栈帧的末尾,这将是垃圾。然后,您将此值分配给blocky
。然后尝试将其作为指向块的指针运行。当然这不起作用。
在第二段代码中,再次获取堆栈中局部变量blocky
的地址,然后从中添加和减去一个单词(当然这是指向局部变量的指针{{ 1}}再次),并取消引用它(这是blocky
的值),并将其分配给blocky
。此操作无效。