C++中類成員使用前需要初始化的重要性


今天寫程序的時候,創建了一個結構體:

struct BufferObj {
char* buf;
int bufLen;
SOCKADDR_STORAGE addr;
int addrLen;
struct BufferObj* next;
};

該結構體有一個next指針,本意是這個指針初始的時候應該為NULL,如果有新的BufferObj添加,這個next指針就會指向這個新添加的BufferObj,其實就是一個鏈表。

程序中有一個生產者線程使用enqueueBufferObj方法向鏈表里面添加BufferObj:

void enqueueBufferObj(ConnectionObj* connObj, BufferObj* bufferObj) {
    EnterCriticalSection(&connObj->sendRecvQueueCriticalSection);

    

    if (connObj->pendingSendHead == NULL) {
        connObj->pendingSendHead = connObj->pendingSendTail = bufferObj;
    } else {
        
        connObj->pendingSendTail->next = bufferObj;
        connObj->pendingSendTail = bufferObj;
    }

    LeaveCriticalSection(&connObj->sendRecvQueueCriticalSection);
}

還有一個消費者線程從這個鏈表里面取BufferObj:

BufferObj* dequeueBufferObj(ConnectionObj* connObj) {
    BufferObj* res = NULL;

    EnterCriticalSection(&connObj->sendRecvQueueCriticalSection);

    if (connObj->pendingSendTail != NULL) {
        res = connObj->pendingSendHead;
        connObj->pendingSendHead = connObj->pendingSendHead->next;
        if (connObj->pendingSendTail == res) {
            connObj->pendingSendTail = NULL;
        }
    }
    LeaveCriticalSection(&connObj->sendRecvQueueCriticalSection);
    return res;
}

 其中,ConnectionObj結構體如下:

struct ConnectionObj {
    SOCKET s;
    HANDLE hRecvSemaphore;
    struct BufferObj* pendingSendHead;
    struct BufferObj* pendingSendTail;
    CRITICAL_SECTION sendRecvQueueCriticalSection;
};

剛開始的時候,由於程序中沒有顯示的將BufferObj的next屬性初始化NULL,導致程序運行到enqueueBufferObj方法時總是出現指針違法訪問:

connObj->pendingSendTail->next = bufferObj;

上面就是出錯的地方。程序中對於ConnectionObj中的pendingSendHead和pendingSendTail都已經顯示初始化為NULL了。經過查找發現,是因為程序中沒有顯式對

BufferObj中next進行NULL初始化,從而當消費者線程從隊列中BufferObj之后,會重新對隊列頭進行初始化,該代碼在dequeueBufferObj中:

connObj->pendingSendHead = connObj->pendingSendHead->next;

此時,如果BufferObj中的next顯示初始化為了NULL,那么connObj->pendingSendHead的值應該為NULL,但是程序中沒有對next進行顯式初始化,所以,此時,

connObj->pendingSendHead的值為一個隨機值,這導致生產者線程使用enqueueBufferObj在向隊列中添加新BufferObj時出錯:

if (connObj->pendingSendHead == NULL) {//如果next顯式初始化了,這個條件檢測應該成立
        connObj->pendingSendHead = connObj->pendingSendTail = bufferObj;
    } else {//但是由於next沒有顯示初始化,導致pendingSendHead的值不是NULL,而是一個隨機的,因此程序錯誤的運行到這里,出現上述錯誤
        
        connObj->pendingSendTail->next = bufferObj;
        connObj->pendingSendTail = bufferObj;
    }

 

在簡單的程序中,這中錯誤查找起來可能不是問題,但是如果程序很復雜,查找這種錯誤就會很浪費時間。因此,為了安全起見,以后對於C++中的結構體,類成員,在使用前,還是先進行初始化后為好。

 


注意!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。



 
粤ICP备14056181号  © 2014-2021 ITdaan.com