Solved

Help with release version

Posted on 2004-08-03
20
457 Views
Last Modified: 2013-11-20
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
Comment
Question by:qocarlos
  • 7
  • 5
  • 3
  • +1
20 Comments
 
LVL 16

Expert Comment

by:nonubik
ID: 11701976
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
 
LVL 3

Author Comment

by:qocarlos
ID: 11702068
Thanks nonubik :-)
I had already tried to rebuild all my project, but it didn't make any difference.

Any other idea?

Thanks,
Carlos
0
 
LVL 16

Expert Comment

by:nonubik
ID: 11702126
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
Gigs: Get Your Project Delivered by an Expert

Select from freelancers specializing in everything from database administration to programming, who have proven themselves as experts in their field. Hire the best, collaborate easily, pay securely and get projects done right.

 
LVL 44

Expert Comment

by:AndyAinscow
ID: 11702959
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
 
LVL 55

Expert Comment

by:Jaime Olivares
ID: 11705294
>or try debugging the old way, with messageboxes ;)
That's my prefered method. Also you can increase your warning level at Compiler settings.
0
 
LVL 3

Author Comment

by:qocarlos
ID: 11713604
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
 
LVL 55

Expert Comment

by:Jaime Olivares
ID: 11716982
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
 
LVL 3

Author Comment

by:qocarlos
ID: 11717150
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
 
LVL 55

Expert Comment

by:Jaime Olivares
ID: 11717236
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
 
LVL 3

Author Comment

by:qocarlos
ID: 11717369
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
 
LVL 3

Author Comment

by:qocarlos
ID: 11735503
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
 
LVL 44

Accepted Solution

by:
AndyAinscow earned 250 total points
ID: 11737132
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
 
LVL 3

Author Comment

by:qocarlos
ID: 11742481
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
 
LVL 44

Expert Comment

by:AndyAinscow
ID: 11742504
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
 
LVL 44

Expert Comment

by:AndyAinscow
ID: 11742507
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
 
LVL 3

Author Comment

by:qocarlos
ID: 11743020
The problem is that the client app doesn't know in advance how much memory will allocate the DLL function.
0
 
LVL 44

Expert Comment

by:AndyAinscow
ID: 11743287
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

Gigs: Get Your Project Delivered by an Expert

Select from freelancers specializing in everything from database administration to programming, who have proven themselves as experts in their field. Hire the best, collaborate easily, pay securely and get projects done right.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Introduction: Displaying information on the statusbar.   Continuing from the third article about sudoku.   Open the project in visual studio. Status bar – let’s display the timestamp there.  We need to get the timestamp from the document s…
Introduction: Ownerdraw of the grid button.  A singleton class implentation and usage. Continuing from the fifth article about sudoku.   Open the project in visual studio. Go to the class view – CGridButton should be visible as a class.  R…
This Micro Tutorial hows how you can integrate  Mac OSX to a Windows Active Directory Domain. Apple has made it easy to allow users to bind their macs to a windows domain with relative ease. The following video show how to bind OSX Mavericks to …
This video will show you how to get GIT to work in Eclipse.   It will walk you through how to install the EGit plugin in eclipse and how to checkout an existing repository.

786 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question