JNI中将jbyteArray转为std::string的C++实现崩溃问题排查
First off, let's clear up why malloc gave you a compile error in C++: unlike C, C++ doesn't allow implicit conversion from void* (the return type of malloc) to other pointer types. So you need to explicitly cast the result:
char* buffer = static_cast<char*>(malloc(num_bytes + 1));
Skip that cast, and the compiler will throw an error—that's almost certainly what happened to you.
Now, the crash you're seeing is definitely tied to your new usage mistake. When you write new char(num_bytes + 1), you're allocating a single char initialized to the value num_bytes + 1, not an array of num_bytes + 1 chars. That means your buffer only points to 1 byte of memory, but you're trying to copy num_bytes bytes into it (plus a null terminator)—this causes a buffer overflow, leading to undefined behavior like a crash.
Correct C++ Implementation
Let's rewrite your code to fix these issues, with safer practices that avoid manual memory management where possible:
Option 1: Directly Create a std::string (Recommended)
This skips the unnecessary intermediate buffer entirely, which is more efficient and less error-prone:
jsize num_bytes = env->GetArrayLength(message); // Get access to the Java byte array elements jbyte* elements = env->GetByteArrayElements(message, nullptr); if (!elements) { // Handle JNI error (return or throw as your code requires) return 2; } // Create std::string directly from the byte array (no null terminator needed here) std::string m(reinterpret_cast<const char*>(elements), num_bytes); // Release JNI's internal buffer—JNI_ABORT means we don't copy changes back (we didn't modify elements) env->ReleaseByteArrayElements(message, elements, JNI_ABORT);
Option 2: If You Need a Null-Terminated C-Style String
If you must have a null-terminated buffer (e.g., for passing to C functions), allocate the array correctly and clean up properly:
jsize num_bytes = env->GetArrayLength(message); // Allocate an array of chars (use [] for array allocation) char* buffer = new char[num_bytes + 1]; if (!buffer) { // Handle memory allocation failure return 1; } // Get JNI byte array elements jbyte* elements = env->GetByteArrayElements(message, nullptr); if (!elements) { // Clean up the buffer before exiting delete[] buffer; return 2; } // Copy bytes and add null terminator memcpy(buffer, elements, num_bytes); buffer[num_bytes] = '\0'; // Use the buffer (e.g., create std::string or pass to C functions) std::string m(buffer); // Release JNI resources and clean up our buffer env->ReleaseByteArrayElements(message, elements, JNI_ABORT); delete[] buffer; // Always use delete[] for arrays allocated with new[]
Key Takeaways
mallocworks in C++ if you explicitly cast itsvoid*return value to the desired pointer type.- Your crash came from using
new char(n)instead ofnew char[n]—the former allocates a single char, the latter allocates an array. - When using
new[]to allocate arrays, always usedelete[]to free them (never plaindelete—this causes undefined behavior). - Prefer
std::stringdirectly over manual buffer allocation in C++ to avoid memory leaks and buffer errors.
内容的提问来源于stack exchange,提问作者Poperton

