语义冲突传递指针指向字节数组的const指针

时间:2012-09-07 15:14:32

标签: c++ const-cast

我想从下面用prototy定义的OpenSSL库中调用此函数:

X509 *d2i_X509(X509 **px, const unsigned char **in, int len);

第二个参数in定义为const unsigned char **,因为:

  • d2i_X509不会修改*in指向的缓冲区中的数据
  • *in将增加从缓冲区解析的数据量。

现在这个原型是一个问题,因为据我所知,函数无法通过以下方式调用,据我所知,API是调用它的常规方法(删除错误管理代码以简化操作) ):

unsigned char buffer[2048];
unsigned char * end = buffer;
unsigned char * p = buffer;

end += read(fd, p, 2048);
certlen1 = parseint(&p);
X509 * cert1 = d2i_x509(NULL, &p, certlen1);
certlen2 = parseint(&p);
X509 * cert2 = d2i_x509(NULL, &p, certlen2);

如果我尝试编译上面的代码,它会说:

error: invalid conversion from 'unsigned char**' to 'const unsigned char**'

我理解消息的基本原理(例如解释here),但在这种特殊情况下,这个基本原理并不适用于函数状态,因为它只会增加*in的值。 ,永远不要指定一个无关的指针。

我无法将p的类型更改为const unsigned char *,因为上面的代码实际上是简化的,指针隐藏在执行读取和写入的一些抽象IO对象后面。与之前的IO对象的好处在于保持对称读取和编写代码在一起,可以使用两个单独的指针在我的IO对象中进行读取和写入,但这样做的总体好处是非常小(如果不是负面的)并添加很多语法噪音。

表示,在一个外部无关的API调用所强制的IO对象中进行了那种深层内部更改

解决方案可能是执行强制转换甚至根本不使用返回的指针值(因为我有size参数),但它也感觉不对。似乎d2i_X509的原型不包含足够的信息,或者在这种情况下编译器的const检查规则过于严格。

如何从C ++调用这样的API?现在我只会使用一个演员,因为我觉得它是较小的邪恶,但还有更好的方法吗?

1 个答案:

答案 0 :(得分:1)

首先,此代码中的+=没有多大意义:

p += read(fd, p, 2048);

您正在修改p指向刚刚过去您刚读取的数据,因此d2i_x509将会读取垃圾邮件。

我会这样做:

unsigned char buffer[2048];
int n = read(fd, buffer, 2048);
if (n < 0) ..error..;
const unsigned char * p = buffer;
X509 * cert1 = d2i_x509(NULL, &p, certlen1);
X509 * cert2 = d2i_x509(NULL, &p, certlen2);
int used = p - buffer;  // # of bytes actually parsed by the two calls

以后可以直接对buffer进行任何更改。

修改

好的,然后替换它:

X509 * cert1 = d2i_x509(NULL, &p, certlen1);

用这个:

{
  const unsigned char *q = p;
  X509 * cert1 = d2i_x509(NULL, &q, certlen1);
  p += q - p;
}