我有一个基本的疑问。 我有一个使用共享库的进程。如果我在库中分配一些内存 然后它是哪个地址空间。 (图书馆或流程) 在我看来,它是进程地址空间,因为一旦附加了库,它就全部在进程地址空间中。
如果我错了,请纠正我。
由于 Arpit
答案 0 :(得分:5)
库没有自己的地址空间。它映射到某个进程并在其中执行。所以你是对的。共享库的内存分配是在使用它的进程内完成的。
答案 1 :(得分:2)
听起来你可能会在地址空间和堆之间感到困惑。
进程只有一个地址空间,进程内的所有内容(主可执行文件,任何共享库和任何静态库)都共享单个地址空间。
虽然单个地址空间中可能存在多个堆,但glibc的实现方式只有一个标准堆(标准堆,我指的是通过malloc / free访问的堆)。这与Windows不同,其中可执行文件和dll可能各自都有自己的堆(尽管再次共享一个地址空间)。
答案 2 :(得分:1)
库本身没有内存空间,因为它不是正在运行的进程。共享库的概念是拥有代码指令的共享副本,但不包含该代码使用或生成的任何数据。
因此,例如,如果您的库旨在管理动态分配的结构:
object.h
struct object_struct {
char *name;
int foo;
int bar;
};
typedef struct object_struct * object_t; /* opaque pointer */
object_t new_object (char *name, int foo, int bar);
void delete_object(object_t);
int dump_object(object_t);
object.c
#include <stdio.h>
#include "object.h"
object_t new_object (char *_name, int foo, int bar) {
object_t _p = malloc(sizeof(object_t);
if (!_p)
return NULL;
_p->foo = foo; _p->bar = bar;
_p->name = strdup(_name);
return _p;
}
void delete_object(object_t p) {
if(_p->name)
free(_p->name);
if(_p)
free(_p);
}
int dump_object(object_t p) {
FILE * fp = fopen(p->name, "w");
if ( !fp )
return -1;
fprintf(fp, "foo: %d\nbar: %d\n", p->foo, p->bar);
fclose(fp);
return 0;
}
你有两个程序consumer1.c和consumer2.c使用该库对象,如下所示:
consumer1.c
#include "object.h"
int main() {
object_t o = new_object("consumer1.txt", 1, 2);
dump_object(o);
delete_object(o);
return 0;
}
consumer2.c
#include "object.h"
int main() {
object_t o = new_object("consumer2.txt", 1, 2);
dump_object(o);
delete_object(o);
return 0;
}
对于所有意图和目的,对象库的这两个程序将不具有任何公共数据或公共内存或公共空间。
P.S。:假设gcc和gnu make,这里有一个make文件供你全部测试。
生成文件
default: libobject.a consumer1 consumer2
.c.o: %.c
$(CC) -c -o $@ $<
libobject.a: object.o
$(AR) r $@ object.o
object.o: object.c object.h
consumer1 consumer2: $@.o libobject.a
$(CC) -o $@ $@.o -L. -lobject
P.P.S:这只是一本指南!我还没有在这里测试过所有的代码,希望这一切都可以顺利运行,但是,如果我做了语法错误,请妥善解决。
答案 3 :(得分:0)
共享库可以与许多进程链接,并在这些进程的上下文中运行。
假设您有一个共享库来发送http请求。浏览器进程和桌面应用程序都可以与该库链接,但进程上下文将使它们能够发送独立请求,尽管两者都加载了相同的库。
因此,无论在何处编写内存(进程或库),进程上下文都会确定内存的分配。