在工具實現的過程中,遇到了內存爆了的問題,部分模型的規模可以達到10的100次方方甚至1000次方。
(工具的主要算法涉及到了遞歸,遞歸深度會很深,所以也用到了ulimit修改棧空間來緩解爆棧的問題,治標不治本。)
有一個循環,這個循環迭代16次,但是可能程序在某一次迭代過程中,已經耗光了內存,再申請空間的時候,出現異常,導致將整個進程殺死。而我的想法是,當某一個迭代過程中,出現無法再申請內存的情況,就輸出內存申請失敗的提示信息,並跳過它,進行下一次的迭代,而不是將整個進程kill。
解決方法:
創建一個子線程,讓它每隔1秒去檢查 當前進程的內存占用,如果超過一定的比例,則跳過此次的迭代。
檢查當前進程的內存占用,是用shell腳本實現的,使用shell腳本進行對內存的查詢只需要兩三行即可。
當執行shell腳本的時候,要獲取其輸出結果,也就是該進程的內存占用。
具體代碼如下

1 void detect_memory() 2 { 3 4 for(;;) 5 { 6 FILE *pf; 7 char buffer[20]; 8 9 //執行內存檢測腳本 10 pf = popen("sh detect_memory.sh", "r"); 11 12 if(pf!=NULL){ 13 14 //buffer:enPAC進程占用的內存(KB) 15 //fread 將pf指向的內容,讀sizeof(buffer)個字節,讀一次,讀到buffer中 16 fread(buffer, sizeof(buffer), 1, pf); 17 18 //used:將buffer轉成整型,單位為MB 19 short int used = atoi(buffer)/1024; 20 pclose(pf); 21 22 //判斷enPAC占用的內存,超過一定比例,則將memory_flag=false 23 //同時break,讓dfs()進行return,結束此公式的search 24 if(100*used/total_mem > 70) 25 { 26 memory_flag = false; 27 cout<<"detect memory over the size given"<<endl; 28 break; 29 } 30 }else{ 31 cout<<"未能檢測到enPAC進程所占內存"<<endl; 32 pclose(pf); 33 } 34 35 //每隔5秒,對enPAC占用內存進行查詢 36 sleep(1); 37 } 38 39 40 } 41 42 detect_mem_thread = thread(&Product_Automata::detect_memory,this); //創建一個子線程進行內存監控
注:popen總是和pclose一起出現被使用的。popen() 創建一個管道,通過fork或者invoke一個子進程,然后執行command。popen返回該FIFO數據流的指針。fread(buffer, sizeof(buffer), 1, pf),fread 將pf指向的內容,讀sizeof(buffer)個字節,讀一次,讀到buffer中。
shell腳本如下:
#!/bin/bash
process="enPAC" #進程名字
PID=$(ps x | grep $process | grep -v grep | awk '{print $1}')
size=` cat /proc/${PID}/status | grep RSS | tr -cd "[0-9]"`
echo $size