2010-10-27 12 views
5

He intentado convertir un proyecto de vc7.1 a vs2010 que obtuve de codeproject. (Y aquí está el enlace h tt p: //www.codeproject.com/KB/cpp/transactions.aspx? Fid = 11253 & df = 90 & mpp = 50 & ruido = 3 & tipo = Posición & vista = Ampliado & fr = 1 # xx0xx¿La colocación nueva llama al constructor si el puntero pasado es nulo?

Pero después convertida y modificar su configuración.

lo encuentro de depuración, sin éxito, que dice excepción no controlada en 0x0028e7b9 en DrawIt.exe: 0xC0000005: ubicación de escritura de violación de acceso 0x00000000.

La línea de error dice así

data = new(Mm::Allocate(sizeof(DocData), sid)) DocData(); 

Y la función

void* Allocate(size_t size, SPACEID sid) 
{ 
    AUDIT 

    Spaces::iterator s = spaces.find(sid); 
    if (s == spaces.end()) 
     return NULL; 

    Space& space = s->second; 
    if (!space.transacting) 
     return NULL; 

    size = max(size, sizeof(Free)); 

    // TODO: assert that "data" is allocated in space 
    space.AssertData(); 

    // are there any more free chunks? 
    if (!space.data->sFreeHead) { 
     space.data->Insert(space.More(size)); 
    } 

    AUDIT 

    // find the first chunk at least the size requested 
    Free* prev = 0; 
    Free* f = space.data->sFreeHead; 
    while (f && (f->size < size)) { 
     prev = f; 
     f = f->next; 
    } 

    AUDIT 
    // if we found one, disconnect it 
    if (f) { 
     space.data->locTree.remove((size_t)f); 

     if (prev) prev->next = f->next; 
     else space.data->sFreeHead = f->next; 

     f->next = 0; 
     memset(&f->loc, 0, sizeof(f->loc)); 
    } else { 
     f = space.More(size); 
    } 

    // f is disconnected from the free list at this point 

    AUDIT 

    // if the free chunk is too(?) big, carve a peice off and return 
    // the rest to the free list 
    if (f->size > (2*(size + sizeof(Free)))) { 
     Free* tmp = space.data->Slice(f, size); // slice size byte off 'f' 
     space.data->Insert(f); // return the remainder to the free list 
     f = tmp; 
    } 

    AUDIT 

    CHECK_POINTER(f) 

    void* p = reinterpret_cast<void*>((char*)f + sizeof(Free::SIZE_TYPE)); 

    CHECK_POINTER(p) 

    return p; 
} 

Alguien tiene idea, PLZ?

Dado que no soy bueno en C++, tomará algún tiempo antes de descubrir cómo resolver este problema. Acabo de subir el código fuente source file, se agradecería si alguien pudiera ayudar.

+0

Esta es una muy buena pregunta que puede reformularse en términos más breves como: * ¿La ubicación nueva llama al constructor si el puntero pasado es nulo? * –

Respuesta

2

Bueno, su función Allocate está regresando claramente NULL. Es bastante difícil para nosotros decir dónde y por qué, y es trivial para usted establecer puntos de interrupción y recorrer el asignador usted mismo, por lo que le sugiero que haga eso y descubra dónde devuelve la función.

+0

Devuelve un puntero determinado ... Después de void * p = reinterpret_cast ((char *) f + sizeof (Gratis :: SIZE_TYPE)); – WhiteTopaz

4

[Esta respuesta puede estar equivocada; ver los comentarios para discusión; Voy a dejar esto sin recuperar por el momento para que podamos averiguar cuál es la respuesta]

Allocate devuelve NULL en varios casos de falla.

No verifica el resultado de llamar al Allocate antes de usarlo.

Necesita verificar el resultado. Alternativamente, puede lanzar una excepción cuando tiene una falla.

+0

Gracias, veré si puedo arreglarlo. – WhiteTopaz

+0

Pero P no es nulo cuando regresa, devuelve 0x0042ffd8? – WhiteTopaz

+0

¿Realmente necesita verificar null antes de llamar a la ubicación nueva? No he podido determinar esto a partir del estándar. Por un lado, parece sensato hacer, por otro lado, llamar al no throw new implica que el asignador puede devolver 0, y la construcción de colocación posterior debe omitirse ... Me da la sensación de que la colocación nueva * puede * ser llamado en un puntero nulo, pero no hay una referencia clara del estándar. También podría ser manejado por 'new (std :: nothrow)' realizando el cheque * antes de * llamar a la ubicación nueva. Por cierto, g ++ 4.2.1: 'new (0) test;' no llama al constructor, ni muere. –

Cuestiones relacionadas