1

好吧,这个让我有点困惑。

以下函数将字符串编码为 base 64

void Base64Enc(const unsigned char *src, int srclen, unsigned char *dest)
{
    static const unsigned char enc[] =
    "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";

    unsigned char *cp;
    int i;

    cp = dest;
    for(i = 0; i < srclen; i += 3) 
    {
      *(cp++) = enc[((src[i + 0] >> 2))];
      *(cp++) = enc[((src[i + 0] << 4) & 0x30)
                    | ((src[i + 1] >> 4) & 0x0f)];
      *(cp++) = enc[((src[i + 1] << 2) & 0x3c)
                    | ((src[i + 2] >> 6) & 0x03)];
      *(cp++) = enc[((src[i + 2]     ) & 0x3f)];
    }
    *cp = '\0';
    while (i-- > srclen)
      *(--cp) = '=';

    return;
}

现在,在调用 Base64Enc() 的函数上,我有:

unsigned char *B64Encoded;

这是我在 base 64 编码函数中传递给 unsigned char *dest 的参数。我尝试了从 mallocs 到 NULL 到其他初始化的不同初始化。无论我做什么,我总是会得到一个异常,如果我不初始化它,那么编译器(VS2005 C 编译器)会抛出一个警告,告诉我它没有被初始化。如果我使用未初始化的变量运行此代码,有时它会起作用,而其他一些则不起作用。如何初始化该指针并将其传递给函数?

4

5 回答 5

1

您需要分配足够大的缓冲区以包含编码结果。要么在堆栈上分配它,就像这样:

unsigned char B64Encoded[256]; // the number here needs to be big enough to hold all possible variations of the argument

但是这种方式分配的空间太少,很容易造成栈缓冲区溢出。如果你在动态内存中分配它会更好:

int cbEncodedSize = srclen * 4 / 3 + 1;  // cbEncodedSize is calculated from the length of the source string
unsigned char *B64Encoded = (unsigned char*)malloc(cbEncodedSize);

完成后不要忘记释放()分配的缓冲区。

于 2009-06-24T21:27:34.413 回答
1

看起来你想使用这样的东西:

// allocate 4/3 bytes per source character, plus one for the null terminator
unsigned char *B64Encoded = malloc(srclen*4/3+1);

Base64Enc(src, srclen, B64Encoded);
于 2009-06-24T21:27:39.497 回答
1

如果您提供了错误,这将有所帮助。

我可以通过上面的功能成功地做到这一点:

int main() {
    unsigned char *B64Encoded;
    B64Encoded = (unsigned char *) malloc (1000);
    unsigned char *src = "ABC";
    Base64Enc(src, 3, B64Encoded);

}

肯定需要为数据分配空间。您还需要 malloc 比 src 更多的空间(我相信多 1/4)。

于 2009-06-24T21:31:28.960 回答
1

base64 编码字符串每三个字节的数据字符串有四个字节,因此如果 srclen 为 300 个字节(或字符),则 base64 编码字符串的长度为 400。

维基百科有一篇简短但相当不错的文章。

因此,将 srclen 四舍五入到最接近的三元组,除以三,乘以四应该正好足够内存。

于 2009-06-24T21:35:16.707 回答
1

我在您的代码中看到一个问题,即它可能会访问尾随空字符之后的字节,例如,如果字符串长度为一个字符。然后该行为未定义,如果激活缓冲区边界检查,则可能导致抛出异常。

这可以解释与访问未初始化内存相关的消息。

然后,您应该更改代码,以便单独处理尾随字符。

int len = (scrlen/3)*3;
for( int i = 0; i < len; i += 3 )
{
  // your current code here, it is ok with this loop condition.
}

// Handle 0 bits padding if required
if( len != srclen )
{
   // add new code here
}

...

PS:这是一个描述Base64 编码的维基百科页面。

于 2009-06-25T10:24:34.653 回答