我知道,当使用支持异常的语言(例如C++)时,必须向运行时环境提供附加信息,以描述在处理异常期间必须解除的调用帧.此信息包含在目标文件的特殊部分中,例如.eh_frame和.eh_frame_hdr.
但是,这些部分中存储了哪种数据结构?我的意思是,可以使用任何C结构来读取它们吗?难道他们有什么做的.cfi语句(如.cfi_startproc,.cfi_endproc,.cfi_offset,.cfi_def_cfa_offset,.cfi_personality和.cfi_lsda)在GNU汇编代码?如果他们这样做,这些条款中的每一个都会在这些部分中产生什么?该.eh_frame_hdr部分与该部分有什么关系.eh_frame?
我希望尽可能多地使用C结构进行解释.谢谢.
是否有任何库有一些功能允许人们通过它监视外部进程的事件pid_t?我的意思是,监视外部进程是否已退出,或者是否已创建一个或多个子进程(with fork),或者它是否已成为另一个可执行映像(通过函数exec或posix_spawn函数系列调用)或是否已将Unix信号传递给它.
编辑
我需要的东西不会干扰正在监控的程序的执行.因此,我不应该使用ptrace,因为它会在发出一些信号时停止正在监视的进程,并且只要发生这种情况就必须恢复进程.
如果我得到以下Objective-C源文件:
// test.m
#import <objc/Object.h>
@interface MySuperClass: Object {
}
-(void) myMessage1;
@end
@implementation MySuperClass
-(void) myMessage1 {
}
@end
@interface MyClass: MySuperClass {
}
-(void) myMessage2;
@end
@implementation MyClass
-(void) myMessage2 {
}
@end
int main() {
return 0;
}
Run Code Online (Sandbox Code Playgroud)
并尝试从中生成一个程序集文件clang -fobjc-nonfragile-abi -fnext-runtime -S test.m,我得到以下汇编代码:
.file "test.m"
.text
.align 16, 0x90
.type _2D__5B_MySuperClass_20_myMessage1_5D_,@function
_2D__5B_MySuperClass_20_myMessage1_5D_: # @"\01-[MySuperClass myMessage1]"
.Ltmp0:
.cfi_startproc
# BB#0:
movq %rdi, -8(%rsp)
movq %rsi, -16(%rsp)
ret
.Ltmp1:
.size _2D__5B_MySuperClass_20_myMessage1_5D_, .Ltmp1-_2D__5B_MySuperClass_20_myMessage1_5D_
.Ltmp2:
.cfi_endproc
.Leh_func_end0:
.align 16, …Run Code Online (Sandbox Code Playgroud) 查看Objective-C运行时库源代码,特别是在objc-runtime-new.mm,我看到了一些函数甚至注释引用了懒惰和非惰性类.似乎没有一个类+load的方法被称为懒类,但我不知道这一点,并最有可能是不正确的.在Google上搜索后,我没有在Objective-C上找到任何有关惰性类的内容.
那么,什么是Objective-C中的惰性类?Obj-C有这个功能吗?它是否与+load类实现中存在方法有关?在上面链接的文件中,运行时系统调用一个被调用的函数_getObjc2NonlazyClassList,以便从图像中获取非惰性类的列表.为什么没有_getObjc2LazyClassList功能呢?
我正在搞乱Objective-C运行时,尝试编译Objective-c代码而不将其链接起来libobjc,并且我对程序有一些分段错误问题,所以我从中生成了一个汇编文件.我认为没有必要显示整个程序集文件.在我的main功能的某些方面,我有以下一行(顺便说一句,这是我得到seg错误之后的行):
callq *l_objc_msgSend_fixup_alloc
Run Code Online (Sandbox Code Playgroud)
这是以下定义l_objc_msgSend_fixup_alloc:
.hidden l_objc_msgSend_fixup_alloc # @"\01l_objc_msgSend_fixup_alloc"
.type l_objc_msgSend_fixup_alloc,@object
.section "__DATA, __objc_msgrefs, coalesced","aw",@progbits
.weak l_objc_msgSend_fixup_alloc
.align 16
l_objc_msgSend_fixup_alloc:
.quad objc_msgSend_fixup
.quad L_OBJC_METH_VAR_NAME_
.size l_objc_msgSend_fixup_alloc, 16
Run Code Online (Sandbox Code Playgroud)
我重新实现objc_msgSend_fixup了一个函数(id objc_msgSend_fixup(id self, SEL op, ...))返回nil(只是为了看看会发生什么),但是这个函数甚至没有被调用(程序在调用之前崩溃).
所以,我的问题是,callq *l_objc_msgSend_fixup_alloc应该做什么以及objc_msgSend_fixup(之后l_objc_msgSend_fixup_alloc:)应该是什么(一个函数或一个对象)?
编辑
为了更好地解释,我没有将我的源文件与objc库链接.我想要做的是实现libray的一些部分,只是为了看它是如何工作的.这是我所做的一种方法:
#include <stdio.h>
#include <objc/runtime.h>
@interface MyClass {
}
+(id) alloc;
@end
@implementation MyClass
+(id) alloc {
// alloc the object
return nil;
}
@end
id objc_msgSend_fixup(id …Run Code Online (Sandbox Code Playgroud) 考虑以下C代码,它创建100,000个4KB大小的页面,然后释放99,999页,最后释放最后一页:
#include <stdio.h>
#include <stdlib.h>
#define NUM_PAGES 100000
int main() {
void *pages[NUM_PAGES];
int i;
for(i=0; i<NUM_PAGES; i++) {
pages[i] = malloc(4096);
}
printf("%d pages allocated.\n", NUM_PAGES);
getchar();
for(i=0; i<NUM_PAGES-1; i++) {
free(pages[i]);
}
printf("%d pages freed.\n", NUM_PAGES-1);
getchar();
free(pages[NUM_PAGES-1]);
printf("Last page freed.\n");
getchar();
return 0;
}
Run Code Online (Sandbox Code Playgroud)
如果你编译它,运行它并监视进程的内存使用情况,你可以看到内存使用量在第一个之前达到大约400MB getchar(当内存分配为100,000页时),即使在99,999页之后仍然保持相同分配(在第二个之后getchar),最后,当最后一页被解除分配时,它下降到1MB.
所以,我的问题是为什么会发生这种情况?为什么只有在释放所有页面时,整个内存才会返回到操作系统?是否有任何页面大小或任何页面对齐,以防止这种情况发生?我的意思是,当只有一个页面被释放时,是否有任何页面大小或对齐使得任何malloced页面完全返回到操作系统?
假设我正在编写一个C++库,它必须导出一个变量,一个数据结构,例如,ExpData.因此,链接到我的libray的程序可以访问此变量(有一个公共头定义它extern void *ExpData[]).
但是,此数据结构在内部是C++类的vtable.例如,该类的名称InternalType.因此,在查看生成的汇编代码后,我发现InternalTypevtable被导出为_ZTV12InternalType.
然后,我需要一种方法来使我的库导出变量ExpData用相同的地址解析_ZTV12InternalType,这样,当外部程序读取我的库的ExpData变量时,它实际上是读取InternalType的vtable.
只是为了澄清,InternalTypevtable汇编代码是:
.type _ZTV12InternalType,@object # @_ZTV12InternalType
.section .data.rel.ro._ZTV12InternalType,"aGw",@progbits,_ZTV12InternalType,comdat
.weak _ZTV12InternalType
.align 16
_ZTV12InternalType:
.quad 0
.quad _ZTI12InternalType
.quad _ZN12InternalType8vMethodXEi
.size _ZTV12InternalType, 24
Run Code Online (Sandbox Code Playgroud)
所以,我需要一种方法来实现这一点(或其他具有相同效果的东西):
.type ExpData,@object
.globl ExpData
.type _ZTV12InternalType,@object
.section .data.rel.ro._ZTV12InternalType,"aGw",@progbits,_ZTV12InternalType,comdat
.weak _ZTV12InternalType
.align 16
_ZTV12InternalType:
ExpData:
.quad 0
.quad _ZTI12InternalType
.quad _ZN12InternalType8vMethodXEi
.size _ZTV12InternalType, 24
Run Code Online (Sandbox Code Playgroud)
在C++方面有可能吗?
PS:我知道我不应该依赖于依赖于实现的细节,比如名称修改和C++类内部数据,但只考虑我的库将在非常特定的环境中运行.
编辑
我可以通过传递--defsym ExpData=_ZTV12InternalType给链接器来解决我的问题.但是,我不想将实现细节附加到外部资源.假设我决定将类'vtable映射为一个名为的C结构InternalTypeVTable.所以,我可以宣布ExpData …
由于Objective-C是C超集,因此在编译.m文件期间,所有Objective-C特定语句都将转换为C语句(我猜是由预处理器).因此,例如,消息表达式[receiver method]转换为消息传递函数的调用objc_msgSend(receiver, selector).
我的问题是:如果我有这样的类定义:
@interface ClassA {
int var1;
float var2;
id var3;
}
-(void) method1;
-(int) method2: (int) num1;
@end
@implementation ClassA
-(void) method1 {
// Implementation of the method
}
-(int) method2: (int) num1 {
// Implementation of the method
}
@end
Run Code Online (Sandbox Code Playgroud)
它是由编译器转换成的(在Objective-C的2.0版本中)?它是转换成电话上一样的功能objc_allocateClassPair(),class_addIvar(),class_addMethod()并且objc_registerClassPair(),为了分别创建类,添加它的实例变量,增加它的方法和注册类,(所以该类结构在运行系统中实际定义,而不是被加载为从可执行文件中获取结构)?
我想构建一个没有Foundation的简单Objective C程序.我试过了:
#include <stdio.h>
@interface Foo{
char * bar;
}
-(void)hello;
@end
@implementation Foo
-(void)hello {
printf("Hello world!");
}
@end
int main(){
Foo * foo = [Foo alloc];
return 0;
}
Run Code Online (Sandbox Code Playgroud)
然后它告诉我Foo may not respond to +alloc和autorelease called without pool...
如何在不使用allocFoundation的情况下初始化对象?
我正在64位Linux系统上开发一个应用程序.正如我所看到的,我的应用程序正在吃太多脏堆内存.谈论堆内存,"脏"是什么意思?是什么让它出现以及可以采取哪些措施来防止它出现?
编辑
我最好解释一下我的应用程序执行的操作.
我的应用程序运行在两个线程中:第一个线程将作业发送到队列,然后在另一个线程中执行.因此,第一个线程分配要排队的页面,第二个线程将它们出列,执行它们的作业并释放它们.所有这些操作都以线程安全的方式执行.
所以我对这个东西进行了测试,使它排队100000000个作业并执行它们.在特定时刻之前,内存使用量会增加.然后,当排队过程结束并且仅剩余出队时,内存使用莫名其妙地不会减少.最后,当所有作业都出列并执行时,释放所有内存.因此,内存泄漏似乎在出列过程中发生,因为当它完成所有内存被释放时,我发现它的代码没有任何错误.
我知道如果我在这里发布我的代码会更好,但它太大了.但是,根据我的补充,是否有人猜测可能导致这种情况的原因是什么?