Go Premium for a chance to win a PS4. Enter to Win

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 459
  • Last Modified:

Help with release version

Hi all,

I’m facing a very weird problem with the release version of my app. In the debug version everything is fine but in the release version, there are some functions that crash. If I put a breakpoint in some line in the release version (this is a release version with debug info), the compiler complains that “One or more breakpoints are not positioned on valid lines. These breakpoints will be moved to the next valid line”. This is very strange, in the debug version this problem doesn’t happen … Is it possible that that the compiler is “seeing” different code in the release version than in the debug one?  

I would really appreciate your help on this.

Thanks
Carlos
0
qocarlos
Asked:
qocarlos
  • 7
  • 5
  • 3
  • +1
1 Solution
 
nonubikCommented:
Try to "rebuild all" your project.

>the compiler complains that ...

This may appear when the pdb file is not corelated with the source file.
0
 
qocarlosAuthor Commented:
Thanks nonubik :-)
I had already tried to rebuild all my project, but it didn't make any difference.

Any other idea?

Thanks,
Carlos
0
 
nonubikCommented:
a release version with debug info in vc++ 6.0 is not th best way to debug. Maybe if you try to see the code in assembly you van get an idea why the breakpoints could not be set. or try debugging the old way, with messageboxes ;) or outputdebugstring.
your funnctions may crash in releas but not debug because of some uninitialized variables used. Like in debug a BOOL will be initialized to FALSE, while in release it is unpredictable. So may be some pointers, initalized to NULL, while in release not. Check better your code.
0
What does it mean to be "Always On"?

Is your cloud always on? With an Always On cloud you won't have to worry about downtime for maintenance or software application code updates, ensuring that your bottom line isn't affected.

 
AndyAinscowCommented:
When you compile the debug version check  the warnings you get.  As nonubik says you may be using an unitialised variable.  DEBUG mode is firendly in that it sets vars to zero or other safe defaults.  Release mode just uses what was in that memory before with unpredictable results.
I also would recommend a pure release build.  (Maybe delete the release output folder before performing the build).
0
 
Jaime OlivaresCommented:
>or try debugging the old way, with messageboxes ;)
That's my prefered method. Also you can increase your warning level at Compiler settings.
0
 
qocarlosAuthor Commented:
Thanks guys and sorry for the delay in getting back to you.
Your comments are really useful, yet I haven’t been able to fix my problems :-(

The problems arise in a module of the program which loads a DLL dinamically and then runs some functions. For example, consider the following lines:

typedef int (__cdecl*F2)(LPCTSTR, LPCTSTR, int, CString&);      // CLogin
F2 f2 = (F2)GetProcAddress(m_hModule, "CLogin");
if (!f2) return false;
long source = 6;
CString serverVersion;
status = f2(username, password, source, serverVersion);


If serverVersion is not initialized, then the program crashes in release mode when f2 function is executed. However, this only happens when the program is run from within VC IDE; if it's run from the Windows shell, then it works fine. Weird, no?
When the program crashes from VC IDE, this is the error message I get:
"User breakpoint called from code at 0x784613b1"

Moreover, when I place a breakpoint in some specific lines, the compiler says that these lines are not valid. Why is this so? I have rebuilt all the projects from scratch (debug, relase and release-debug)

Thanks,
Carlos
0
 
Jaime OlivaresCommented:
I will assume that f2 returns/writes some string in serverVersion. In this case your code is incorrect

CString serverVersion;
status = f2(username, password, source, serverVersion.GetBuffer(200)); <---- some maximum expected buffer size
serverVersion.ReleaseBuffer();

Possibly debug mode is initializing serverVersion internal char pointer to something, but in Release mode this is not done due to performance issues.

0
 
qocarlosAuthor Commented:
Thanks Jaime.

I tried your suggestion, but I got this error:

"error C2664: 'int (const char *,const char *,int,class CString &)' : cannot convert parameter 4 from 'char *' to 'class CString &'"

0
 
Jaime OlivaresCommented:
Oh, then f2 is expecting a CString & (I figured out it was a char *), then I think your error could be inside f2() function.
0
 
qocarlosAuthor Commented:
well, I didn't write the DLL code myself ... This is the implementation of f2:

int CServer::Login(LPCTSTR lpszUserID, LPCTSTR lpszPassword, long source, CString& serverVersion)
{
      int nRVal = FALSE;
      
      serverVersion.Empty();
      
    if (!m_bConnected){
        //  Return error if not connected
        return ERR_NOTCONNECTED;
    }
      else{
            int  status;
            char cBuf[512];
            wsprintf(cBuf, "%s%c%s", lpszPassword, FS, lpszUserID);
            status = Encrypt(cBuf, m_Sequence);
            m_szTx.Empty();
            sprintf(cBuf, _T ("%s\x1c%s"), lpszPassword, lpszUserID);
            status = Encrypt(cBuf, m_Sequence);
            
            m_szTx.Format("LOGIN_USER\n%d\n1\n%s\n%d\n", m_Sequence, cBuf, source);
        Send(m_szTx);
    }
      
    BufferToFile(m_Receive, "ENUMSVR.RX");
      
    nRVal = DecodeHeader();
      
      if (nRVal > 0){
            TCHAR cBuf[512];
            m_Receive.ReadLine(cBuf, sizeof(cBuf));      
      }
    if (nRVal == 0){
        m_bLoggedIn = TRUE;
            TCHAR cBuf[512];
            
            m_Receive.ReadLine(cBuf, sizeof(cBuf));      
            char* cServerVersion = _tcstok(cBuf, cFieldSeps);      // serverVersion
            if (cServerVersion){
                  serverVersion = cServerVersion;
            }
            char* sstatus = _tcstok(NULL, cFieldSeps);                  // status
            if (sstatus){
                  int status = atoi(sstatus);
            }
    }
   
    return nRVal;
}


Any idea?
0
 
qocarlosAuthor Commented:
Following up with my problems with the DLL, it seems that they have to do
with an incorrect usage of MFC collection classes passed across different
modules.

For example, in the client app I have this:
CString serverVersion;

status = f2(username, password, source, serverVersion);

where f2 is the DLL exported function declared as

typedef int (__cdecl*F2)(LPCTSTR, LPCTSTR, int, CString&);

If I'm correct, if the DLL allocates memory for the CString&
object, when the client app attempts to delete it, it will try to delete it
from the wrong memory address. Is this right? Can't CString objects be used
as parameters in a DLL function? Weirdly enough, if the CString object is
initialized before calling the DLL function, then everything works fine .

I have another function which uses CArrays collections which present the
same problems. For example, I have this function in the DLL:

typedef int (__cdecl*F5)(const int, long*, CArray<CString, CString>&);

If in my client app, a CArray object is instantiated:

CArray<CString, CString> myArray;

When MyArray goes out of scope, the application crashes.
As I haven't written the DLL, is there anything I can do to avoid these
problems?

Thanks for your help,
0
 
AndyAinscowCommented:
Don't pass MFC objects between processes.
Instead of CString you should use LPTSTR and allocate a section of memory.  Equally well for your CArray<CString, CString>.  I think you would have to pass a pointer to a section of memory and other info such as the size of each string.
0
 
qocarlosAuthor Commented:
Thanks.
Does this mean that each dll has its own memory space? They are in the same process. I thought the heap was global.
 I can see how I could return  a char*, allocated in the calling function, but how can I return an array of CString?
0
 
AndyAinscowCommented:
but how can I return an array of CString?

I don't think you can.  I think you would need to supply a pointer to a pice of memory that you expect to be filled for example with 10 strings each 32 chars long.
0
 
AndyAinscowCommented:
ps. A number of API routines function that way - They will inform you of how much space is required (eg with a NULL pointer) and then you assign space and pass a pointer to that space, the API call then fills it.
0
 
qocarlosAuthor Commented:
The problem is that the client app doesn't know in advance how much memory will allocate the DLL function.
0
 
AndyAinscowCommented:
The client allocates the memory, not the dll.  The two stage approach is the client queries the dll as to how much memory is required to perform the operation, assigns the memory and then asks the dll to fill the memory.
0

Featured Post

Keep up with what's happening at Experts Exchange!

Sign up to receive Decoded, a new monthly digest with product updates, feature release info, continuing education opportunities, and more.

  • 7
  • 5
  • 3
  • +1
Tackle projects and never again get stuck behind a technical roadblock.
Join Now