Results 1 to 5 of 5

Thread: Out Of memory Error

  1. #1

    Thread Starter
    Hyperactive Member
    Join Date
    Jun 2009
    Posts
    441

    Out Of memory Error

    The code posted here works good, it takes a filename received from command and send it to the previous instance of the application.....

    I am making some changes on it, and i am getting an error "Out Of Memory" ... if i try with the exe, it crashes and close, and if i am on the IDE, and i run with compile, i get an error "Out Of Memory" and the IDE stop responding


    to make it easiar to identify the problem, i removed all the changes i made and kept the only ones causing the error...So here what i am trying to do is instead of sending
    the file name only, i try to send another string wich is the short name of the file

    Attached the original Code and the Edited one...Anyway here are the difference between both :


    The error occurs on the Edited version , at the Function WndProc
    line :
    vb Code:
    1. ReDim bDataArrShort(tData.cbDataShortName - 1)

    As it seems here the value of the tData.cbDataShortName is too big, while when we send it at the sendStringToPrimaryInstance, it's value is the lenght so why here we receive it that big ? maybe if you have an answer to this question this will solve the problem

    here are the original and edited version of the code (the original works good)

    'Original

    vb Code:
    1. Private Type COPYDATASTRUCT
    2.     dwData As Long
    3.     cbData As Long
    4.     lpData As Long
    5.    
    6. End Type


    'Edited

    vb Code:
    1. Private Type COPYDATASTRUCT
    2.     dwData As Long
    3.     cbData As Long
    4.     lpData As Long
    5.  
    6.     cbDataShortName As Long
    7.     lpDataShortName As Long
    8.  
    9. End Type

    'Original

    vb Code:
    1. Public Function sendStringToPrimaryInstance(ByRef szData As String, ByVal hWndSubordinate As Long, ByVal hWndPrimary As Long)
    2.     Dim tData As COPYDATASTRUCT, bDataArr() As Byte, lRet As Long
    3.    
    4.     '--Convert (UNICODE) String to (ANSI) so it faster for Windows to marshall the data across processes
    5.     '--Note that UNICODE support dies here
    6.     bDataArr = StrConv(szData, vbFromUnicode)
    7.    
    8.     '--Setup the COPYDATA Struct
    9.     tData.dwData = hWndSubordinate      '--HWND of Sender
    10.     tData.cbData = UBound(bDataArr) + 1 '--Length Of data
    11.     tData.lpData = VarPtr(bDataArr(0))  '--Pointer to the data
    12.     '--Sendit to the primary instance
    13.     lRet = SendMessage(hWndPrimary, WM_COPYDATA, hWndSubordinate, tData)
    14. End Function

    'Edited

    vb Code:
    1. Public Function sendStringToPrimaryInstance(ByRef szData As String, ByVal hWndSubordinate As Long, ByVal hWndPrimary As Long)
    2.     Dim tData As COPYDATASTRUCT, bDataArr() As Byte, lRet As Long
    3.     Dim bDataArrShort() As Byte
    4.    
    5.     Dim ShortFileName As String
    6.     ShortFileName = GetDirOrShortFileName(szData)
    7.    
    8.     '--Convert (UNICODE) String to (ANSI) so it faster for Windows to marshall the data across processes
    9.     '--Note that UNICODE support dies here
    10.     bDataArr = StrConv(szData, vbFromUnicode)
    11.    
    12.     '--Setup the COPYDATA Struct
    13.     tData.dwData = hWndSubordinate      '--HWND of Sender
    14.     tData.cbData = UBound(bDataArr) + 1 '--Length Of data
    15.     tData.lpData = VarPtr(bDataArr(0))  '--Pointer to the data
    16.     '--Sendit to the primary instance
    17.    
    18.     bDataArrShort = StrConv(ShortFileName, vbFromUnicode)
    19.    
    20.     'UBound(bDataArrShort) + 1  ==> giving the right value wich is the length of the ShortFileName
    21.     tData.cbDataShortName = UBound(bDataArrShort) + 1
    22.     tData.lpDataShortName = VarPtr(bDataArrShort(0))
    23.  
    24.      
    25.     lRet = SendMessage(hWndPrimary, WM_COPYDATA, hWndSubordinate, tData)
    26. End Function


    'Original


    vb Code:
    1. Public Function WndProc(ByVal hWnd As Long, ByVal uiMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
    2.     Dim szFilename As String, bDataArr() As Byte, tData As COPYDATASTRUCT
    3.    
    4.     If (uiMsg = WM_COPYDATA) Then
    5.         '--Grab the COPYDATA struct from the pointer lParam
    6.         Call CopyMemory(tData, ByVal lParam, Len(tData))
    7.         '--Make sure its the required COPYDATA struct by making sure wParam == tData.dwData
    8.         If (tData.dwData = wParam) Then
    9.             '--Create a buffer the size of the data
    10.             ReDim bDataArr(tData.cbData - 1)
    11.             '--Copy data into the buffer
    12.             Call CopyMemory(bDataArr(0), ByVal tData.lpData, tData.cbData)
    13.             '--Create ANSI String from Byte Array
    14.             szFilename = bDataArr
    15.             '--Convert ANSI String into UNICODE so VB understands it
    16.             szFilename = StrConv(szFilename, vbUnicode)
    17.             '--Call the handler and pass it the filename passed
    18.             Call Interaction.CallByName(m_pDisp, FUNC_PROC, VbMethod, szFilename)
    19.             '--We handled the message!
    20.             WndProc = 1
    21.         Else
    22.             '--We dont care
    23.             WndProc = 0
    24.         End If
    25.     Else
    26.         'Default impl.
    27.         WndProc = CallWindowProc(m_lPrevProc, hWnd, uiMsg, wParam, lParam)
    28.     End If
    29. End Function


    'Edited

    vb Code:
    1. Public Function WndProc(ByVal hWnd As Long, ByVal uiMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
    2.     Dim szFilename As String, bDataArr() As Byte, tData As COPYDATASTRUCT
    3.     Dim szFilenameShort As String, bDataArrShort() As Byte
    4.    
    5.    
    6.     If (uiMsg = WM_COPYDATA) Then
    7.         '--Grab the COPYDATA struct from the pointer lParam
    8.         Call CopyMemory(tData, ByVal lParam, Len(tData))
    9.         '--Make sure its the required COPYDATA struct by making sure wParam == tData.dwData
    10.         If (tData.dwData = wParam) Then
    11.             '--Create a buffer the size of the data
    12.             ReDim bDataArr(tData.cbData - 1)
    13.             '--Copy data into the buffer
    14.             Call CopyMemory(bDataArr(0), ByVal tData.lpData, tData.cbData)
    15.             '--Create ANSI String from Byte Array
    16.             szFilename = bDataArr
    17.             '--Convert ANSI String into UNICODE so VB understands it
    18.             szFilename = StrConv(szFilename, vbUnicode)
    19.             '--Call the handler and pass it the filename passed
    20.            
    21.            
    22.              'Added Code
    23.              
    24.              'Here it's getting out of memory !
    25.             ReDim bDataArrShort(tData.cbDataShortName - 1)
    26.              
    27.             Call CopyMemory(bDataArrShort(0), ByVal tData.lpDataShortName, tData.cbDataShortName)
    28.              
    29.             szFilenameShort = bDataArrShort
    30.            
    31.             szFilenameShort = StrConv(szFilenameShort, vbUnicode)
    32.              
    33.              
    34.             Call Interaction.CallByName(m_pDisp, FUNC_PROC, VbMethod, szFilename, szFilenameShort)
    35.             '--We handled the message!
    36.            
    37.        
    38.             WndProc = 1
    39.         Else
    40.             '--We dont care
    41.             WndProc = 0
    42.         End If
    43.     Else
    44.         'Default impl.
    45.         WndProc = CallWindowProc(m_lPrevProc, hWnd, uiMsg, wParam, lParam)
    46.     End If
    47. End Function



    'Original

    vb Code:
    1. Public Function filenameReceived(ByRef szFilename As String)
    2.     Call lstFiles.AddItem(szFilename)
    3. End Function


    'Edited

    vb Code:
    1. Public Function filenameReceived(ByRef szFilename As String, ByRef szFilenameShort As String)
    2.     Call lstFiles.AddItem(szFilename)
    3.     Call lstFiles.AddItem(szFilenameShort)
    4. End Function


    'Edited-New Function
    vb Code:
    1. Public Function GetDirOrShortFileName(ByVal ScanString As String) As String
    2.  
    3. 'This function works well
    4.  
    5.     Dim intPos As Integer
    6.     Dim intPosSave As Integer
    7.    
    8.     intPos = 1
    9.     Do
    10.         intPos = InStr(intPos, ScanString, "\")
    11.         If intPos = 0 Then
    12.             Exit Do
    13.         Else
    14.             intPos = intPos + 1
    15.             intPosSave = intPos - 1
    16.         End If
    17.     Loop
    18.    
    19.      
    20.     GetDirOrShortFileName = Mid(ScanString, intPosSave + 1, Len(ScanString) - intPosSave)
    21.    
    22.  
    23. End Function


    thanks again to all for your support till now , your advides till now helped me a lot to advance in my appliction


    X3 Passing Filenames.zip

    X3 Passing Filenames_Edited.zip
    Last edited by justgreat; Dec 15th, 2009 at 05:57 AM.

  2. #2
    VB-aholic & Lovin' It LaVolpe's Avatar
    Join Date
    Oct 2007
    Location
    Beside Waldo
    Posts
    19,541

    Re: Out Of memory Error

    You cannot modify the COPYDATASTRUCT structure. WM_COPYDATA is a special message that Windows knows about and expects a 12 byte structure, no more no less. When this message is sent, Windows basically reserves space in the targets process' memory space and copies the data pointed to by .lpData, for a total of .cbData bytes.

    I think you have 2 choices.

    1. Send the message twice, once with long file names, once with short file names

    2. Create your own custom UDT/array that contains all the information you need in contiguous bytes, then set the .lpData with the VarPtr() of that UDT/array, and the .cbData will be the total size of the UDT/array. This can be tricky initially, but not extremely difficult. See if this example helps.

    Edited. The reason for the crash is most likely due to your lpDataShortName. That pointer is pointing to memory in the sender's process space not the target's space. So when you try to read it, you will either crash or get garbage.

    WM_COPYDATA ensures that .lpData points to the target's memory space not the sender's. You can test this if curious. I doubt that the value of .lpData sent is the same value when received, assuming sender and target are not in the same process.
    Last edited by LaVolpe; Dec 15th, 2009 at 09:59 AM.
    Insomnia is just a byproduct of, "It can't be done"

    Classics Enthusiast? Here's my 1969 Mustang Mach I Fastback. Her sister '67 Coupe has been adopted

    Newbie? Novice? Bored? Spend a few minutes browsing the FAQ section of the forum.
    Read the HitchHiker's Guide to Getting Help on the Forums.
    Here is the list of TAGs you can use to format your posts
    Here are VB6 Help Files online


    {Alpha Image Control} {Memory Leak FAQ} {Unicode Open/Save Dialog} {Resource Image Viewer/Extractor}
    {VB and DPI Tutorial} {Manifest Creator} {UserControl Button Template} {stdPicture Render Usage}

  3. #3

    Thread Starter
    Hyperactive Member
    Join Date
    Jun 2009
    Posts
    441

    Re: Out Of memory Error

    Quote Originally Posted by LaVolpe View Post
    You cannot modify the COPYDATASTRUCT structure. WM_COPYDATA is a special message that Windows knows about and expects a 12 byte structure, no more no less. When this message is sent, Windows basically reserves space in the targets process' memory space and copies the data pointed to by .lpData, for a total of .cbData bytes.

    I think you have 2 choices.

    1. Send the message twice, once with long file names, once with short file names

    2. Create your own custom UDT/array that contains all the information you need in contiguous bytes, then set the .lpData with the VarPtr() of that UDT/array, and the .cbData will be the total size of the UDT/array. This can be tricky initially, but not extremely difficult. See if this example helps.

    Edited. The reason for the crash is most likely due to your lpDataShortName. That pointer is pointing to memory in the sender's process space not the target's space. So when you try to read it, you will either crash or get garbage.

    WM_COPYDATA ensures that .lpData points to the target's memory space not the sender's. You can test this if curious. I doubt that the value of .lpData sent is the same value when received, assuming sender and target are not in the same process.

    thanks a lot for your answer, i will check the link you gave me, but please
    confirm if i understand your answer, because i got an idea, and want to see if it works or not...
    What i understand is that
    Whenever i want to use the SendMessage, if i send a WM_COPYDATA parameters, i have to send with it a structure of 12 byte ....
    Is it related to SendMessage only or also WndProc won't accept except a 12 byte ?

    To solve my problem i got 2 ideas, please tell me, if it may work

    1) can't i use something like :

    vb Code:
    1. so lRet = SendMessage(hWndPrimary, WM_COPYDATA, tData1, tData)

    where tData1 is another structure of 12 byte that contain the short file name ? So i do the same thing for tdata1 and tdata ?

    2) Am i obliged to use the WM_COPYDATA ? What i understand from the code is that WM_COPYDATA helps to know if the message is sent from me or another application and nothing more (i may be wrong, which means i understand the code wrong)... In this case, can't i use something like :

    vb Code:
    1. CONST WM_MYOWNMESSAGE = "AnyString"
    2.  
    3. Then i use the api RegisterMessage() , to register the WM_MYOWNMESSAGE and to get a unique ID for my custom message
    4.  
    5. then i use something like
    6.  
    7. so lRet = SendMessage(hWndPrimary, WM_MYOWNMESSAGE, hWndSubordinate, tData)
    8. where tData use a custom structure (more than 12 byte like the one
    9. i made that send all i want ?

    I mean that i keep the code as it is, all i change is that i use another message name than WM_COPYDATA ?

  4. #4
    VB-aholic & Lovin' It LaVolpe's Avatar
    Join Date
    Oct 2007
    Location
    Beside Waldo
    Posts
    19,541

    Re: Out Of memory Error

    You have to understand pointers and address space. Each process has its own space, so if App1 passes VarPtr(something) to APP2, the value of VarPtr(something) only applies to APP1. If APP2 tries to use CopyMemory on that value, it will either crash or read garbage, because that pointer is not valid for APP2's memory space and points to something completely different in APP2, if anything at all.

    WM_COPYDATA does stuff behind the scenes that allows memory to be shared between two different processes. WM_COPYDATA's primary purpose is to transfer information between two different windows. This is a bit easier to use than mapped memory files and read/writeprocessmemory apis (which I believe is what WM_CopyData is using behind the scenes).

    Try to understand that your array data exists only in the sender's process memory. WM_COPYDATA ensures it is also copied to the target's process memory. Trying to send your own message and a structure does no good.... Your structure will most likely contain pointers to arrays and/or strings that the target app cannot access; if you try, you will continue to crash.

    Play with the project I linked to, if I remember it correctly (been several years ago), it is a very good one to learn from and the comments allow the code to be followed easily I think.
    Insomnia is just a byproduct of, "It can't be done"

    Classics Enthusiast? Here's my 1969 Mustang Mach I Fastback. Her sister '67 Coupe has been adopted

    Newbie? Novice? Bored? Spend a few minutes browsing the FAQ section of the forum.
    Read the HitchHiker's Guide to Getting Help on the Forums.
    Here is the list of TAGs you can use to format your posts
    Here are VB6 Help Files online


    {Alpha Image Control} {Memory Leak FAQ} {Unicode Open/Save Dialog} {Resource Image Viewer/Extractor}
    {VB and DPI Tutorial} {Manifest Creator} {UserControl Button Template} {stdPicture Render Usage}

  5. #5

    Thread Starter
    Hyperactive Member
    Join Date
    Jun 2009
    Posts
    441

    Re: Out Of memory Error

    Thanks for your valuable reply and explication.

    I am reading the example now to see how can i send an array of strings...


    You know if the user select multiple files multiple instance will send to the primary instance the selected files names...
    Thus, I would like to know how to detect that all files has been transfered and that now i can process them, because i want to collect them all in the list box and once i finish receiving them, i start working on them ... any clue about it ?

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width