出现问题的原因(JNI底层C代码问题)
1、数组越界(解决方法:增加数组容量)
2、局部指针变量在未使用完成时,被free释放。(解决方法:找准释放时机,或由系统自己释放)
例子:出处百度知道:Fatal signal 11 at 0xdeadbaad 错误怎么找
这个错误并不是再调用某个jni接口的时候发生的 而是反复调用之后(或是上层进行了一些其他操作后)冷不丁的蹦出来 程序虽然没有弹框,但进程已经挂了 这种随机问题最难搞了,很难确定哪行代码出的问题 于是各种百度谷歌寻求解决方案 其中最重要的错误信息是 Fatal signal 11 (SIGSEGV) at 0xdeadbaad (code=1) 网上也有很多人都遇到类似的问题 主要症结还是内存操作的问题 在经过各种排查测试后,折腾了老半天 终于找到问题所在,的确是内存操作有误 在jni里,我想把jbyteArray转化成char* 于是写了个转化函数,原型如下: char* ConvertJByteaArrayToChars(JNIEnv *env, jbyteArray bytearray, jbyte *&bytes) { char *chars = NULL; bytes = env->GetByteArrayElements(bytearray, 0); chars = (char *)bytes; int chars_len = env->GetArrayLength(bytearray); chars[chars_len] = 0; return chars; } 问题就出在 chars[chars_len] = 0; 这句话 假如GetByteArrayElements返回的是abc 则chars_len值为3 而chars[3]=0就等于是数组越界访问修改了 这样无形当中就破坏了堆内存给程序留下安全隐患 到特定时候就会触发错误爆发 后函数改为: char* ConvertJByteaArrayToChars(JNIEnv *env, jbyteArray bytearray, jbyte *&bytes) { char *chars = NULL; bytes = env->GetByteArrayElements(bytearray, 0); int chars_len = env->GetArrayLength(bytearray); chars = new char[chars_len + 1]; memcpy(chars, bytes, chars_len); chars[chars_len] = 0; return chars; } 就没有问题了 在调用函数处处理了char*之后再delete掉就ok了 哎,C++的指针真是让人又爱又恨 以后大家遇到类似问题 还是好好检查下native代码 看看有没有指针操作不当的问题 指针有风险,用时需谨慎 仅以此文小记,希望对大家有帮助~
百度百科中:
-
-
-
memcpy
c和c++使用的内存拷贝函数,memcpy函数的功能是从源src所指的内存地址的起始位置开始拷贝n个字节到目标dest所指的内存地址的起始位置中。
-
中文名
- 内存拷贝函数 外文名
- memcpy
-
函数原型
- 见正文 功 能
- 拷贝n个字节 返回值
- 指向dest的指针
目录
函数原型编辑
void *memcpy(void *dest, const void *src, size_t n);
功能编辑
从源src所指的内存地址的起始位置开始拷贝n个字节到目标dest所指的内存地址的起始位置中
所需头文件编辑
C语言:#include<string.h>
C++:#include<cstring>
返回值编辑
函数返回指向dest的指针。
说明编辑
1.source和destin所指的内存区域可能重叠,但是如果source和destin所指的内存区域重叠,那么这个函数并不能够确保source所在重叠区域在拷贝之前不被覆盖。而使用memmove可以用来处理重叠区域。函数返回指向destin的
指针.
2.如果目标数组destin本身已有数据,执行memcpy()后,将覆盖原有数据(最多覆盖n)。如果要追加数据,则每次执行memcpy后,要将目标数组地址增加到你要追加数据的地址。
注意:source和destin都不一定是数组,任意的可读写的空间均可。
函数实现编辑
Windows中
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
void
* __cdecl
memcpy
(
void
* dst,
const
void
* src,
size_t
count
)
{
void
*ret=dst;
#if defined(_M_MRX000)||defined(_M_ALPHA)||defined(_M_PPC)
{
extern
void
RtlMoveMemory(
void
*,
const
void
*,
size_t
count);
RtlMoveMemory(dst,src,count);
}
#else /*defined(_M_MRX000)||defined(_M_ALPHA)||defined(_M_PPC)*/
/*
*copy from lower addresses to higher addresses
*/
while
(count--){
*(
char
*)dst = *(
char
*)src;
dst = (
char
*)dst+1;
src = (
char
*)src+1;
}
#endif /*defined(_M_MRX000)||defined(_M_ALPHA)||defined(_M_PPC)*/
return
(ret);
}
|
coreutils中
1
2
3
4
5
6
7
8
9
10
|
void
*
memcpy
(
void
*destaddr,voidconst*srcaddr,size_tlen)
{
char
* dest=destaddr;
char
const
* src=srcaddr;
while
(len-->0)
{
*dest++ = *src++;
}
return
destaddr;
}
|
Linux中:
1
2
3
4
5
6
7
8
9
10
11
|
void
*
memcpy
(
void
*dest,constvoid*src,size_tcount)
{
assert
(dest!=NULL && src!=NULL);
char
* tmp=dest;
const
char
* s=src;
for
(
size_t
i=0;i<count;i++)
{
tmp[i]=s[i];
}
return
dest;
}
|
程序例example1
作用:将s中的字符串复制到字符数组d中。
1
2
3
4
5
6
7
8
9
10
11
12
13
|
//memcpy.c
#include <stdio.h>
#include <string.h>
int
main()
{
char
* s=
"GoldenGlobalView"
;
chard[20];
clrscr();
memcpy
(d,s,(
strlen
(s)+1));
printf
(
"%s"
,d);
getchar
();
return
0;
}
|
输出结果:Golden Global View
example2
作用:将s中第13个字符开始的4个连续字符复制到d中。(从0开始)
1
2
3
4
5
6
7
8
9
10
11
|
#include<string.h>
int
main(
{
char
* s=
"GoldenGlobalView"
;
char
d[20];
memcpy
(d,s+12,4);
//从第13个字符(V)开始复制,连续复制4个字符(View)
d[4]=
'\0'
;
//memcpy(d,s+12*sizeof(char),4*sizeof(char));也可
printf
(
"%s"
,d);
getchar
();
return
0;
}
|
输出结果: View
example3
作用:复制后覆盖原有部分数据
1
2
3
4
5
6
7
8
9
10
11
|
#include<stdio.h>
#include<string.h>
intmain(
void
)
{
char
src[]=
"******************************"
;
char
dest[]=
"abcdefghijlkmnopqrstuvwxyz0123as6"
;
printf
(
"destination before memcpy:%s\n"
,dest);
memcpy
(dest,src,
strlen
(src));
printf
(
"destination after memcpy:%s\n"
,dest);
return
0;
}
|
输出结果:
destination before memcpy:abcdefghijlkmnopqrstuvwxyz0123as6
destination after memcpy: ******************************as6
区别编辑
strcpy和memcpy主要有以下3方面的区别。
2、复制的方法不同。strcpy不需要指定长度,它遇到被复制字符的串结束符"\0"才结束,所以容易溢出。memcpy则是根据其第3个参数决定复制的长度。
3、用途不同。通常在复制字符串时用strcpy,而需要复制其他类型数据时则一般用memcpy