Fatal signal 11 (SIGSEGV) at 0xff500020 (code=1) 类问题

出现问题的原因(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方面的区别。
1、复制的内容不同。 strcpy只能复制 字符串,而memcpy可以复制任意内容,例如 字符数组、整型、 结构体、类等。
2、复制的方法不同。strcpy不需要指定长度,它遇到被复制字符的串结束符"\0"才结束,所以容易溢出。memcpy则是根据其第3个参数决定复制的长度。
3、用途不同。通常在复制字符串时用strcpy,而需要复制其他类型数据时则一般用memcpy


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值