在Objective-C的遗留版本中,objc_class结构实现如下:
struct objc_class {
Class isa;
Class super_class;
const char *name;
long version;
long info;
long instance_size;
struct objc_ivar_list *ivars;
struct objc_method_list **methodLists;
struct objc_cache *cache;
struct objc_protocol_list *protocols;
};
Run Code Online (Sandbox Code Playgroud)
因此,表示对象的结构存储指向对象类的指针,指向对象超类的指针,对象的类名,对象的版本,信息和实例大小,对象的实例变量列表,对象的方法列表,对象的缓存和对象的协议列表.在表示对象的结构中存在这些字段是非常容易理解的,因为它们中的每一个都存储有关该对象的信息.
但是,相同的struct objc_class的Objective-C 2.0实现是这样的:
struct objc_class {
Class isa;
};
Run Code Online (Sandbox Code Playgroud)
因此,在这个版本的objc_class中,struct中只有一个字段:指向对象类结构的指针.
那么,我的问题是,对象的其他信息是如何存储在Objective-C 2.0中的,因为结构中只有一个表示对象的字段?
根据该Block_private.h文件,只要在Objective-c文件中声明块,就会在目标文件中创建以下结构来表示它:
struct Block_descriptor {
unsigned long int reserved;
unsigned long int size;
void (*copy)(void *dst, void *src);
void (*dispose)(void *);
};
struct Block_layout {
void *isa;
int flags;
int reserved;
void (*invoke)(void *, ...);
struct Block_descriptor *descriptor;
/* Imported variables. */
};
Run Code Online (Sandbox Code Playgroud)
但是,当我生成一个程序集文件时,with clang -S ...,from
int(^squared)(int) = ^(int i) {
return i*i;
};
Run Code Online (Sandbox Code Playgroud)
我得到代表块的以下代码段:
.type .L.str210,@object # @.str210
.L.str210:
.asciz "i12@?0i8"
.size .L.str210, 9
.type __block_descriptor_tmp,@object # @__block_descriptor_tmp
.section .rodata,"a",@progbits
.align 16
__block_descriptor_tmp:
.quad 0 # …Run Code Online (Sandbox Code Playgroud) 我的问题是当前版本的Foundation(或Objective-C运行时库,因为它似乎在那里)如何实现NSObject派生对象的保留计数?正如我在NSObject.mm上看到的那样,retain count在NSObject界面体中没有调用ivar .相反,似乎有一种表或映射包含每个对象的引用计数器.但是,如果保留计数真的与地图做,是不是retain和release行动与这种实现(因为太贵了,在这种情况下,有必要锁定和解锁互斥,查找地图,找到合适的对象,除了事实那么,在多线程环境中,一次只能保留/释放一个对象)?
我没有找到相关的新对象的分配时,保留计数器设置为1东西,无论是在_objc_rootAllocWithZone在NSObject.mm(这似乎是被调用的函数[NSObject alloc])也不_class_createInstanceFromZone在objc-runtime-new.mm(即后来被称为_objc_rootAllocWithZone.
仅查看Objective-C运行时库,当消息发送到不响应它的对象时,运行时系统为接收者提供了另一个处理消息的机会.因此,接收者的forward::方法(如果实现的话)被调用.但是,看看NSObject.mm,NSObject似乎没有实现forward::.
那么,如何NSObject的forwardInvocation:方法被调用,因为需要转发时运行系统调用的唯一的事情是forward::?Foundation是否使用objc_setForwardHandler(runtime.h)设置一个新的处理程序,forwardInvocation:只要发送到NSObject对象的消息需要转发,它就会调用?
forwarding objective-c objective-c-runtime nsobject nsinvocation
在OSX的开发环境中,存在框架的概念.框架是一种包含头,共享库和其他有用东西的包.可以将框架传递给编译器,以便编译器在搜索路径中包含其标头,并使用其共享库将程序与它们链接.
因此,例如,如果-framework FrameworkName在OSX上传递给gcc或clang,编译器会查找/System/Library/Frameworks目录以查找FrameworkName.framework目录.如果找到,编译器将包含其标头并将程序与其共享库链接.
那么,这个超级有用的功能是否适用于Linux?gcc或clang是否认可-frameworkLinux上的选项?当我在Linux上键入此选项时,编译器似乎无法识别它,但这可能是因为我需要在它之前设置框架目录路径.是否有任何特殊技巧可以使它在Linux上运行?或者这在这个平台上绝对不可能?
看一下Mac OS X 10.8版本的Objective-C运行时库源代码,我注意到它有一个NSObject.mm文件.顾名思义,它有NSObject类实现,以及内置自动释放池和保留计数实现.
但是,Mountain Lion之前的ObjC运行时库的版本没有实现NSObject该类(它们没有NSObject.mm文件,正如您可以在Mac OS X 10.7的Objective-C运行时库源代码中看到的那样,例如).
那么这是否真的意味着NSObject该类现在是Objective-C运行时库的一部分而不是作为Foundation库组件?如果是,为什么?是否要-framework Foundation在子类化时避免与整个Foundation库(with )链接NSObject?
我正在尝试使用clone()创建一个新线程.使用以下代码(...):
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#define _SCHED_H 1
#define __USE_GNU 1
#include <bits/sched.h>
#define STACK_SIZE 4096
int func(void *arg) {
printf("Inside func.\n");
sleep(1);
printf("Terminating func...\n");
return 0;
}
int main() {
printf("This process pid: %u\n", getpid());
char status_file[] = "/proc/self/status";
void *child_stack = malloc(STACK_SIZE);
int thread_pid;
printf("Creating new thread...\n");
thread_pid = clone(&func, child_stack+STACK_SIZE, CLONE_SIGHAND|CLONE_FS|CLONE_VM|CLONE_FILES, NULL);
printf("Done! Thread pid: %d\n", thread_pid);
FILE *fp = fopen(status_file, "rb");
printf("Looking into %s...\n", status_file);
while(1) {
char ch = fgetc(fp);
if(feof(fp)) …Run Code Online (Sandbox Code Playgroud) 考虑到我有一个CFMutableArray使用以下函数调用创建的对象:
CFMutableArrayRef marray = CFArrayCreateMutable(kCFAllocatorDefault, 1, &kCFTypeArrayCallBacks);
Run Code Online (Sandbox Code Playgroud)
根据CFMutableArray文档,的第二个参数CFArrayCreateMutable,这被称为capacity是"可以由新的数组被包含的值的最大数量.该阵列开始空并能长到这个数值(它可以具有更小) .传递0指定最大容量不受限制.该值不得为负数."
但是,如果我向我的新数组附加多个值,它会不断增长.我的意思是,如果新数组已经有一个值并且我附加了一个新CFArrayAppendValue(marray, newValue)值,则存储该值并且数组计数变为2,超过其容量.
那么,为什么会这样呢?我误解了文档吗?
在objective-c运行时,类由以下结构表示:
typedef struct class_t {
struct class_t *isa; // Points to the class' meta class
struct class_t *super; // Points to the class' super class
Cache cache;
IMP *vtable;
union {
class_ro_t *rodata;
class_rw_t *rwdata;
};
} class_t;
Run Code Online (Sandbox Code Playgroud)
当一个MyClass类是一个根类而不是一个元类时,它的超级成员是一个NULL指针(这是可以理解的,因为它是一个根类,因此它没有超类).但是,如果我们得到同MyClass一根类的isa成员(指向MyClass'meta class),并且我们得到该isa成员的超级成员,它不是NULL指针,而是指向MyClass(不是元类)的指针.非元根类的元类的超类不应该是NULL指针(作为非元根类的超类)吗?既然不是,那它应该是什么?
我问这个是因为,事实上的方式,如果methodX是MyClass根类的实例方法(不是类方法),语句[MyClass methodX]
会调用methodX(它实际上是),不应该发生什么(再次,因为methodX是实例方法,而不是类方法,所以它不应该响应[MyClass methodX]语句).
在我的Linux程序中,我需要一个接收地址的函数,addr并检查callq放置的指令是否addr正在调用func从共享库加载的特定函数.我的意思是,我需要检查自己是否有这样的事情callq func@PLT在addr.
那么,在Linux上,如何func从callq func@PLT指令中获取函数的真实地址?
objective-c ×6
cocoa ×3
nsobject ×3
linux ×2
assembly ×1
clang ×1
class ×1
compilation ×1
forwarding ×1
foundation ×1
frameworks ×1
function ×1
gcc ×1
ios ×1
nsarray ×1
nsinvocation ×1
process ×1
retaincount ×1