2017-06-07 4 views
0

Ich habe derzeit eine std::ofstream auf dem Stapel erstellt, und wenn es eine globale operator new zuweist, die Speicher aus einem vorab zugewiesenen Puffer zuweist, stürzt das Programm danach ab main schließt den Aufruf von std::locale0 : line 59. Read Access Violation. nodeptr was 0x... als Programmabsturzpunkt ab. nodeptr 's Speicheradresse ist eine echte Adresse. Ich habe keine Ahnung, warum dies geschieht, und ich kann nur annehmen, dass es daran lag, dass ich missverstehe, was die Zuteilungen tatsächlich tun.std :: fstream stürzt nach main ab, während zuvor zugewiesener Speicher verwendet wird

Dieses Verhalten tritt auf einem release bauen auf MSVC Version 19.10.25019 x86 getestet, aufbauend auf debug ohne Absturz des Programms komplett hat. Dr. Memory meldet im Debug-Modus keine Lecks.

Minimal-Code:

#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

Es scheint nicht, dass der Ersatz neu in einem Debug-Build genannt wird, zumindest in Visual Studio 2017. In einem Release baut den Ersatz new wird nur einmal aufgerufen, und der Absturz scheint beim Bereinigen eines Gebiets zu sein, das Ihrer Beschreibung entspricht. Die Kommentare im Code sprechen davon, faule Facetten zu zerstören. Wenn Sie etwas höher in der Datei schauen, werden Sie sehen, dass es in einem Debug-Build einen Ersatz für die Klasse new/delete gibt. –

+0

@RetiredNinja Es scheint, als wäre dies ein Visual C++ - Bug in Bezug auf benutzerdefinierte Zuordnungen und std :: locale. "std :: locale in CRT geht davon aus, dass alle Facetten dem CRT-Heap zugewiesen werden" - ein Fehlerbericht –

Antwort

0

Es gibt zwei offensichtliche Fehler:

  1. Was passiert, wenn operator new mehr als einmal aufgerufen wird? Was passiert, wenn der Konstruktor out ein Unterobjekt konstruiert?

  2. Sie frei byte während out ist immer noch im Anwendungsbereich. Wenn der Destruktor out ausgeführt wird, haben Sie seinen Speicher bereits an das System zurückgegeben.

Versuchen Sie folgendes:

#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

Genau die gleiche Ausnahme wie zuvor. Für 1) Das war, weil ich den kleinsten möglichen Code haben wollte, und ich vergaß zu erklären, dass ich testete und sicherstellte, dass "neu" nur einmal genannt wurde. –

+0

Re. (1), es scheint wahrscheinlich, dass die Einrichtung aller Geräte für die Verwendung eines Streams und andere Startprozeduren mehrere Zuweisungen –

+0

@MM beinhalten Ich wollte nie die gleiche Adresse zweimal vergeben (außer für die Zuweisung der Größe Null) und an auszurichten 16-Byte-Grenze. (Was ich natürlich falsch verstanden habe.) –

Verwandte Themen