程序发生内存访问错误(signal 11)退出,请大家帮忙看看

小弟的一段采样程序,运行一段时间(时间不确定,有时候几小时,有时候几分钟)后发生signal 11错误。

这个问题折磨我很久了,请大家帮忙看看问题出在哪里。

while(gNavRunFlag)
{
InterruptWait (NULL, NULL); // Waitting for interrupt

/* Allocation memory */
pCntReadNew = (struct LNode_CNT_t *)malloc(149);
if(pCntReadNew == NULL)
{
printf(“malloc error.\n”);
break;
}// end of if

/* Read AD result */
pCntReadNew->pAddrLNode = pCntReadNew;
pCntReadNew->WriteOverFlag = 0;
pCntReadNew->pNext = NULL;

for(i=0; i<10; i++) // Read ad result
{
for(j=0; j<14; j++)
{
pCntReadNew->CntData_[j] = in8(Addr_CntData[j]);
}
}// end of for


/* Append the new element to the linklist of ReadList /
if(pCntLinkListLast == NULL)
{
pCntLinkListLast = pCntReadNew;
pCntLinkListFirst = pCntReadNew;
}// end of if
else
{
pCntLinkListLast->pNext = pCntReadNew;
}// end of else
pCntLinkListLast = pCntReadNew;

/
Post the semaphore of read over /
gNavCounter ++;
sem_post(&semCntReadOver);

/
Search the node which should be free */
while(pCntLinkListFirst != NULL)
{
if(pCntLinkListFirst->WriteOverFlag == 1)
{
pCntFree = pCntLinkListFirst->pAddrLNode;
pCntLinkListFirst = pCntLinkListFirst->pNext;
free(pCntFree); // Free the memory which is useless
} // end of if
else
{
break;
}
} // end of while

InterruptUnmask(TIME_OUT_IRQ, CntIntId);
}// end of while_

退出发生在第二行pCntReadNew = (struct LNode_CNT_t *)malloc(149);

进行dumper结果如下:
Program terminated with signal 11, Segmentation fault.
Reading symbols from /usr/qnx632/target/qnx6/x86/lib/libc.so.2…done.
Loaded symbols for /usr/qnx632/target/qnx6/x86/lib/libc.so.2
#0 0xb0320d9f in _flist_bin_first_fit ()
from /usr/qnx632/target/qnx6/x86/lib/libc.so.2
(gdb) bt
#0 0xb0320d9f in _flist_bin_first_fit ()
from /usr/qnx632/target/qnx6/x86/lib/libc.so.2
#1 0xb032020c in _list_memalign ()
from /usr/qnx632/target/qnx6/x86/lib/libc.so.2
#2 0xb03205d8 in _list_alloc () from /usr/qnx632/target/qnx6/x86/lib/libc.so.2
#3 0xb0321110 in __malloc_lock ()
from /usr/qnx632/target/qnx6/x86/lib/libc.so.2
#4 0xb03211c8 in __malloc () from /usr/qnx632/target/qnx6/x86/lib/libc.so.2
#5 0xb031ea72 in malloc () from /usr/qnx632/target/qnx6/x86/lib/libc.so.2
#6 0x080495e4 in nav_counter_read_thread (arg=0x0) at hjq.c:392
(gdb) up
#1 0xb032020c in _list_memalign ()
from /usr/qnx632/target/qnx6/x86/lib/libc.so.2
(gdb) up
#2 0xb03205d8 in _list_alloc () from /usr/qnx632/target/qnx6/x86/lib/libc.so.2
(gdb) up
#3 0xb0321110 in __malloc_lock ()
from /usr/qnx632/target/qnx6/x86/lib/libc.so.2
(gdb) up
#4 0xb03211c8 in __malloc () from /usr/qnx632/target/qnx6/x86/lib/libc.so.2
(gdb) up
#5 0xb031ea72 in malloc () from /usr/qnx632/target/qnx6/x86/lib/libc.so.2
(gdb) up
#6 0x080495e4 in nav_counter_read_thread (arg=0x0) at hjq.c:392
392 pCntReadNew = (struct LNode_CNT_t *)malloc(149);
(gdb) up
Initial frame selected; you cannot go up.
(gdb)

出错的这个线程负责从硬件读回数据,另有一个线程负责将数据写入磁盘,程序如下:

while(gNavRunFlag | (pCntLinkListFirst != NULL))
{
/* Wait for semaphore */
sem_wait(&semCntReadOver);

/* Search the node which should be write to the file */
if(pCntLinkListFirst == NULL)
{
continue;
}
pCntWrite = pCntLinkListFirst;
while(pCntWrite->WriteOverFlag == 1)
{
pCntWrite = pCntWrite->pNext;
if(pCntWrite == NULL)
{
break;
}
}// end of while
if(pCntWrite == NULL)
{
continue;
}

/* Write the data to the file */
nwrite = write(fdCntData, pCntWrite->CntData, 140);
if(nwrite != 140)
{
printf(“Write CntData.dat Error!\n”);
}// end of if
pCntWrite->WriteOverFlag = 1;

}// end of while

还有一个现象就是,如果禁止将数据写入磁盘的线程工作,那么不会发生sigmal 11错误,但是会malloc()会返回内存申请失败。之后数据采集卡FIFO溢出,硬件失去响应,但程序可以继续运行。

我现在认为根本原因应该是采集卡硬件FIFO深度不够,采集程序来不及读回数据引起的,但是想不通为什么会引起signal 11错误,希望大家帮忙分析分析。

简单看了一下,以下是我的猜想:)

不管之前是什么原因,最后都应该是malloc多,free少引起的吧。
最后的最后肯定就没内存可用了。
可用#pidin info #showmem之类的命令看看内存用量。

不过我觉得你不停的malloc和free不是一个好的方法。

先要保证写硬盘的速度比采集的快。不然怎么设计也是丢数据。
这样程序所需要的内存应该会在一个范围内。不如一开始就malloc好一块内存来放数据。如做成环形链表的样式等。

谢谢nakeyfish,不过我试过屏蔽掉写磁盘的线程,程序也没什么问题,觉得应该不是内存不够引起的。
今天又试了一下,在写磁盘线程中进行free操作,1到2秒就出现了signal 11错误,错误点仍然是malloc。现在把精力集中在查找是否对同一地址进行了free操作上,但是自己查程序始终看不明白哪里可能会发生多次free操作的情况。
另外已经准备用环形缓冲区的方式了,但是老板还是坚持要求找出发生错误的原因,郁闷呀,大家帮忙出出主意吧。

IDE里有QNX Memory Analysis这个功能,可以试用一下。
用法可以参考File->New…->Example里的Detecting Runtime Errors示例工程。