首页 > 解决方案 > 当我在 JNI 中拼接字符串时“检测到堆损坏”

问题描述

我使用JNI这样连接字符串,并收到一个APP崩溃错误:“dlmalloc_real检测到堆损坏”,编译器告诉我内存堆有问题。我是新手,不知道是否使用JNI正确连接。在分配 char 的内存块时,我其他人会在 +1 或不 +1 时收到此错误。这个错误直接导致了我的APP崩溃,并且没有错误日志可以追踪。我只收到一个:“dlmalloc_real 检测到堆损坏”。此错误目前仅出现在 Android 5.x 上。没有其他版本发现这个错误。所以我想知道我的JNI连接拼接字符串是否错误。

这是我的代码原截图,最后re直接返回到JAVA层。

    const char *username = (*env)->GetStringUTFChars(env, user_name, NULL);
    const char *password = (*env)->GetStringUTFChars(env, pass_word, NULL);
    const char *http = "thi is a string***";
    const char *pas = "*thi is a string****";
    const char *httpTail = "thi is a string***";
    char *host = (char *) malloc(
            strlen(http) + strlen(username) +strlen(pas) + strlen(password) + strlen(httpTail)+1);
    strcat(host, http);
    strcat(host, username);
    strcat(host, pas);
    strcat(host, password);
    strcat(host, httpTail);
    correctUtfBytes(host);
    (*env)->ReleaseStringUTFChars(env, user_name, username);
    (*env)->ReleaseStringUTFChars(env, pass_word, password);
    jstring re = (*env)->NewStringUTF(env, host);
    return re;

该方法只检查编码是否符合 C 的编码格式。如果不进行检测和转换,函数newstringutf可能会报编码格式不符合的错误,因为Java的string和C的char字符编码不同

void correctUtfBytes(char *bytes) {
    char three = 0;
    while (*bytes != '\0') {
        unsigned char utf8 = *(bytes++);
        three = 0;
        // Switch on the high four bits.
        switch (utf8 >> 4) {
            case 0x00:
            case 0x01:
            case 0x02:
            case 0x03:
            case 0x04:
            case 0x05:
            case 0x06:
            case 0x07:
                // Bit pattern 0xxx. No need for any extra bytes.
                break;
            case 0x08:
            case 0x09:
            case 0x0a:
            case 0x0b:
            case 0x0f:
                /*
                 * Bit pattern 10xx or 1111, which are illegal start bytes.
                 * Note: 1111 is valid for normal UTF-8, but not the
                 * modified UTF-8 used here.
                 */
                *(bytes - 1) = '?';
                break;
            case 0x0e:
                // Bit pattern 1110, so there are two additional bytes.
                utf8 = *(bytes++);
                if ((utf8 & 0xc0) != 0x80) {
                    --bytes;
                    *(bytes - 1) = '?';
                    break;
                }
                three = 1;
                // Fall through to take care of the final byte.
            case 0x0c:
            case 0x0d:
                // Bit pattern 110x, so there is one additional byte.
                utf8 = *(bytes++);
                if ((utf8 & 0xc0) != 0x80) {
                    --bytes;
                    if (three)--bytes;
                    *(bytes - 1) = '?';
                }
                break;
        }
    }
}

标签: androidandroid-ndkjava-native-interface

解决方案


推荐阅读