在android上使用偏移量时,memcpy的问题

issues with memcpy on android when using offset for the source

本文关键字:memcpy 问题 偏移量 android      更新时间:2023-10-16

我正在使用JNI开发android应用程序。

我一直从java发送byte[],它在cpp中作为jbyteArray到达。

jbyteArraysigned char*,我使用这个函数:

jbyte* content_array = (env)->GetByteArrayElements(array,NULL);

(jbyte*只是signed char*的一个类型定义)

现在我遇到了问题,当试图访问数据在signed char*指针在以后的时间。它认为在某个时刻java垃圾收集器启动并释放内存,因此我不能再访问它。

为了解决这个问题,我现在像这样复制传入的数据:

    // newJavaByteData is the signed char* coming in from java
    signed char* buffer = new signed char[length];
    memcpy(buffer, newJavaByteData, length);
    //javaByteData is a std::vector<signed char*>
    javaByteData.push_back(buffer);

到目前为止一切顺利。在以后的帧中,我可以读取数据,当我不再需要它时,我像这样删除它:

        int frame_cnt=0;
        while(frame_cnt<javaByteData.size()){
            delete javaByteData[frame_cnt++];
        }
        javaByteData.clear();

现在我需要从这个数据中提取字节块。我再次使用memcpy来提取所需的字节部分。

这次我需要在源指针

上应用一个偏移量
    char* extractedBytes[lengthOfBytes];
    //originalJavaData is the signed char* i did alloc and memcpy into earlier
    memcpy(extractedBytes, &originalJavaData[offset], lengthOfBytes* sizeof(char));

这工作得很好,直到它不是:(

我可以用这种方式提取数据,但是当我提取的字节数超过某个限制时,我得到这个错误:

SIGSEGV (signal SIGSEGV: invalid address (fault address: 0x53))

每次运行app消息,故障地址都不一样。

我还不确定限制是什么,但我可以提取262144字节(256x256x4)正好好,而提取1048576字节(1024x1024x4)会导致崩溃/信号。

我认为问题是我在cpp线程中内存不足,但我可以高兴地分配更多的内存。只是memcpy失败了。

我想我可以为SIGSEGV信号设置一个eventandler,但我没有经验,而且我已经将问题追踪到memcpy的使用,所以我希望这只是一件我用memcpy做错的事情。

我认为可能是内存未正确对齐的问题,因此memcpy由于我将偏移量添加到源指针而失败。

OK。我找到问题了。

这似乎是我运行的堆栈内存,而当我使用堆内存我很好去。

而不是这几行:

char* extractedBytes[lengthOfBytes];
//originalJavaData is the signed char* i did alloc and memcpy into earlier
memcpy(extractedBytes, &originalJavaData[offset], lengthOfBytes* sizeof(char));

我现在有了这个:

char* extractedBytes = new char[lengthOfBytes];
//originalJavaData is the signed char* i did alloc and memcpy into earlier
memcpy(extractedBytes, &originalJavaData[offset], lengthOfBytes* sizeof(char));

memcpy现在正在做它的工作,并且毫无怨言地提取signed char*的部分内容。

当然,通过在堆上分配内存,我现在必须注意以后处理我的数据。

旁注:我自己停止复制传入的数据,而不是GetByteArrayElements,我现在使用GetByteArrayRegion为我做复制。

希望我不会再因为回答自己的问题而被否决。对我来说,这是解决我问题的有效方法。