This is a very good question! I will investigate, than you for the idea.
This is a very good question! I will investigate, than you for the idea.
I would be extremely thankful if you kindly take a little more trouble by testing this variation.Yes, it works fine.
This would help me to narrow down the problem
Saludos,
Carlos Gallego
*** FWH-25.12, xHarbour 1.3.1 Build 20241008, Borland C++7.70, PellesC, ADS 11.1***
It is very important for those of us who have chosen xHarbour and Maria_Connect for all our developments.Only for xHarbour 64 bit users.
Testing further.
There are other FWH classes having DESTRUCTOR methods. I did not experience any problem with them. Not also with FWMariaConnection class.
The only problem is with FWMariaRowSet class.
My knowledge is limited.
I would seek the guidance of my seniors to go through the destructor method of rowset class and see what modifications can resolve the conflict, also keeping in view that the problem is only with 64 bits xHarbour.
Saludos,
Carlos Gallego
*** FWH-25.12, xHarbour 1.3.1 Build 20241008, Borland C++7.70, PellesC, ADS 11.1***
I have same problem with xharbour and bcc 64 blits, searching internet i found:
The code you provided uses pointer arithmetic, which can behave differently between 32-bit and 64-bit environments. This is especially relevant when you deal with data structures that involve pointers, as the size of pointers differs between 32-bit and 64-bit systems (4 bytes vs. 8 bytes, respectively).
To make your code compatible with both 32-bit and 64-bit environments, you should address the following points:
In 64-bit mode, the size of pointers is 8 bytes, so pointer arithmetic needs to account for this difference. The line:
cpp
Copy code
( s_pCurrBlock + 1 )
adds 1 to a pointer, which in C/C++ means it advances by the size of the object the pointer points to (based on the type of s_pCurrBlock).
If s_pCurrBlock is a structure or class, ensure that the addition of 1 is appropriately aligned. Pointer arithmetic in C++ is based on the size of the object, so s_pCurrBlock + 1 will skip the size of the object.
For example:
In 32-bit mode: If sizeof(s_pCurrBlock) is 4 bytes, adding 1 will move the pointer by 4 bytes.
In 64-bit mode: If sizeof(s_pCurrBlock) is 8 bytes, adding 1 will move the pointer by 8 bytes.
If you are working with pointer arithmetic in a way that needs to be independent of pointer size, you can cast to uintptr_t. This is a type that is guaranteed to be able to hold a pointer regardless of whether the platform is 32-bit or 64-bit.
hb_vmPushSymbol( pDestructor );
hb_vmPush( pObject ); /* Do NOT Forward!!! */
hb_vmSend( 0 ); <-- CRASH HERE!if( s_AllowDestructors /* && hb_stack_ready */ )if (pDestructor && pObject)
{
聽 聽 hb_vmPushSymbol(pDestructor);
聽 聽 hb_vmPush(pObject); /* Do NOT Forward!!! */
聽 聽 if (!hb_vmSend(0))
聽 聽 {
聽 聽 聽 聽 // Error handling here, log more details if needed
聽 聽 聽 聽 hb_errInternal(HB_EI_ERRUNRECOV, "Error in hb_vmSend on Borland C 64", NULL, NULL);
聽 聽 }
}
else
{
聽 聽 // Log errors if pDestructor or pObject are invalid
聽 聽 hb_errInternal(HB_EI_ERRUNRECOV, "pDestructor or pObject invalid in Borland C 64", NULL, NULL);
}I don't need AI response, I need a real help.
#include <stdint.h> 聽// for uint16_t
void hb_clsFinalize( PHB_ITEM pObject )
{
聽 聽 HB_THREAD_STUB
聽 聽 uint16_t uiClass; 聽// Changed from USHORT to uint16_t
聽 聽 if( HB_IS_OBJECT( pObject ) )
聽 聽 聽 聽 uiClass = pObject->item.asArray.value->uiClass;
聽 聽 else
聽 聽 聽 聽 return;if (pObject == NULL || pObject->item.asArray.value == NULL)
{
聽 聽 // Log or handle the error
聽 聽 return;
}if (pClass->pDestructor && pObject)
{
聽 聽 hb_vmPushSymbol(pClass->pDestructor->pMessage->pSymbol);
聽 聽 hb_vmPush(pObject);
聽 聽 // Add error handling for hb_vmSend
聽 聽 if (!hb_vmSend(0)) 聽// Handle the case where hb_vmSend fails
聽 聽 {
聽 聽 聽 聽 hb_errInternal(HB_EI_ERRUNRECOV, "hb_vmSend failed", NULL, NULL);
聽 聽 聽 聽 return;
聽 聽 }
}
else
{
聽 聽 hb_errInternal(HB_EI_ERRUNRECOV, "Invalid destructor or object", NULL, NULL);
}BOOL bCollecting = hb_gcSetCollecting(TRUE);
PHB_SYMB pDestructor = pClass->pDestructor->pMessage->pSymbol;
// Handle errors during destructor execution
if (pDestructor)
{
聽 聽 hb_vmPushSymbol(pDestructor);
聽 聽 hb_vmPush(pObject);
聽 聽 hb_vmSend(0);
}
hb_gcSetCollecting(bCollecting); 聽// Ensure GC is reset even after errorsPHB_ITEM* pObjectCopy = (PHB_ITEM*)malloc(sizeof(PHB_ITEM));
if (pObjectCopy == NULL)
{
聽 聽 // Handle memory allocation failure
聽 聽 return;
}
memcpy(pObjectCopy, pObject, sizeof(PHB_ITEM));void hb_clsFinalize( PHB_ITEM pObject )
{
聽 聽 HB_THREAD_STUB
聽 聽 uint16_t uiClass;
聽 聽 if (!pObject || !HB_IS_OBJECT(pObject) || !pObject->item.asArray.value) {
聽 聽 聽 聽 // Handle invalid object
聽 聽 聽 聽 return;
聽 聽 }
聽 聽 uiClass = pObject->item.asArray.value->uiClass;
聽 聽 if (uiClass && uiClass <= s_uiClasses)
聽 聽 {
聽 聽 聽 聽 PCLASS pClass = s_pClasses + (uiClass - 1);
聽 聽 聽 聽 if (pClass->pDestructor)
聽 聽 聽 聽 {
聽 聽 聽 聽 聽 聽 if (pClass->uiScope & HB_OO_CLS_DESTRUC_SYMB)
聽 聽 聽 聽 聽 聽 {
聽 聽 聽 聽 聽 聽 聽 聽 assert(hb_stack_ready);
聽 聽 聽 聽 聽 聽 聽 聽 if (s_AllowDestructors)
聽 聽 聽 聽 聽 聽 聽 聽 {
聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 if (hb_stackBaseItem() && hb_stackSelfItem() && strcmp(hb_stackBaseItem()->item.asSymbol.value->szName, "__CLSINSTSUPER"))
聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 {
聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 BOOL bCollecting = hb_gcSetCollecting(TRUE);
聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 PHB_SYMB pDestructor = pClass->pDestructor->pMessage->pSymbol;
聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 if (pDestructor && pObject)
聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 {
聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 hb_vmPushSymbol(pDestructor);
聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 hb_vmPush(pObject);
聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 // Call destructor and handle errors
聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 if (!hb_vmSend(0))
聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 {
聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 hb_errInternal(HB_EI_ERRUNRECOV, "Error in hb_vmSend", NULL, NULL);
聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 }
聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 }
聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 hb_gcSetCollecting(bCollecting);
聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 }
聽 聽 聽 聽 聽 聽 聽 聽 }
聽 聽 聽 聽 聽 聽 聽 聽 else
聽 聽 聽 聽 聽 聽 聽 聽 {
聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 hb_errInternal(HB_EI_ERRUNRECOV, "Destructors disabled!", pClass->szName, NULL);
聽 聽 聽 聽 聽 聽 聽 聽 }
聽 聽 聽 聽 聽 聽 }
聽 聽 聽 聽 }
聽 聽 }
}B_BOOL hb_vm_ready( void )
{
聽 聽/* Verificar si la pila de la m谩quina virtual est谩 inicializada */
聽 聽if( !hb_stack_ready )
聽 聽{
聽 聽 聽 return HB_FALSE;
聽 聽}
聽 聽/* Verificar si el puntero de la m谩quina virtual es v谩lido */
聽 聽if( hb_vm_ptr() == NULL )
聽 聽{
聽 聽 聽 return HB_FALSE;
聽 聽}
聽 聽/* Verificar si el 谩rea de memoria de la m谩quina virtual est谩 inicializada */
聽 聽if( hb_vmMemoryPtr() == NULL )
聽 聽{
聽 聽 聽 return HB_FALSE;
聽 聽}
聽 聽/* Puedes agregar m谩s verificaciones aqu铆 si es necesario */
聽 聽return HB_TRUE;
}
void hb_clsFinalize( PHB_ITEM pObject )
{
聽 聽HB_THREAD_STUB
聽 聽USHORT uiClass;
聽 聽if( HB_IS_OBJECT( pObject ) )
聽 聽 聽 uiClass = pObject->item.asArray.value->uiClass;
聽 聽else
聽 聽 聽 return;
聽 聽if( uiClass && uiClass <= s_uiClasses )
聽 聽{
聽 聽 聽 PCLASS pClass = s_pClasses + ( uiClass - 1 );
聽 聽 聽 if( pClass->pDestructor )
聽 聽 聽 {
聽 聽 聽 聽 聽if( pClass->uiScope & HB_OO_CLS_DESTRUC_SYMB )
聽 聽 聽 聽 聽{
聽 聽 聽 聽 聽 聽 assert( hb_stack_ready );
聽 聽 聽 聽 聽 聽 if( s_AllowDestructors )
聽 聽 聽 聽 聽 聽 {
聽 聽 聽 聽 聽 聽 聽 聽if( HB_IS_SYMBOL( hb_stackBaseItem() ) &&
聽 聽 聽 聽 聽 聽 聽 聽 聽 聽( hb_stackBaseItem()->item.asSymbol.pCargo->uiSuperClass == 0 ||
聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽( USHORT ) hb_stackBaseItem()->item.asSymbol.pCargo->uiSuperClass != uiClass ||
聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽( HB_IS_ARRAY( hb_stackSelfItem() ) &&
聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽hb_stackSelfItem()->item.asArray.value != pObject->item.asArray.value ) ) &&
聽 聽 聽 聽 聽 聽 聽 聽 聽 聽strcmp( hb_stackBaseItem()->item.asSymbol.value->szName, "__CLSINSTSUPER" ) )
聽 聽 聽 聽 聽 聽 聽 聽{
聽 聽 聽 聽 聽 聽 聽 聽 聽 BOOL 聽 聽 bCollecting = hb_gcSetCollecting( TRUE ), bPop = TRUE;
聽 聽 聽 聽 聽 聽 聽 聽 聽 PHB_SYMB pDestructor = pClass->pDestructor->pMessage->pSymbol;
聽 聽 聽 聽 聽 聽 聽 聽 聽 if( HB_IS_ARRAY( &HB_VM_STACK.Return ) &&
聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 HB_VM_STACK.Return.item.asArray.value == pObject->item.asArray.value )
聽 聽 聽 聽 聽 聽 聽 聽 聽 {
聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽bPop = FALSE;
聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽hb_stackPush();
聽 聽 聽 聽 聽 聽 聽 聽 聽 }
聽 聽 聽 聽 聽 聽 聽 聽 聽 else
聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽hb_vmPushState();
聽 聽 聽 聽 聽 聽 聽 聽 聽 hb_vmPushSymbol( pDestructor );
聽 聽 聽 聽 聽 聽 聽 聽 聽 hb_vmPush( pObject );
聽 聽 聽 聽 聽 聽 聽 聽 聽 #ifdef __BORLANDC__
聽 聽 聽 聽 聽 聽 聽 聽 聽 #if __BORLANDC__ > 0x0580 聽// Ajusta este valor seg煤n la versi贸n de Borland C 64-bit
聽 聽 聽 聽 聽 聽 聽 聽 聽 // Alternativa para 64-bit
聽 聽 聽 聽 聽 聽 聽 聽 聽 if (hb_vm_ready()) 聽// Asume que existe una funci贸n como esta
聽 聽 聽 聽 聽 聽 聽 聽 聽 {
聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽// Llama directamente al destructor si es posible
聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽if (pDestructor && pDestructor->value)
聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽{
聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 pDestructor->value(pObject);
聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽}
聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽else
聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽{
聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 // Registra un error o maneja la situaci贸n de otra manera
聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 hb_errInternal(HB_EI_ERRUNRECOV, "Unable to call destructor", NULL, NULL);
聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽}
聽 聽 聽 聽 聽 聽 聽 聽 聽 }
聽 聽 聽 聽 聽 聽 聽 聽 聽 else
聽 聽 聽 聽 聽 聽 聽 聽 聽 {
聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽hb_errInternal(HB_EI_ERRUNRECOV, "Harbour VM not ready", NULL, NULL);
聽 聽 聽 聽 聽 聽 聽 聽 聽 }
聽 聽 聽 聽 聽 聽 聽 聽 聽 #else
聽 聽 聽 聽 聽 聽 聽 聽 聽 hb_vmSend( 0 );
聽 聽 聽 聽 聽 聽 聽 聽 聽 #endif
聽 聽 聽 聽 聽 聽 聽 聽 聽 #else
聽 聽 聽 聽 聽 聽 聽 聽 聽 hb_vmSend( 0 );
聽 聽 聽 聽 聽 聽 聽 聽 聽 #endif
聽 聽 聽 聽 聽 聽 聽 聽 聽 if( bPop )
聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽hb_vmPopState();
聽 聽 聽 聽 聽 聽 聽 聽 聽 else
聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽hb_stackDec();
聽 聽 聽 聽 聽 聽 聽 聽 聽 hb_gcSetCollecting( bCollecting );
聽 聽 聽 聽 聽 聽 聽 聽}
聽 聽 聽 聽 聽 聽 }
聽 聽 聽 聽 聽 聽 else
聽 聽 聽 聽 聽 聽 聽 聽hb_errInternal( HB_EI_ERRUNRECOV, "Destructors disabled! Destructor of class: '%s' can't be executed.", pClass->szName, NULL );
聽 聽 聽 聽 聽}
聽 聽 聽 }
聽 聽}
}Keep in mind that all is working fine using MSC64, so the problem can't be something related to 64 bit handling. And moreover, I can't trap the crash because the call to hb_vmSend( 0 ) crashes che program and never returns. And I cannot use try/catch, we are using C not C++ in this module.
#ifdef MSVC32
#define NXS_MAX_KEYLEN 聽256
static void nxs_crypt(
聽 聽const unsigned char * source, HB_SIZE srclen,
聽 聽const unsigned char * key, HB_SIZE keylen,
聽 聽unsigned char * cipher );
static void nxs_scramble(
聽 聽const unsigned char * source, HB_SIZE srclen,
聽 聽const unsigned char * key, HB_SIZE keylen,
聽 聽unsigned char * cipher );
static void nxs_partial_scramble(
聽 聽const unsigned char * source, unsigned char * cipher,
聽 聽HB_ISIZ * scramble,
聽 聽HB_SIZE len, HB_SIZE keylen );
static void nxs_xorcode(
聽 聽unsigned char * cipher, HB_SIZE cipherlen,
聽 聽const unsigned char * key, HB_SIZE keylen );
static void nxs_xorcyclic(
聽 聽unsigned char * cipher, HB_SIZE cipherlen,
聽 聽const unsigned char * key, HB_SIZE keylen );
static HB_U32 nxs_cyclic_sequence( HB_U32 input );
static void nxs_make_scramble(
聽 聽HB_ISIZ * scramble,
聽 聽const unsigned char * key,
聽 聽HB_SIZE keylen );
#else
void nxs_crypt(
聽 聽const unsigned char *source, HB_SIZE srclen,
聽 聽const unsigned char *key, HB_SIZE keylen,
聽 聽unsigned char *cipher );
#endiferror LNK2019: unresolved external symbol _nxs_crypt referenced in function _HB_FUN_MYSQL_CRYPT