2

我正在开发一个执行加密任务的应用程序。它使用 OpenSSL 来完成这些任务,并且界面类似于libcurl. 如果不熟悉,它看起来像这样:

conf_func(handle, ENUM_OPTION, value);

从而在实例上设置由ENUM_OPTIONto表示的选项。通读它的文档说它会复制所有值(除非另有说明),因此你释放了你分配的东西,它释放了它分配的东西。valuehandlelibcurl

我认为这对我的应用程序来说可能是一个好主意。虽然它会提高内存需求,但它确实使使用更容易。但是,我在这里遇到了一个问题。假设这段代码:

X509 *cert = X509_new();
X509 *cert_copy = malloc(sizeof(X509));
memcpy(cert_copy, cert, sizeof(X509));

这当然会产生一个问题:它只是一个浅拷贝,释放会有问题。搜索后,我决定 OpenSSL 本身不提供深拷贝,它甚至可能是不可取的(内存使用)。

因此,我采取了不同的方法:我不复制,而只是存储我传递的指针:

X509 *cert = X509_new();
X509 *cert_copy = cert;
X509_free(cert_copy);

这将减少内存占用并简化开发。另一方面,这将提高文档需求和特殊使用意识:您分配,但我免费为您服务。

所以我想也许我应该始终如一地提供这种行为?但是后来我遇到了字符串问题:

char *s = "Some text";
char *s_copy = s;
free(s_copy);

这不会像s常量一样工作,并且没有在堆上分配。

所以这是我的两难境地:我将不得不复制字符串,但不能复制 OpenSSL 结构。我该如何干净地解决这个问题?我是否记录它并依赖用户正确使用我的界面?或者有什么完全明显的我失踪了吗?

注意:我释放意味着我在使用结束时有一个通用的销毁功能。它只会检查指针是否存在NULL,否则会释放。

4

1 回答 1

2

正如您所发现的,除非该库公开了用于执行复制的 API,否则没有正确的方法可以“深度复制”属于库的不透明数据对象。你有几个选择:

  1. 不要让调用者传入属于库的对象,而只需传递创建所述对象所需的信息/参数。然后,您的代码可以自由调用库来创建对象。

  2. 设计你的接口契约,使你的代码成为传递给它的对象的“所有者”,并且调用者在传递它们后不能再使用它们。

  3. 设计您的接口契约,以便在调用者和您的代码之间明确共享所有权。例如,这可能意味着调用者在您的代码仍然具有对它的引用时不会修改或释放该对象,但是在您的代码完成使用它之后,调用者可以再次自由使用它并负责释放它。

哪种方法最好取决于您的应用程序的要求。除非内存或性能是关键问题,否则我会选择以简单性取胜的设计。

于 2013-04-12T19:00:43.503 回答