NO

Author Topic: Get the VALUE stored in the address of a void *  (Read 1966 times)

Offline John Z

  • Member
  • *
  • Posts: 840
Get the VALUE stored in the address of a void *
« on: August 20, 2024, 11:39:14 PM »
situation:
ghwndEsc and ghwndTable are HANDLEs and so are void *

When my escape thread runs it course (completes without user pressing quit) a table appears, then escape dialog closes, but for unknown reasons ghwndTable window also closes but only on the i5 LG Gram laptop.
If I just skip closing the escape thread the table continues to be shown and usable....
On other i7 laptops everything is working as expected . . . .

I wanted to see if I'm corrupting the handles by logging them before and after table creation

These lines compile without warning, but causes a crash when run after I added the *(long long int *) part

sprintf(p_msg,"outgoing ghwndTable pointer %p, %lld",ghwndTable,*(long long int *)ghwndTable);
sprintf(p_msg,"outgoing ghwndEsc pointer %p, %lld",ghwndEsc,*(long long int *)ghwndEsc);

How do it correctly get and print the VALUE stored in the address of the void *

Thanks in advance,
John Z

Offline MrBcx

  • Global Moderator
  • Member
  • *****
  • Posts: 186
    • Bcx Basic to C/C++ Translator
Re: Get the VALUE stored in the address of a void *
« Reply #1 on: August 21, 2024, 05:57:08 AM »
John -- ChatGPT says about your post:

To correctly print the value stored at the address of a void * (in this case, the HANDLE) in C, you need to properly cast the void * to the appropriate type before dereferencing it. Since HANDLE is typically defined as void *, and assuming you're trying to print a 64-bit address (as suggested by the use of long long int), you should ensure that you are handling the correct data type.

If your intention is to print the value of the pointer (the address), %p will do that directly. However, if you want to print the value stored at that address, you must ensure that you're casting to the correct type that the HANDLE actually points to. If it's a pointer to a long long int, then your code should be correct. But this seems unusual for a HANDLE, which is more typically used as a pointer to a structure or some other object, not an integer.

If you simply want to print the address and then the value stored at that address assuming it points to a long long int, you would do something like this:

// Print the pointer value (address) and the value stored at that address
sprintf(p_msg, "outgoing ghwndTable pointer %p, value at address %lld", (void *)ghwndTable, *(long long int *)ghwndTable);
sprintf(p_msg, "outgoing ghwndEsc pointer %p, value at address %lld", (void *)ghwndEsc, *(long long int *)ghwndEsc);

However, if you're uncertain about what the HANDLE is actually pointing to, dereferencing it could lead to undefined behavior, including crashes. If you're only interested in printing the pointer itself (the address), you should not dereference it:

// Print the pointer value (address)
sprintf(p_msg, "outgoing ghwndTable pointer %p", (void *)ghwndTable);
sprintf(p_msg, "outgoing ghwndEsc pointer %p", (void *)ghwndEsc);

Handling Potential Crashes:

    Ensure Correct Type: Confirm that ghwndTable and ghwndEsc actually point to long long int values before casting and dereferencing them. If they point to other data types, adjust your code accordingly.

    Check for NULL Pointers: Before dereferencing the pointer, ensure it's not NULL:

    if (ghwndTable != NULL) {
        sprintf(p_msg, "outgoing ghwndTable pointer %p, value at address %lld", (void *)ghwndTable, *(long long int *)ghwndTable);
    }

    Use Appropriate Format Specifiers: Ensure that the format specifier matches the data type you're printing. For pointer addresses, use %p, and for long long int, use %lld.

If the crash persists even with these precautions, consider investigating whether the handle (HANDLE) is being prematurely closed or corrupted elsewhere in your code, particularly on the i5 laptop. Differences in system architecture, drivers, or OS configurations might also be influencing behavior.

Bcx Basic to C/C++ Translator
https://www.BcxBasicCoders.com

Offline John Z

  • Member
  • *
  • Posts: 840
Re: Get the VALUE stored in the address of a void *
« Reply #2 on: August 21, 2024, 07:14:18 AM »
Thanks MrBcx,

Well it seems I've done everything.

There is no need to cast a void pointer to a void pointer though and the address output works correctly when not trying to output the value stored at that address.  The crash only happened when adding printing of the value stored at the address.

The only question I guess is what the HANDLE points to - yes I believe it should contain the address of the procedure it references.  It is 64 bit code so I used long long int .

This code was preceded by NULL checks so that is ok.  I guess I can try different castings.

Appreciate the help,
John

Offline frankie

  • Global Moderator
  • Member
  • *****
  • Posts: 2111
Re: Get the VALUE stored in the address of a void *
« Reply #3 on: August 21, 2024, 09:55:59 AM »
Windows handles aren't addresses mapped in the process space, any trial to dereference the pointer will produce an access violation.
Windows internal structures are system data protect against user access.
The problem you have in your code could be due to incorrect windows management. When you create a window in a thread some data is created locally to the thread (especially anything related to messages translation and dispatch), mixing working threads and User Interface threads could generate troubles.
A good practice is to create an UI thread that manages all windows and dialogs, then create a working thread to execute computation in background.
In your code, if I well understood, you create a thread that in turn creates the dialog which waits for messages from it, while continuing the data processing.
Heavy processing inside a window/dialog procedure is a bad method, while processing the thread local message queue is stopped. This prevent managing of messages and could break the program for timeout. Sending messages to another dialog that can destroy itself potentially can invalidate handles used in the thread that creates it causing crash (access violation). Consider that the creating thread message queue was stopped so couldn't had processed any message relative to the son thread.

Why it works on an I7 processor and not on an I5? Maybe a subtle difference in the virtual memory management that makes dead data still available?

I suggest you to try fixing the code in this way: in your main/UI thread create both a working thread, that process the data and checks for a stop flag, and the dialog that shows the state and expose the terminating button. If the processing completes without user interruption, the working thread send a user message to the dialog, in the UI thread, that will close itself. Else, if the user aborts processing, in UI thread set a flag to stop processing and wait on the working thread handle for its end, then complete the cleanup procedures.
As advanced diagnostic you could start a timeout timer after issuing the stop processing (i.e. using WaitForSingleObject() set the milliseconds to the required timeout), if the working thread doesn't stop after that timeout you can show a failure message and eventually brute-force stop the thread and/or abort the whole program (or take any other action suitable for this case).
« Last Edit: August 21, 2024, 10:38:23 AM by frankie »
"It is better to be hated for what you are than to be loved for what you are not." - Andre Gide

Offline John Z

  • Member
  • *
  • Posts: 840
Re: Get the VALUE stored in the address of a void *
« Reply #4 on: August 21, 2024, 11:02:20 AM »
Thanks frankie,

Helpful -

So maybe I have it backwards here is what I did  When the user requests to view the data in a table a modeless table window is created with a listview table. The listview table parameters are established then a new thread is started to generate a modal escape window which also shows which record is being processed and has a 'stop now' button to cancel/escape the tablebuilder process if desired.  The record number is received by the modal escape window by a sendmessage to the control from the tablebuilder.

The modal escape window signals using a shared global variable which is set to TRUE by the thread indicating to the tablebuilder to stop processing files. The global variable is checked after each record processed.

If the user clicks the 'stop now' button in the modal escape window it stops the tablebuilder processing early and then thread itself close the modal escape window and terminates the thread.

If the processing is allowed to complete then the tablebuilder sends an end message to the modal escape window to close and terminate the thread then the tablebuilder cleans up the global handles i.e. NULL them out.

It has worked well on Windows 7, 10, 11 with various processors from intel and AMD Ryzen, but fails on the LG Gram with an i5. On the LG Gram i5 if I prevent the modal escape window and thread from terminating all is functional, otherwise when the thread terminates the modeless tableview also terminates.

Sooo -  I will look at putting the tablebuilder into a thread rather than the escape window.

Thanks for the HANDLE clarification.  I thought it would point to an address....this was only tried for troubleshooting

John Z

Offline WiiLF23

  • Member
  • *
  • Posts: 85
Re: Get the VALUE stored in the address of a void *
« Reply #5 on: August 24, 2024, 03:46:35 AM »
"...otherwise when the thread terminates the modeless tableview also terminates.", are you creating controls within the thread? This causes problems. What I have had to do is perform checks, create controls on main thread, start a thread with _beginthreadex(), and when thread exits (returns EXIT_SUCCESS), I either keep the control visible or I issue DestroyWindow(hwnd), hwnd = NULL. DestroyWindow should not be called within a thread.

"If the window being destroyed is a child window that does not have the WS_EX_NOPARENTNOTIFY style, a WM_PARENTNOTIFY message is sent to the parent.".

https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-destroywindow

Offline John Z

  • Member
  • *
  • Posts: 840
Re: Get the VALUE stored in the address of a void *
« Reply #6 on: August 24, 2024, 06:19:28 AM »
Thanks WiilF23,

The window that is being closed (without intent) is a modeless window created before the thread.

I am fairly sure frankie's suggestion that I'm somehow corrupting memory somewhere is right.
This 'bug' only shows up on an i5 LG Gram computer and not on an i7 or Ryzen one.

Appreciate the input and I'll double check to be sure.  The escape dialog for the thread is modal and closed with EndDialog, the modeless table window is closed with DestroyWindow(ghwndTable) when the user is done with it, but this is created before the thread. 

My thread implementation is very poor.

John Z

Offline WiiLF23

  • Member
  • *
  • Posts: 85
Re: Get the VALUE stored in the address of a void *
« Reply #7 on: August 28, 2024, 05:48:52 AM »
What exactly is the logic in the application in question that leads to this behavior? I can narrow down from there if you like.

Offline John Z

  • Member
  • *
  • Posts: 840
Re: Get the VALUE stored in the address of a void *
« Reply #8 on: August 28, 2024, 07:35:38 AM »
Thanks WiiLF23!

As it happens it is resolved. It had to do with mainly how I have the thread implemented and with windows 'ghosting'.  The interesting part, if there is any, is that the issue only manifested when run on an LG Gram with the i5 processor.   When run on several different HP i7 systems and a Lenovo Ryzen system it ran fine - no hint of any issue.

Cheers,

John Z

Offline WiiLF23

  • Member
  • *
  • Posts: 85
Re: Get the VALUE stored in the address of a void *
« Reply #9 on: August 28, 2024, 09:32:26 PM »
Partial solution though, no?

Quiz GPT and request “compatible CPU supported code”, and see if it finds the issue. Also reference i5 processors, so it has a starting point to resolution.

Offline John Z

  • Member
  • *
  • Posts: 840
Re: Get the VALUE stored in the address of a void *
« Reply #10 on: August 31, 2024, 02:04:00 AM »
Possibly helpful - maybe ....

Can't at this time though - I'm in a severely restrictive country at the moment, not much is accessible, and VPN mostly blocked too.  In any case a difficult question to explain and posting my poorly implemented thread code would probably get many red herrings.  Frankie has shown me the better method but that is going to be a very major change and take a while to implement. Meanwhile what I've done has it now working on the i5 so far. 

John Z