今天,在用C語言刷LeetCode時,天真的我發現了leetcode的一個小 ”bug“,
但事實證明:我錯了!,,,,
題目:二叉樹的前序遍歷
圖片:

我用C語言的解答如下:
/**
* Note: The returned array must be malloced, assume caller calls free().
*/
//二叉樹節點的個數
int TreeSize(struct TreeNode* root)
{
return root==NULL?0:TreeSize(root->left)+TreeSize(root->right)+1;
}
//前序遍歷存值
void PrevTree(struct TreeNode* root,int *arr)
{
static int i=0;
if(root==NULL)
return;
arr[i++]=root->val;
PrevTree(root->left,arr);
PrevTree(root->right,arr);
}
int* preorderTraversal(struct TreeNode* root, int* returnSize){
*returnSize=TreeSize(root);
int* arr=(int*)malloc(sizeof(int)*(*returnSize));
PrevTree(root,arr);
return arr;
}
寫好了代碼,我習慣性的先執行代碼,然后點擊提交,
示例3:

執行代碼:

提交:

好家伙!有一點被leetcode戲耍的感覺,
錯誤詳情:堆溢位

我把測驗用例**“1”**帶入代碼中,紙上計算,VS下除錯,最后都沒有發現問題,為什么會產生堆溢位呢?
于是,我又嘗試點擊了2次提交,

思考
老鐵,你有發現我程式中的問題嗎?
如果沒有發現問題(像我一樣覺得leetcode有bug),那么請嘗試用多個測驗用例呼叫該介面 ,
再看看下面的原因,
百因必有果
我始終沒有找到原因,隨即請教了一位資深程式員老師,老師很快就發現了問題:靜態區域變數
先來看一個簡單的例子:

將test1和test2函式分別呼叫5次,結果是多少?
static靜態區域變數
static靜態區域變數是在堆區申請地址空間,在作用域結束時并不消失,當程式再次呼叫定義它的函式時,它保留了上一次留下來的值,
回到原問題中:

程式用一個測驗用例來呼叫該函式并不會產生問題,前序遍歷的函式只是執行了一次,并不會產生值的累加效果,但是如果程式多次呼叫該前序遍歷函式,未免會產生錯誤,

可以看到leetcode已經呼叫了3次該介面,靜態區域變數i發生了多次累加效果,以致于arr[i]超出了堆區的地址空間,越界訪問,導致堆溢位(heap-buffer-overflow),所以leetcode聰明的報出了bug,
leetcode真明智, 并沒有bug!
結語
- 百因必有果,多從自身角度檢查問題,
- 學會追根溯源,發現更深層次錯誤,多從不同方向思考問題,
- 多敲代碼,多除錯,多總結編碼經驗,
如果您對文章有任何想法,歡迎在下方評論區留言,
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/283055.html
標籤:其他
上一篇:這8件小事兒,對考研上岸很有幫助(21計算機考研經驗分享)
下一篇:2021-05-04
