Cargando la página...

Access violation in module rtl100.bpl en Win7 (C++Builder)

Por Darío el 06 de noviembre de 2011 en los siguientes foros: C++ Delphi

Access violation in module rtl100.bpl en Win7 (C++Builder)

Avatar de Darío
Hola,

Tengo una aplicación que usa ZEOSDBO, creación y destrucción dinámica de TImage, TLabel y TEdit dentro de un TScrollBox, un componente simple que usa FindFirstChangeNotification (TfisFileNotification de FISH 2000) y un TTimer.

Se debe mover una TImage ubicada en un TScrollBox origen hacia otro TScrollBox destino, cuando hago el seguimiento del código del evento OnDragDrop del TScrollBox destino, el procedimiento termina sin error (el seguimiento lo hago con BDS 2006), pero cuando ejecuto la aplicaci{on en W7 me salta el error "Access violation at address 2000697A in module 'rtl100.bpl'. Read of address EFEFEFBF"

Este error no salta en XP

Nota: W7 es de 64 bits

El objetivo de este TForm es:


  1. El usuario selecciona un directorio que contiene una o más imágenes en formato JPEG BMP y WMF

  2. Por cada imagen, la redimensiona a 200px de altura y su proporción en ancho

  3. Carga la miniatura en sbxEsc (TScrollBox origen)

  4. El usuario arrastra una imagen desde sbxEsc hasta sbxDoc (para conformar las imágenes que compondrán el documento) Acá salta el error



  5. Este es el código (sbxDoc es el TScrollBox origen y sbxEsc es el TScrollBox destino):

    //---------------------------------------------------------------------------

    void __fastcall TfrmEscMas::sbxDocDragDrop(TObject *Sender, TObject *Source,
    int X, int Y)
    {
    try
    {
    int val_tag = ((TImage*)Source)->Tag;
    AnsiString nomComp = ((TImage*)Source)->Parent->Name;

    if (((TImage*)Source)->Parent->Name == "sbxEsc")
    {
    TImage *img = new TImage(sbxDoc);
    img->Parent = sbxDoc;

    img->Height = ((TImage*)Source)->Height;
    img->Width = ((TImage*)Source)->Width;
    img->Left = X;
    img->Top = ESPACIO_SUP_IMG;
    img->Constraints->MaxHeight = ANCHO_MAX_IMAGEN;
    img->Constraints->MaxWidth = ALTO_MAX_IMAGEN;

    img->AutoSize = true;
    img->Center = true;
    img->Proportional = true;
    img->DragMode = dmAutomatic;

    img->Picture->LoadFromFile(dirTempEscMas + "\\mini_" + ((TImage*)Source)->Hint);

    img->Hint = ((TImage*)Source)->Hint;
    img->ShowHint = true;
    img->Tag = 0;

    img->OnDragDrop = imgSbxDocDragDrop;
    img->OnDragOver = imgSbxDocDragOver;
    img->OnMouseDown = OnImageMouseDown;

    img->Refresh();

    for (int i = (sbxEsc->ControlCount-1); i > -1; i--)
    {
    if (sbxEsc->Controls[i]->Hint == img->Hint)
    {
    TImage* img = (TImage*)sbxEsc->Controls[i];
    try { sbxEsc->RemoveControl(img); } catch (...) { ; }
    try { img->Picture->Bitmap->FreeImage(); } catch (...) { ; }
    try { img->Free(); } catch (...) { ; }
    }
    }
    reubicarImagenesPorDoc(sbxDoc);
    reubicarImagenesPorDoc(sbxEsc);
    }
    else if (((TImage*)Source)->Parent->Name == "sbxDoc")
    { // mueve la imagen de lugar dentro del sbxDoc
    // asigna la posicion del mouse donde fue soltado
    ((TImage*)Source)->Left = X;
    reubicarImagenesPorDoc(sbxDoc);
    }

    lblImgPend->Caption = IntToStr(contarImgEnSbxEsc()) + " Imagenes pendientes";
    }
    __finally
    {
    Application->ProcessMessages();
    }
    }

    //---------------------------------------------------------------------------

    typedef class IdxPosImg : public TObject
    {
    public:
    int IDX;
    int Pos;
    AnsiString Ruta;
    } TIdxPosImg;
    typedef TIdxPosImg *PIdxPosImg;

    //---------------------------------------------------------------------------

    void TfrmEscMas::reubicarImagenesPorDoc(TScrollBox *sbx, TList *olst)
    {
    TObjectList *lst = new TObjectList;
    PIdxPosImg datos;
    int idx, pos=(sbx->HorzScrollBar->Position*(-1))+ESPACIO_ENTRE_IMG; // posicion izquierda inicial
    EstadoImagen est;

    lst->OwnsObjects = true;

    try
    {
    for (int i = 0; i < sbx->ControlCount; i++)
    {
    if (AnsiString(sbx->Controls[i]->ClassName()) == AnsiString("TImage"))
    {
    datos = new TIdxPosImg;
    // anota el indice y la posicion de cada uno
    AnsiString Hint = sbx->Controls[i]->Hint;
    AnsiString Left = sbx->Controls[i]->Left;
    datos->IDX = sbx->Controls[i]->Tag;
    datos->Pos = sbx->Controls[i]->Left;
    datos->Ruta = sbx->Controls[i]->Hint;
    // agrega los datos al TObjectList
    lst->Add(datos);
    datos = NULL;
    }
    }

    lst->Sort(FuncOrdenar); // ordena los componentes en base a la posicion

    for (int i = 0; i < lst->Count; i++) // recorre la TObjectList ordenada
    {
    // para cada componente en el TScrollBox
    for (int j = 0; j < sbx->ControlCount; j++)
    {
    // si el indice del componente de la TObjectList
    // es igual al indice del componente del TScrollBox
    if ((((PIdxPosImg)lst->Items[i])->Ruta == sbx->Controls[j]->Hint) &&
    (AnsiString(sbx->Controls[j]->ClassName()) == AnsiString("TImage")))
    {
    // le asigna la posicion izquierda al componente del TScrollBox
    sbx->Controls[j]->Left = pos;
    for (int k = 0; k < sbx->ControlCount; k++)
    {
    AnsiString hint = sbx->Controls[k]->Hint;
    AnsiString ruta = sbx->Controls[j]->Hint;
    AnsiString clase = AnsiString(sbx->Controls[k]->ClassName());
    if ((sbx->Controls[j]->Hint == sbx->Controls[k]->Hint) &&
    (AnsiString(sbx->Controls[k]->ClassName()) == "TLabel"))
    sbx->Controls[k]->Left = pos;
    }

    // anota la proxima posicion
    pos += ANCHO_MAX_IMAGEN + ESPACIO_ENTRE_IMG;
    }
    }
    }
    }
    __finally
    {
    try { lst->Clear(); } __finally { ; }
    try { lst->Free(); } __finally { ; }
    }
    }

    //---------------------------------------------------------------------------


    Agradezco cualquier ayuda o sugerencia.

    Saludos.

Respuestas

1
08
diciembre
2011
Avatar de Gastón

Gastón 0 puntos

C++ Builder, que épocas!

Cuando salio Windows Vista, fue cuando fui abandonando la programación con C++Builder, asi que mi ayuda probablemente no te sea de mucha utilidad.

Sin embargo, probaste hacer enlace estático al generar tu ejecutable?
Además BDS 2006 es anterior a Windows 7, probablemente no tenga soporte y debas compilar en una versión más moderna.

De todas maneras, contamos si pudiste solucionar el problema.

Saludos.
2
08
diciembre
2011
Avatar de Darío

Darío (iniciador del tema) 0 puntos

Hola,

Si, lo solucioné agregando una llamada al siguiente procedimiento al final de cada for "pesado" o al final de cada procedimiento:


bool TfrmEscMas::liberarMemoria(void)
{
HANDLE HndlPpal;
bool ret=false;

try
{
HndlPpal = OpenProcess(PROCESS_ALL_ACCESS, FALSE, GetCurrentProcessId());
if ( SetProcessWorkingSetSize(HndlPpal, DWORD(-1),DWORD(-1)) )
ret = true;
else
ret = false;
}
__finally
{
CloseHandle(HndlPpal);
}
return ret;
}


El return sobra, por que si no se puede liberar la memoria "sobrante", no hay nada que se pueda hacer, uso el procedimiento sin evaluar el retorno y en XP y superiores anda perfecto, le tomé el tiempo y consume una cantidad considerable de ciclos del procesador, pero en el contexto en que lo uso, no afecta.

Con respecto al C++Builder, esa aplicación tiene varios años, no tengo ganas de pasarla al nuevo IDE, la sigo manteniendo en el viejo pero todavía poderoso 2006.

Ahora estoy usando el XE sobre 7 y mi fanatismo va en aumento, soy de la "vieja escuela" de C++ y VC se sale demasiado del estandard de C++, hice muchos intentos de adaptarme pero abandoné cuando sacó esa especie de referencia o no se como se llama ( ^ ) que nunca la entendí.

VC, para mi gusto, es más "sucio" que Borland (Embarcadero), no tengo líneas de código innecesarias en la pantalla que se presten a la confusión.

¿Por qué abandonaste el Builder? ¿Me contás tu experiencia?

Gracias pro las respuesta, saludos
3
09
diciembre
2011
Avatar de Gastón

Gastón 0 puntos

Recuerdo esa función del api de windows, la use en mi tesis para forzar liberar memoria (es lo mismo que ocurre cuando se minimiza la aplicación, una simple gestión del sistema operativo).

void TfrmMain::LiberarMemoria()

{

if( Win32Platform == VER_PLATFORM_WIN32_NT )

SetProcessWorkingSetSize(GetCurrentProcess(), 0xFFFFFFFF, 0xFFFFFFFF);

}


Lo abandoné porque comencé a dedicarme al desarrollo web, además con el tiempo elegí linux como sistema de trabajo, y pocas veces iniciaba el windows, asi que fui dejandolo de lado.

Pero es verdad lo que decis, C++Builder es una solución elegante para un lenguaje complejo. Coincido con vos con respecto a VC.

Por cierto, voy a aprovechar para compartir una manera que descubrí en C++ Builder para mostrar formularios modales en una sola línea... una particularidad simplemente:


template <typename T>

class TShowModal

{

private:

T *p;

public:

TShowModal(TForm*Owner){

p = new T(Owner);

p->ShowModal();

}

~TShowModal(){

delete p;

}

};


Y luego la usamos asi:

delete new TShowModal<TfrmAbout>(this);


Interesante, no?

Espero que puedas aportar cosas de C++ Builder al club. Se nota que sabes lo que haces.

Saludos.
4
09
diciembre
2011
Avatar de Darío

Darío (iniciador del tema) 0 puntos

Aportaré todo lo que surja de mi trabajo.

Y más que saber, soy un ladrón profesional, desde que Internet estuvo al alcance público, fué mi fuente de conocimientos, todo lo que aplico en mi trabajo es robado de otros que encontraron la solución que estaba buscando.

Muy interesante la clase que propones, otra vez más voy a robar, le voy a hacer un par de modificaciones como crear un macro para la llamada y modificar la clase para que acepte parámetros. el 50% de las veces uso modales para requerir algún dato del usuario (logueo, config, rutas, etc) y sería mucho ahorro de escritura tener una clase o un tipo para no tener código redundante.

No me parece que sea este el hilo para postear algunos códigos, apenas tenga tiempo, postearé un procedimiento y una clase para utilizar un OCR ruso (Cognitive OpenOCR -ex Cuneiform OCR-) con C++Builder que estoy utilizando mucho en esta serie de desarrollos recientes.

Te mantendré al tanto.

¿Hay alguna forma de que te suscribas y/o suscribirme a tus post?

Saludos
5
09
diciembre
2011
Avatar de Gastón

Gastón 0 puntos

No esta implementada la subscripción por usuario, pero agregame como contacto en el modulo de mensajeria.

Saludos.

Tema cerrado por inactividad mayor a 90 días