2010-08-12 26 views
3

我在努力用XCode 3.2,GCC 4.2,libstdC++ 4.0,動態版本替換全局新增和刪除操作符。在OSX上替換libstdC++。dylib(4.0)全局新增和刪除操作符

我直接從標頭「新」採取原型,並實施它們。它們粘貼在下面。

該項目是一個.plugin所以動態庫。這個插件必須將分配委託給主應用程序自己的alloc/free例程,這些例程位於舊的C SDK中。

所有我自己對新/刪除以及std :: list和std :: map分配的調用都被正確地替換了,但是當std :: vector :: push_back不得不增加它的緩衝區時。這種情況下,我的運營商新不叫,但我的運營商刪除是。我知道,因爲我在我的新運算符分配的任何緩衝區的前四個字節中寫入了一個令牌,並且我在運算符delete中檢查了此令牌。請參閱下面的違規代碼。

extern "C++" 
{ 
__attribute__((visibility("default"))) void* operator new(std::size_t) throw (std::bad_alloc); 
__attribute__((visibility("default"))) void* operator new[](std::size_t) throw (std::bad_alloc); 
__attribute__((visibility("default"))) void operator delete(void*) throw(); 
__attribute__((visibility("default"))) void operator delete[](void*) throw(); 
__attribute__((visibility("default"))) void* operator new(std::size_t, const std::nothrow_t&) throw(); 
__attribute__((visibility("default"))) void* operator new[](std::size_t, const std::nothrow_t&) throw(); 
__attribute__((visibility("default"))) void operator delete(void*, const std::nothrow_t&) throw(); 
__attribute__((visibility("default"))) void operator delete[](void*, const std::nothrow_t&) throw(); 

} 

下面的代碼會導致斷言時,「喲」超出範圍,因爲分配給的std ::矢量內存不是由我的運營商新的分配。

{ 
     std::vector<std::string> yo; 
     yo.push_back("yoyoma"); 
     yo.push_back("yoyoma"); 
     yo.push_back("yoyoma"); 
     yo.push_back("yoyoma"); 
    } 

下面的代碼是可以的,因爲的std ::矢量::儲備調用我的operator new:

{ 
     std::vector<std::string> yo; 
     yo.reserve(4); 
     yo.push_back("yoyoma"); 
     yo.push_back("yoyoma"); 
     yo.push_back("yoyoma"); 
     yo.push_back("yoyoma"); 
    } 

GBD(調試器)不會讓滿足跨進的std ::矢量:: push_back實現時需要增長緩衝區(該方法名爲_M_insert_aux)。我所知道的是,我的操作符new從來不會從std :: vector :: push_back中調用。

上述解決方法不能應用於我正在使用的所有第三方庫。其中之一是push_back的大用戶。

我試着靜態鏈接到libstdC++。a但我遇到同樣的問題。

是否有一些std :: vector < std :: string>不使用全局new運算符的特化?

順便說一句,這與VS9的Windows完美工作。

+0

更可靠的方法來檢查您是否被調用是在調用應用程序API之前插入斷點。 – Potatoswatter 2010-08-12 21:29:40

回答

0

我不完全確定如何完全按照您的要求進行操作,但是您可以使用自定義分配器在STL中實現自己的分配語義。

http://www.cplusplus.com/reference/std/memory/allocator/

我想我還記得++時,我一直在尋找在漢斯 - Bohen GC對於C,該庫將取代新/用GC版本刪除,但你仍然不得不分配器傳遞給STL結構你希望使用。

此外,您正在使用的庫中仍有可能存在使用malloc的代碼。需要思考的東西。

0

_M_insert_auxvector.tcc這令人討厭的不適合GCC。但是,快速掃描顯示它像其他方法一樣正確調用分配器。

pointer __new_start(this->_M_allocate(__len)); 

你可以嘗試設置斷點在你operator new,定義自定義分配器(你可以從std::allocator派生),它打印調試輸出,或在new_allocator.h:91,其中文庫應該打電話給你覆蓋設置一個斷點。

+0

vector.tcc中的實現非常複雜。在調試一個簡單的控制檯應用程序時,我實際上能夠進入該代碼。我不知道爲什麼GDB在調試.dylib時找不到源代碼。 – 2010-08-13 18:28:54

0

最可能的解釋是GCC的std :: vector的內部實現包含了新的重載。 MSVC有許多額外的操作員新的重載。您需要拆分源代碼或創建新的自定義分配器。

+0

GCC不這樣做。 – Potatoswatter 2010-08-12 21:41:18

1

我終於用George Costanza的技術解決了我的問題:做相反的事情。

而不是試圖讓我的操作員新增和刪除可見性,我完全隱藏它們。

關鍵是要設置這些每一個靜態庫&束中的設置:

  • 設置C++標準庫類型:靜態
  • 符號默認是隱藏的:經過
  • 修復&繼續:未選中(非常重要,否則默默禁用以前的設置)

並做一個乾淨的所有& b因爲使用XCode 3.2只需在更改這些設置後點擊Build就無法工作。

很顯然,我改變了運營商新&刪除原型:

#pragma GCC visibility push(hidden) 

extern "C++" 
{ 
    void* operator new(std::size_t) throw (std::bad_alloc); 
    void* operator new[](std::size_t) throw (std::bad_alloc); 
    void operator delete(void*) throw(); 
    void operator delete[](void*) throw(); 
    void* operator new(std::size_t, const std::nothrow_t&) throw(); 
    void* operator new[](std::size_t, const std::nothrow_t&) throw(); 
    void operator delete(void*, const std::nothrow_t&) throw(); 
    void operator delete[](void*, const std::nothrow_t&) throw(); 
} // extern "C++" 

#pragma GCC visibility pop 

沒有爲什麼工作?必須同時具有靜態+隱藏符號才能工作。它似乎將我的包插件從STL專業化實現中屏蔽,這些實現將內容分配給它們。

還要注意,這隻發生在一個從大應用程序動態加載的包插件中。在一個從控制檯應用程序調用的簡單的.dylib項目中,任何設置都可以正常工作。