程序长时间运行崩溃,VC运行库BUG

最近發現Visual C++ 6.0有一個有趣的,能讓programmer發瘋的bug。Debug版本編譯出來的程序可能最終會異常中止,也許是報告程序停在斷點xxxxxxx。更確切地說是用debug 版本的運行時庫編譯的程序。

由於項目需要寫了一個求最短路徑的引擎。 運行穩定(內存,CPU,Handle count 保持未定),但是一段時間後,進程突然退出(crash?)。確切地說是計算了20000+ 對(源點、目標點)後。沒有捕捉到任何異常。就好像有人殺掉進程似的。通過分析在Adplus在進程退出前創建的進程dump,發現是CTRL+C導致進 程退出,堆棧信息顯示計算線程最後調用函數是_heap_alloc_dbg。 這個函數是被由new 或者malloc調用的。

難道是out of memory?可是performance monitor 現實內存穩定,並沒有洩漏。仔細分析dump,發現程序最後一個語句是dbgheap.c的338 行

if (lRequest == _crtBreakAlloc)   //337
           _CrtDbgBreak();                //338

根據msdn,_CrtDbgBreak 用來設定斷點。為什麼呢?閱讀_heap_alloc_dbg函數發現:

  lRequest = _lRequestCurr;

       /* break into debugger at specific memory allocation */
       if (lRequest == _crtBreakAlloc)
           _CrtDbgBreak();

       //省略如干行
       ++_lRequestCurr;

也就是說一旦_heap_alloc_dbg被調用,_lRequestCurr就增加1,搜索_lRequestCurr和_crtBreakAlloc,發現定於如下:

static long _lRequestCurr = 1;
_CRTIMP long _crtBreakAlloc = -1L;

並且只有函數_CrtSetBreakAlloc改變_crtBreakAlloc 。在我的程序中沒有地方調用_CrtSetBreakAlloc,所以_crtBreakAlloc 應該保持-1,所以只要_heap_alloc_dbg, 也就是說new 或malloc被不停的調用,即使請求的內存被正確釋放,條件lRequest == _crtBreakAlloc最終會滿足。Yes, that's it!!!

寫了一個簡單的小程序如下,證實了我的想法。

int nCount = 1;
while(1)
{  
  char* p = new char[4];    //cause _lRequestCurr to increase
  delete []p;
  nCount++;
  if(nCount == 0xffffffff)  //_lRequestCurr should reach this value already
break;              //to ensure that if my thought is wrong, loop could break    
}

所以我認為這是debug run-time library的一個bug。如果程序(compiled with vc6 debug version run-time library)中會不停的請求內存,那麼該程序最終會異常中止,只是時間問題。

所幸的是微軟在以後的版本中對這個做了修改,vs2005中已經沒喲這個bug了。具體不知道是從那個版本開始的。

資料來源:http://blog.csdn.net/Miracle08/archive/2006/12/24/1457060.aspx

 

遇到過一個通信方面的軟件,需要長期運行,做壓力測試時,高負荷連續運行一定天數時必定崩潰,而且都是在msvcrtd.dll中崩潰。負責維護的人百思不得其解,就去問微軟的人,結果微軟的人說這是VC6帶的msvcrtd.dll的一個問題,VC2005已經沒有這個問題了,請升級到新的版本。這個軟件規模比較大,依賴於很多庫,後台都是用VC6編譯的調試版本,為了方便定位問題,沒有Release版本。升級到VC2005後會不會出現別的問題,沒有人敢冒這個風險,於是沒有使用VC2005。

閒著沒事的時候分析了一下,才發現問題其實很簡單。msvcrtd.dll對每次內存申請都進行計數,當計數值達到設定的某個值時,就會調用_CrtDbgBreak()。MSDN對_CrtDbgBreak的說明是:Sets a break point on a particular line of code,其實_CrtDbgBreak在X86下只有一條指令就是int 3(0xCC)。

在dbgheap.c中定義了下面兩個變量:

static long _lRequestCurr = 1;      /* Current request number */

extern "C" _CRTIMP long _crtBreakAlloc = -1L;  /* Break on allocation by request number */

_lRequestCurr表示當前的申請次數,_crtBreakAlloc表示當內存申請次數達到某個值時break,即調用_CrtDbgBreak。詳情可參考debugheap.c中的_heap_alloc_dbg_impl函數:

lRequest = _lRequestCurr;

/* break into debugger at specific memory allocation */

if (_crtBreakAlloc != -1L && lRequest == _crtBreakAlloc)

_CrtDbgBreak();

VC6附帶的dbgheap.c中沒有添加_crtBreakAlloc != -1L的判斷,而是:

if (lRequest == _crtBreakAlloc)

_CrtDbgBreak();

_lRequestCurr初始化為1,每次申請內存都加1,當_lRequestCurr為-1時在VC6的dbgheap.c中就會觸發int 3導致程序退出,而在新的版本中添加了_crtBreakAlloc != -1L的判斷,所以默認的情況下是不會觸發int 3 退出的。

可以通過調用_CrtSetBreakAlloc設置_crtBreakAlloc的值,當我們設置了新的_crtBreakAlloc,而且_crtBreakAlloc等於_lRequestCurr時就會觸發int 3。

弄清楚了問題的所在,我們就可以著手解決問題了。VC6的dbgheap.c中有兩個地方判斷了lRequest 是否與_crtBreakAlloc相等,相等後執行指令int 3。我們不用複雜的處理,把int 3替換為nop(0x90)指令即可。首先得到「if (_crtBreakAlloc != -1L && lRequest == _crtBreakAlloc)」 對應的二進制指令,用UE打開msvcrtd.dll,使用16進制編輯模式,查找得到的二進制指令,發現確實只有二處,把緊接著它們的0xCC替換為0x90,問題解決。

資料來源:http://blog.csdn.net/someonea/archive/2008/03/29/2229183.aspx

深度学习是机器学习的一个子领域,它基于人工神经网络的研究,特别是利用多层次的神经网络来进行学习和模式识别。深度学习模型能够学习数据的高层次特征,这些特征对于图像和语音识别、自然语言处理、医学图像分析等应用至关重要。以下是深度学习的一些关键概念和组成部分: 1. **神经网络(Neural Networks)**:深度学习的基础是人工神经网络,它是由多个层组成的网络结构,包括输入层、隐藏层和输出层。每个层由多个神经元组成,神经元之间通过权重连接。 2. **前馈神经网络(Feedforward Neural Networks)**:这是最常见的神经网络类型,信息从输入层流向隐藏层,最终到达输出层。 3. **卷积神经网络(Convolutional Neural Networks, CNNs)**:这种网络特别适合处理具有网格结构的数据,如图像。它们使用卷积层来提取图像的特征。 4. **循环神经网络(Recurrent Neural Networks, RNNs)**:这种网络能够处理序列数据,如时间序列或自然语言,因为它们具有记忆功能,能够捕捉数据中的时间依赖性。 5. **长短期记忆网络(Long Short-Term Memory, LSTM)**:LSTM 是一种特殊的 RNN,它能够学习长期依赖关系,非常适合复杂的序列预测任务。 6. **生成对抗网络(Generative Adversarial Networks, GANs)**:由两个网络组成,一个生成器和一个判别器,它们相互竞争,生成器生成数据,判别器评估数据的真实性。 7. **深度学习框架**:如 TensorFlow、Keras、PyTorch 等,这些框架提供了构建、训练和部署深度学习模型的工具和库。 8. **激活函数(Activation Functions)**:如 ReLU、Sigmoid、Tanh 等,它们在神经网络中用于添加非线性,使得网络能够学习复杂的函数。 9. **损失函数(Loss Functions)**:用于评估模型的预测与真实值之间的差异,常见的损失函数包括均方误差(MSE)、交叉熵(Cross-Entropy)等。 10. **优化算法(Optimization Algorithms)**:如梯度下降(Gradient Descent)、随机梯度下降(SGD)、Adam 等,用于更新网络权重,以最小化损失函数。 11. **正则化(Regularization)**:技术如 Dropout、L1/L2 正则化等,用于防止模型过拟合。 12. **迁移学习(Transfer Learning)**:利用在一个任务上训练好的模型来提高另一个相关任务的性能。 深度学习在许多领域都取得了显著的成就,但它也面临着一些挑战,如对大量数据的依赖、模型的解释性差、计算资源消耗大等。研究人员正在不断探索新的方法来解决这些问题。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值