malloc分配到一块内存,读写操作时却发生segmentation falt的奇怪问题。

期初现象:malloc一块内存,读写操作时发生segmentation falt。一般来讲malloc倘若失败应该抛出异常,所以malloc返回一个指针后,这个指针应该都是可用的,况且是进行读操作。 所以遇到这个问题时感觉很奇怪。

继续现象:经过地址打印确认该地址是前面操作过的一个地址。说明地址不在系统保护区。

继续现象:通过地址便宜发现该地址前面便宜几位就能够访问了,说明仅有该段内存出了问题。怀疑该段内存被某些代码做了手脚。

重现现象:安卓上munmap大于1835008后面再用这块内存就会core。

测试代码:
{
int test_size = 1835008;
std::cout<<"test_size:"<<test_size<<std::endl;
char * abc = (char *)malloc(test_size);
abc[1] = 'a';
std::cout<<(long long)abc<<std::endl;
std::cout<<abc[1]<<std::endl;
std::cout<<munmap(abc test_size)<<std::endl;
std::cout<<abc[1]<<std::endl;
free(abc);
abc = (char *)malloc(test_size);
std::cout<<(long long)abc<<std::endl;
std::cout<<abc[1]<<std::endl;
}

{
int test_size = 1835009;
std::cout<<"test_size:"<<test_size<<std::endl;
char * abc = (char *)malloc(test_size);
abc[1] = 'a';
std::cout<<(long long)abc<<std::endl;
std::cout<<abc[1]<<std::endl;
std::cout<<munmap(abc test_size)<<std::endl;
std::cout<<abc[1]<<std::endl;// 即使没有这句,下一句打印仍然会core的
free(abc);
abc = (char *)malloc(test_size);
std::cout<<(long long)abc<<std::endl;
std::cout<<abc[1]<<std::endl;
}

执行结果:
test_size:1835008
506508402240
a
-1
a
506508401344

test_size:1835009
506510442496
a
0
Segmentation fault

前面申请到内存506508402240时该内存还处于可用状态,后面再次申请到时就变成不可访问的了。

 

结论:感觉是安卓上超过1835008的内存就会用mmap方式分配(应该受限于glibc限定、ptmalloc实现时对具有长生命周期或特别大的内存分配会使用mmap。),此时该块内存可以被unmap掉,而unmap掉之后,该块内存就会引发Segmentation fault。这个在munmap使用说明有提到。(munmap该调用在进程地址空间中解除一个映射关系,addr是调用mmap()时返回的地址,len是映射区的大小。当映射关系解除后,对原来映射地址的访问将导致段错误发生。)

猜测也是munmap操作与glibc操作冲突导致glibc管理出现混乱无法对该机制内存进行再次map操作了。

posted @ 2019-11-27 00:39  dzqabc  阅读(1204)  评论(0编辑  收藏  举报