protocol buffer庫模板函數導致的內存錯誤問題

最近調查一個protocol buffer庫的問題:應用程序使用了libprotobuf-lite庫,在調試Debug版本時如果鏈接了Release版本的libprotobuf-lite庫,會在調用RepeatedPtrFieldBase::Destroy()時報告堆出錯;但是如果鏈接的是Debug版本的libprotobuf-lite庫就能正常運行。
調查了很長時間,原因可能是這樣的:
1. 在編譯Release版本的libprotobuf-lite庫時,鏈接的是Release版本的VC庫:
void RepeatedPtrFieldBase::Reserve(int new_size) { 調用
void** RepeatedPtrFieldBase::InternalExtend(int extend_amount) {
...
    rep_ = reinterpret_cast<Rep*>(
        new char[kRepHeaderSize + sizeof(old_rep->elements[0]) * new_size]);
是在protobuf庫文件repeated_field.cc中定義的普通類成員函數,new引用的(malloc)是Release版本的VC庫;
2. 在編譯Debug版本的應用程序時用到了protobuf庫的模板函數:
template <typename TypeHandler>
void RepeatedPtrFieldBase::Destroy() {
...
      delete [] reinterpret_cast<char*>(rep_);
模板函數要有具體的模板參數才能生成代碼,因此會延遲到編譯應用程序時才生成具體代碼,delete引用的(free)是Debug版本的VC庫。

於是內存分配和釋放採用了不同的庫,導致了前面描述的問題。
總結:一般第三方程序庫在鏈接前就完成了所有目標文件(.obj)的生成,鏈接生成庫時內存分配和釋放代碼會引用相同版本的VC庫,因此不管應用程序是Debug版本還是Release版本使用都沒有問題。而象protobuf這樣帶有模板函數的程序庫,相關的二進制代碼在鏈接庫時沒有全部生成,部分延期到了編譯應用程序代碼時,因此無法保證庫導出函數和模板函數會引用相同版本的VC庫,一旦這兩處出現內存分配和釋放的處理交叉就會導致潛在的內存錯誤。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章