2017-06-07 61 views
0

我當前在堆棧上創建了std::ofstream,並且當它分配全局operator new,它從預先分配的緩衝區分配內存時,程序將在main完成援引std::locale0 : line 59. Read Access Violation. nodeptr was 0x...的程序崩潰點。 nodeptr的內存地址是一個真實的地址。我不知道爲什麼會發生這種情況,我只能假設這是因爲我誤解了配置實際上在做什麼。std :: fstream在使用預先分配的內存之後主要崩潰

這種行爲發生在構建MSVC Version 19.10.25019 x86測試版上,構建於debug程序完成沒有崩潰。 Memory博士在調試模式下報告沒有泄漏。

最少的代碼:

#include <fstream> 
#include <cstdlib> 

std::uint8_t *byte = static_cast<std::uint8_t*>(malloc(134217728)); // 134217728 = 128 MiB 

void *operator new(size_t bytes) throw(std::bad_alloc) 
    { 
     return static_cast<void*>(byte); // Tested empirically, and this is only called once so this shouldnt be a cause of a problem 
    } 

void operator delete(void *memory) throw() 
    {} 

int main() 
    { 
     std::ofstream out("abc"); 

     free(byte); 
    } 
+0

它不會出現新的替換被稱爲在調試版本,至少在Visual Studio 2017在發佈版本替換新只被調用一次,崩潰似乎是清理與您的描述相匹配的語言環境。代碼中的評論談論摧毀懶惰的方面。如果你在文件中看起來更高一些,你會發現在一個調試版本中有一個替換的新/刪除類。 –

+0

@RetiredNinja看起來這是關於定製的分配和std ::區域設置一個Visual C++的bug。 「的std ::區域設置在CRT當做CRT堆分配所有方面」 - 作爲前一個錯誤報告 –

回答

0

有兩個明顯的缺陷:

  1. 如果operator new被稱爲不止一次?如果out的構造函數構造一個子對象呢?

  2. 你自由byteout仍然在範圍內。當out的析構函數運行時,您已將其內存返回給系統。

試試這個:

#include <fstream> 
#include <cstdlib> 

std::uint8_t *byte = static_cast<std::uint8_t*>(malloc(134217728)); // 134217728 = 128 MiB 

void *operator new(size_t bytes) throw(std::bad_alloc) 
    { 
     static int offset = 0; 
     void * ret = static_cast<void*>(byte + offset); 
     offset += 16 * ((bytes + 15)/16); 
     return ret; 
    } 

void operator delete(void *memory) throw() 
    {} 

int main() 
    { 
     { 
      std::ofstream out("abc"); 
     } 

     free(byte); 
    } 
+0

完全相同的例外。對於1)那是因爲我想讓最小的代碼成爲可能,我忘了解釋我測試並確保'new'只被調用一次。 –

+0

Re。 (1),似乎設置所有使用流和其他啓動程序的設備將涉及多個分配 –

+0

@MM我的意思是永遠不會給出兩次相同的地址(除非分配大小爲零)並且與16字節邊界。 (我明明有錯。) –

相關問題