NO

Author Topic: Is my Pelles C Debugger skipping lines?  (Read 21893 times)

Hydronium

  • Guest
Re: Is my Pelles C Debugger skipping lines?
« Reply #15 on: November 23, 2012, 12:55:36 AM »
This way you can avoid that 64-bit crash:
InitGL() must be before ShowWindow() because ShowWindow() send WM_SIZE message.
If you have WS_VISIBLE flag in windows style, then InitGL() have to be before CreateWindow().
That glViewport() is called from ResizeGLScene().

See my previous post. I moved it and the same error occurred. Also, I don't use WS_VISIBLE, so that part is not important. Thanks for pointing it out though.

I don't error-check GetProcAddress() because it has worked so far, and I can see the value of the PFN when debugging if I need to see if it is null (and I did this extensively while trying to implement it). I have no way of knowing what the true value of it should be, beyond it's name and an offset into the DLL.

Very simply ... how do you know it worked?
 
If your LoadLibrary() call fails --the library is missing, the paths are wrong, your disk is crapping out, etc.-- all those GetProcAddress() calls are going to fail, returning nulls... and your function is going to return just like everything went perfectly.  What impact do you think that would have on the rest of your program?
 
"It's always worked so far" does not cut it when the code is "mission critical"...
 
Quote
According to this and this I couldn't see any way of verifying the exact address of any particular function. Either it returns NULL or some address, which may or may not be correct. The wgl ones in particular vary from context to context, which makes it more difficult (unless I misinterpreted what the MSDN said).

You are looking for total failure...
 
Code: [Select]

if (! LoadLibrary(...))
  ReportFatalError();
 
if (! GetProcAddress(...  ))
  ReportFatalError();

When it cannot fetch the address of the function (for any reason) it returns NULL... signalling failure.  If it returns an address, it will be the correct address.
 
 
Also I am in agreement with the others who are pointing out flaws in your sequence of events... You really have to go at this incrementally... as already suggested, get the window showing up, resizing and closing, first then add the GL stuff in bits and pieces, testing as you go.

You're right, I wouldn't know how it worked. Generally, the fact that my window did what I wanted and I saw squares when I drew them was good enough for me, so I didn't bother. I've since fixed that.

I started another project as of yesterday; see attached. Is this more along the lines of what you'd expect a WinAPI window creation to look like?

Also, is it correct that, even though CreateWindowEx sends the WM_CREATE message, it isn't handled by WndProc until the while(!done) loop is reached and the message is dispatched? Or is the operating system sending the message directly to the WndProc in this case? MSDN page for WM_CREATE says nothing, and the MSDN page for CreateWindowEx says it "sends WM_NCCREATE, WM_NCCALCSIZE, and WM_CREATE messages to the window being created. " Is it using "send" in the sense that it is skipping the queue, or that it is just sending a message which is handled by the queue?

Edit #1: I also tried making a manifest file (also attached), mainly for the new program that I started. Is that properly formatted/correct for the issue you mentioned, aardvajk? I couldn't install the hotfix because the .msu that the support page sent me quit after telling me my system is unsupported, so I wrote up a manifest like the links you provided said to. I'm going to see what happens if I use it with my old code.
« Last Edit: November 23, 2012, 01:01:40 AM by Hydronium »

CommonTater

  • Guest
Re: Is my Pelles C Debugger skipping lines?
« Reply #16 on: November 23, 2012, 02:51:14 AM »
You're right, I wouldn't know how it worked.

That's not what I asked... How would you know it worked *at all* if your program is constantly crashing? 
How do you know that's not the cause?
 
Quote
Generally, the fact that my window did what I wanted and I saw squares when I drew them was good enough for me, so I didn't bother. I've since fixed that.

Actually no, you haven't... that whole big string of nulltester = lines actually only tests the last call to GetProcAddress()... You could have multiple failures and it would report true as long as the last one worked. Similarly it would report false if the last one fails, even if all the rest worked.
 
Quote
Also, is it correct that, even though CreateWindowEx sends the WM_CREATE message, it isn't handled by WndProc until the while(!done) loop is reached and the message is dispatched? Or is the operating system sending the message directly to the WndProc in this case? MSDN page for WM_CREATE says nothing, and the MSDN page for CreateWindowEx says it "sends WM_NCCREATE, WM_NCCALCSIZE, and WM_CREATE messages to the window being created. " Is it using "send" in the sense that it is skipping the queue, or that it is just sending a message which is handled by the queue?

WM_CREATE et all use SendMessage() which calls your window proc directly.
 
Quote
Edit #1: I also tried making a manifest file

Here's a much better general purpose manifest you can use... just edit the program name and description parts and you're in business... Also you can just as easily import the manfest into your program's resources so the two never get separated.
 
Code: [Select]

 <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
  <assemblyIdentity type="win32"
                    name="ProgramNameWithoutExtension"
                    version="1.0.0.0"
                    processorArchitecture="*" />
  <description>
    My Program Description goes here   
  </description>
  <dependency>
    <dependentAssembly>
      <assemblyIdentity type="win32"
                        name="Microsoft.Windows.Common-Controls"
                        version="6.0.0.0"
                        processorArchitecture="*"
                        publicKeyToken="6595b64144ccf1df"
                        language="*" />
    </dependentAssembly>
  </dependency>
  <trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
    <security>
      <requestedPrivileges>
        <requestedExecutionLevel  level="asInvoker"
                                  uiAccess="false" />
      </requestedPrivileges>
    </security>
  </trustInfo>
</assembly>

Also, to give you the idea about what I was saying for WinMain :
This is typical of my programs, and it's the entire function...
Code: [Select]
// cold entry point
INT APIENTRY wWinMain (HINSTANCE Inst, HINSTANCE Prev, LPWSTR CmdLine, INT Show)
  {
    gInst = Inst;  // global instance handle
 
#ifndef _WIN64
    CheckWindowsVersion();   
#endif
 
    InitCommonControls();
 
     {
      WNDCLASS wc = {0};
      wc.style        = CS_CLASSDC;
      wc.lpszClassName= EZPRO_CLASS;
      wc.hCursor      = LoadCursor(NULL,IDC_ARROW);
      wc.hIcon        = LoadIcon(Inst,L"APPICON");
      wc.lpszMenuName = L"MAINMENU";
      wc.hInstance    = Inst;
      wc.lpfnWndProc  = MainTosser;
 
      if(! RegisterClass(&wc))
        {
          MessageBox(NULL,L"Class registration failed.", NULL, MB_ICONSTOP | MB_OK);
          return (GetLastError());   
        }
    }   
 
    // create the main window
    gMainWind = CreateWindowEx(WS_EX_CONTROLPARENT, EZPRO_CLASS, L"Easy Project",
                                WS_OVERLAPPEDWINDOW,
                                CW_USEDEFAULT,CW_USEDEFAULT,200,200,
                                NULL, NULL, Inst, NULL);
    if(!gMainWind)
      {
        MessageBox(NULL,L"Main window creation failed.", NULL, MB_ICONSTOP | MB_OK);
        return (GetLastError());   
      }
     
    // dispatch messages
    {
      MSG msg;
      while(GetMessage(&msg, NULL, 0, 0))
        {
          TranslateMessage(&msg);
          DispatchMessage(&msg);
        }
 
      return (DWORD) msg.wParam;   
    }
 
    // if all else fails
    return 0;
  }

All the initialization occurs in WM_CREATE...
 
And FWIW... except in rare circumstances you actually want GetMessage() to block so your system can enter a low CPU usage idle state.  If the loop is running around in circles full speed you can cause CPU races that will overheat some systems.
 
 

Hydronium

  • Guest
Re: Is my Pelles C Debugger skipping lines?
« Reply #17 on: November 23, 2012, 03:28:48 AM »
That's not what I asked... How would you know it worked *at all* if your program is constantly crashing? 
How do you know that's not the cause?
Meant to say if* it worked, and my program was functional with that code before this issue, so I knew that it worked at the the time at which it did. Right now I have no idea what the issue is, and have started over.
Quote

Actually no, you haven't... that whole big string of nulltester = lines actually only tests the last call to GetProcAddress()... You could have multiple failures and it would report true as long as the last one worked. Similarly it would report false if the last one fails, even if all the rest worked.
Yea, just realized that before coming back. Not sure how to do it without a line of if statements, but I'll probably have to do that.

Quote

WM_CREATE et all use SendMessage() which calls your window proc directly.

Could you clarify "et all"? Aren't only a few messages sent directly, based on the function that is sending them? Else why would I bother with a Translate/Dispatch loop?

Quote
All the initialization occurs in WM_CREATE...
 
And FWIW... except in rare circumstances you actually want GetMessage() to block so your system can enter a low CPU usage idle state.  If the loop is running around in circles full speed you can cause CPU races that will overheat some systems.

Your code only differs from mine in that I check for full screen, and use a RECT struct for window dimensions. I don't see your WndProc nor how your WM_CREATE message is handled.

I use PeekMessage because I will be rendering to the screen and am not interesting in waiting for messages to allow my program to continue.

CommonTater

  • Guest
Re: Is my Pelles C Debugger skipping lines?
« Reply #18 on: November 23, 2012, 06:51:36 AM »
Yea, just realized that before coming back. Not sure how to do it without a line of if statements, but I'll probably have to do that.

Code: [Select]
SetLastError(0);
 
// getprocaddress lines go here
 
if(GetLastError())
  ScreamBloodyMurder();

The only way for GetLastError() to return 0 is if there were no errors.

Quote

Quote
WM_CREATE et all use SendMessage() which calls your window proc directly.

Could you clarify "et all"?

"And others"
 
Quote

Aren't only a few messages sent directly, based on the function that is sending them? Else why would I bother with a Translate/Dispatch loop?

Yep ... and WM_CREATE is one of them.  It has to be sent that way... your message loop won't be running yet.
 
 
Quote

Quote
All the initialization occurs in WM_CREATE...
 
And FWIW... except in rare circumstances you actually want GetMessage() to block so your system can enter a low CPU usage idle state.  If the loop is running around in circles full speed you can cause CPU races that will overheat some systems.

Your code only differs from mine in that I check for full screen, and use a RECT struct for window dimensions. I don't see your WndProc nor how your WM_CREATE message is handled.
From the same program....
Code: [Select]
// resize the main window
INT DoWmSize(HWND Win, INT Width, INT Height)
  {
    RECT tbr;     // toolbar rectangle
 
    // resize the toolbar
    SendMessage(gToolBar, TB_AUTOSIZE, 0, 0);
 
    // adjust for tool bar rectangle
    GetWindowRect(gToolBar, &tbr);
    tbr.bottom -= tbr.top;
   
    // now the treeview
    MoveWindow(gTreeView, 0, tbr.bottom, Width, Height - tbr.bottom, 1);
    return 0;
  }
 
 
// Initialize the application
INT DoWmCreate(HWND Win, LPCREATESTRUCT Data)
  {
    RECT cr;            // client rectangle
    HIMAGELIST hti;     // treview images 
    HIMAGELIST hbi;     // button images 

    // button initializers
    const TBBUTTON  btnu[4] =     
            {
              {0, 1000, TBSTATE_ENABLED, BTNS_BUTTON},
              {1, 1001, TBSTATE_ENABLED, BTNS_BUTTON},
              {2, 1002, TBSTATE_ENABLED, BTNS_BUTTON},
              {3, 1003, TBSTATE_ENABLED, BTNS_BUTTON},
            };
 
    // visual display elements
    hti = ImageList_LoadImage(gInst,L"TREE",16,0,RGB(255,255,255),
                        IMAGE_BITMAP, LR_CREATEDIBSECTION | LR_LOADTRANSPARENT);
    hbi = ImageList_LoadImage(gInst,L"TOOL",16,0,RGB(255,255,255),
                        IMAGE_BITMAP, LR_CREATEDIBSECTION | LR_LOADTRANSPARENT);

    // toolbar
    gToolBar = CreateWindow(TOOLBARCLASSNAME, NULL,
                        WS_VISIBLE | WS_CHILD |
                        TBSTYLE_WRAPABLE | TBSTYLE_FLAT,
                        0, 0, 0, 0,
                        Win, (HMENU) 1000, Data->hInstance, NULL);
   
    SendMessage(gToolBar,TB_SETBITMAPSIZE,0,MAKELONG(16,16));   
    SendMessage(gToolBar,TB_SETBUTTONSIZE,0,MAKELONG(20,20));
    SendMessage(gToolBar,TB_SETIMAGELIST,0,(LPARAM)hbi);
    SendMessage(gToolBar,TB_BUTTONSTRUCTSIZE,sizeof(TBBUTTON),0);
    SendMessage(gToolBar,TB_ADDBUTTONS,4,(LPARAM)&btnu);
 
     // treeview
    gTreeView = CreateWindow(WC_TREEVIEW, NULL,
                        WS_VISIBLE | WS_CHILD |
                        TVS_HASLINES |
                        TVS_EDITLABELS | TVS_INFOTIP | TVS_HASBUTTONS | TVS_LINESATROOT,
                        0, 0, 0, 0,
                        Win, (HMENU) 1010, Data->hInstance, NULL);
    TreeView_SetImageList(gTreeView, hti, TVSIL_NORMAL);

     // organize children
    GetClientRect(Win, &cr);
    SendMessage(Win,WM_SIZE, SIZE_RESTORED, MAKELPARAM(cr.right, cr.bottom));
 
    // and lets see it
    ShowWindow(Win, SW_SHOWNORMAL);
    return 0;
  }
 
// main message loop
LRESULT CALLBACK MainTosser(HWND Win, UINT Msg, WPARAM Wparm, LPARAM Lparm)
  {
    switch(Msg)
      {
        case WM_CREATE :
          return DoWmCreate(Win, (LPCREATESTRUCT) Lparm);
        case WM_SIZE :
          return DoWmSize(Win, LOWORD(Lparm), HIWORD(Lparm));
        case WM_CLOSE :
          DestroyWindow(Win);
          return 0;
        case WM_DESTROY :
          PostQuitMessage(0);
          return 0; 
 
// a ton of stuff removed

        default :   
          return DefWindowProc(Win, Msg, Wparm, Lparm);
      }
  }

Small differences sometimes make all the difference.  The reason for doing it that way is that in WM_CREATE the window actually exists, has a valid DC and can accept children but it is static and not yet on the screen.  This is the perfect time to do things like resizing, adding controls, rendering images, etc.  That is, in fact why the message is sent when it is sent.
 
Quote
I use PeekMessage because I will be rendering to the screen and am not interesting in waiting for messages to allow my program to continue.

Screen renders usually take about 2 to 3 milliseconds (on anything newer than P3). The vertical frame rate is about 16 milliseconds for most LCD monitors and TV sets... you could set an 8 millisecond timer to check if any rendering needs to be done and still render at twice the vertical frame rate without racing the CPU.  Alternatively you could render in a separate thread that is governed by timed events (CreateEvent(), WaitForSingleObject() etc) and let the main thread block unless there is user input... Once again an 8 millisecond interval will let you render at twice the frame rate without playing silly tricks on your message loop.
 
More than one clever programmer has cooked a supply or cpu trying to mess with methods that are by design intended to use as little CPU time as possible.
 

Hydronium

  • Guest
Re: Is my Pelles C Debugger skipping lines?
« Reply #19 on: November 24, 2012, 02:23:51 PM »
Thanks for GetLastError(), totally forgot about that WRT WinAPI calls.

More than one clever programmer has cooked a supply or cpu trying to mess with methods that are by design intended to use as little CPU time as possible.

Yea, I forgot to say that I would implement a timer and wait to reduce it. I've implemented it now.

Thanks for your help, I think I'm good from here on out but we'll see.

Hydronium

  • Guest
Re: Is my Pelles C Debugger skipping lines?
« Reply #20 on: November 24, 2012, 03:26:41 PM »
Alright, nevermind.

Tried implementing my GetBitmap function after my loadlibrary and function pointer setup. Stepping into the same line as last time causes the same strange issue: the Pelles C debugger treats the next "Step Into" as "Go/Debug" and loses focus to the window. Now, it doesn't tell me anything either through the debugger or normal execution that would let me know that the calls are not being reached. I added sprintf and MessageBox lines so that I could get the error code (which the debugger couldn't show me because it wouldn't step to the next line) and it's 0, which probably means it is OK. It's interesting that by adding these two lines the debugger allows me to "step into" normally! But why is it skipping lines otherwise?

This might make it clearer, if my explanation was confusing:

Case #1:
Code: [Select]
      fclose(bmFile); <------------------------------------BREAKPOINT HERE.

      glActiveTexture(GL_TEXTURE0); <------------------------------------STEP INTO HERE
      enumGLError = glGetError(); <------------------------------------Another step into DOES NOT get here! It just runs and gives focus to my window.
      glGenTextures(1, &texture);
      enumGLError = glGetError();
      glBindTexture(GL_TEXTURE_2D, texture);
      enumGLError = glGetError();

      glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
      glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

      glTexImage2D(GL_TEXTURE_2D,   /*Type of texture*/
                   0,               /*Level of Detail number*/
                   GL_RGB,          /*Internal format*/
                   bmWidthPx,       /*Width in texels(pixels?)*/
                   bmHeightPx,      /*Height in texels(pixels?)*/
                   0,               /*Border. Must be 0 (probably only for 2D)*/
                   GL_BGR,          /*Format, of the data the texture will be created from*/
                   GL_UNSIGNED_BYTE,/*Data type of the pixel data*/
                   bmBuffer);       /*Pointer to the image data to create the texture from*/

      //glBindTexture(GL_TEXTURE_2D, 0);

      free(bmBuffer);

Case #2:
Code: [Select]
      fclose(bmFile); <------------------------------------BREAKPOINT HERE.

      char msgData[100];
      glActiveTexture(GL_TEXTURE0); <------------------------------------STEP INTO HERE.
      enumGLError = glGetError(); <------------------------------------STEP INTO works here!
      sprintf(msgData, "%i", enumGLError); <------------------------------------And here!
      MessageBox(NULL, msgData, NULL, MB_OK | MB_ICONINFORMATION); <------------------------------------And for everything after! Returns 0 for error, which leads me to believe it is OK, but the debugger just ignores everything after glActiveTexture.
      glGenTextures(1, &texture);
      enumGLError = glGetError();
      glBindTexture(GL_TEXTURE_2D, texture);
      enumGLError = glGetError();

      glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
      glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

      glTexImage2D(GL_TEXTURE_2D,   /*Type of texture*/
                   0,               /*Level of Detail number*/
                   GL_RGB,          /*Internal format*/
                   bmWidthPx,       /*Width in texels(pixels?)*/
                   bmHeightPx,      /*Height in texels(pixels?)*/
                   0,               /*Border. Must be 0 (probably only for 2D)*/
                   GL_BGR,          /*Format, of the data the texture will be created from*/
                   GL_UNSIGNED_BYTE,/*Data type of the pixel data*/
                   bmBuffer);       /*Pointer to the image data to create the texture from*/

      //glBindTexture(GL_TEXTURE_2D, 0);

      free(bmBuffer);
glActiveTexture comes from atio6axx.dll. That is the only thing about it that I think could be related to the way Pelles C is handling this. I checked my registry key related to the Windows 7 compatibility shim, etc, and saw nothing. So that is not occurring here. It looks like this is error free, but the debugger is acting weird. Is it just the way that Pelles C handles returns from certain externally loaded libraries?

Edit: I suppose my real question is: Does this behaviour of the Pelles C debugger mask a real issue with my code?

Attached is code, 64bit.
« Last Edit: November 24, 2012, 03:32:05 PM by Hydronium »

CommonTater

  • Guest
Re: Is my Pelles C Debugger skipping lines?
« Reply #21 on: November 24, 2012, 04:58:16 PM »
Ok, downloaded your latest sample...
 
After correcting the error handling in your LoadLibrary() call...
Code: [Select]

    HINSTANCE hGLLIB = NULL;
    SetLastError(0);                    // Explicitly set last error to 0
   
     hGLLIB = LoadLibrary("opengl32.dll");
     if(hGLLIB != NULL)                            // explicitly test the library handle
        {
          // library imports
          glActiveTexture    = (PFNGLACTIVETEXTUREPROC)wglGetProcAddress("glActiveTexture");
          glAttachShader     = (PFNGLATTACHSHADERPROC)wglGetProcAddress("glAttachShader");
          ...
        }

     // check and report error
     if (GetLastError())
      {
         char err[32] = {0};
 
         sprintf(err,"Fatal Error #%d", GetLastError());
         MessageBox (NULL, "Failed to import one or more procedures from OpenGl32.dll",
                                  err, MB_ICONSTOP | MB_OK);
         exit (GetLastError());
      }
I stepped throught the program line by line...

The result of your  GetProcAddress calls is attached...
As you can see, about half of them failed.
 
It is as I said all along ... How did you know it worked?
« Last Edit: November 24, 2012, 05:50:44 PM by CommonTater »

Hydronium

  • Guest
Re: Is my Pelles C Debugger skipping lines?
« Reply #22 on: November 24, 2012, 06:21:05 PM »
Because I have the required DLL, and you do not. See attached.

Is it possible that this is a machine specific issue? wgLGetProcAddress gets it from the appropriate driver dll, so I have no control (that I know of) over whether or not you're able to get the same functions.

EDIT:

I just tested that the glActiveTexture calls were appropriately setting the right enumerator value, using multiple glActiveTexture calls to set different texture locations and glGetIntegerv(GL_ACTIVE_TEXTURE, &testval); to return the changed value. I checked the enum definitions in glcorearb.h. They are correct, and the function is getting called. So my code is doing what I want it to (possibly things I don't, but I have not been notified by the debugger or a crash about it) so my question is still: why does the Pelles C debugger skip lines after this particular (style of) call? Is there a hidden issue it is detecting and not telling me about? Or is it "just how it is"?
« Last Edit: November 24, 2012, 06:50:04 PM by Hydronium »

Offline Bitbeisser

  • Global Moderator
  • Member
  • *****
  • Posts: 772
Re: Is my Pelles C Debugger skipping lines?
« Reply #23 on: November 24, 2012, 07:48:19 PM »
...so my question is still: why does the Pelles C debugger skip lines after this particular (style of) call? Is there a hidden issue it is detecting and not telling me about? Or is it "just how it is"?
Sorry for possibly stating the obvious, but if you set the breakpoint at a function call to something contained in a (3rd party provided) DLL, you can of course not "step into", as that DLL is very likely not compiled with any debug info to begin with...  ???

Ralf

Hydronium

  • Guest
Re: Is my Pelles C Debugger skipping lines?
« Reply #24 on: November 24, 2012, 08:13:32 PM »
That's a good point, I hadn't even thought of that. Although, why would the debugger not pick up on the rest of the code when the external DLL calls return? I have a feeling you're correct, and to be honest I have not tried Step Over which may continue the debugging properly (maybe, I'm not sure).

So is the debugger getting lost, can't regain it's "footing" in my local code, and then just "running" instead of stepping?

Thanks for the input.

Edit:

"Stepping over" exhibits the same behaviour. I still think you're correct, but I feel like it wouldn't make sense to suddenly stop debugging after coming across something that many C programs probably do (call things from an external DLL, that was manually loaded). Even though the function pointer is the same style as a regular GetProcAddress function pointer, might the wglGetProcAddress function have anything to do with it? This odd behaviour forces me to double break-point all my code, so that the debugger halts after coming out of one of these DLL's. Output code such as MessageBox seem to halt it as well though. I'm confused. :|
« Last Edit: November 24, 2012, 08:18:36 PM by Hydronium »

CommonTater

  • Guest
Re: Is my Pelles C Debugger skipping lines?
« Reply #25 on: November 24, 2012, 08:56:36 PM »
I'm confused.

You're not alone... It's now obvious I can't test your software here, so I'm pretty much out of the game, except for general advice.  You should definately set up error checks the way I showed you in my last message, any external process like that needes to be checked... especially one that is crucial to making your program run.  (Had you done that, you could have saved me about 9 ot 10 hours messing with code that is destined not to work on my system!)

I do find myself wondering exactly what you expect from the debugger. I use it quite routinely with my own projects and so far it seems to track my program's behaviour correctly in that when an if() is true it skips the else part, follows loops for the required number of repititions, tracks into and out of subroutines according to my program's flow, etc.  And, yes, if my program hangs, so does the debugger... If it loses track of your program then it's most likely because your program is no longer in control.
 
I'd like to be more help... but I just don't see how...
 
 

Hydronium

  • Guest
Re: Is my Pelles C Debugger skipping lines?
« Reply #26 on: November 24, 2012, 10:44:23 PM »
Well, I would expect to be able to step through my code, without the debugger deciding to do something else for some indiscernible reason. If I click "Step Into", I expect to step into the next line. If I hit "Step Into" and it pretends to be "Go/Debug" in certain instances only instead, then that doesn't make sense.

It seems related to what Bitbeisser said, but I can Step through Win API calls and other external calls which are definitely not local without this odd behaviour. My code still seems to work, the debugger just refuses to play nice....but won't tell me why not. For now it doesn't appear to be a problem. We'll see as I reach the point I was at with my older code.

Thanks for the assistance so far. Hopefully no actual problems end up appearing.

CommonTater

  • Guest
Re: Is my Pelles C Debugger skipping lines?
« Reply #27 on: November 24, 2012, 11:16:33 PM »
If I click "Step Into", I expect to step into the next line. If I hit "Step Into" and it pretends to be "Go/Debug" in certain instances only instead, then that doesn't make sense.

One important distinction... it does not step to the next line... When you click "Step Into" or "Step Over" it executes the current line then relocates itself to the next point where your program has control. 

For example...
Code: [Select]
int x = 10;
 
if (x == 10)
  puts("Yes it's ten");
else
  puts("Sorry not ten");
 
puts("I'm here now")
It's going to execute the if statement, locate on the first puts, then jump completely over the else clase and land on the last puts.  It follows your program's execution... not your source code's line numbers.  If your program does something silly like overwriting the return address of a function (and it happens with buffer overflows and such) it's going to follow your program as it descends into the bowels of undefined behaviour.

Quote
It seems related to what Bitbeisser said, but I can Step through Win API calls and other external calls which are definitely not local without this odd behaviour.

Because in assembler mode it follows instructions... the steps are smaller.  If you step into a JMP or CALL it's going to follow that too...
 
Quote
My code still seems to work, the debugger just refuses to play nice....but won't tell me why not. For now it doesn't appear to be a problem. We'll see as I reach the point I was at with my older code.

Thanks for the assistance so far. Hopefully no actual problems end up appearing.

You can pretty much take to the bank that if the debugger is misbehaving there are problems in the program...
 
One distinct possibility the compiler won't catch, is if your code is trashing the stack.  FWIW, the stack in most windows programs is limited to about a megabyte, once that's exceeded, just about any darned strange thing can happen since you will be playing in unallocated memory.  Check your variables, see how much stuff you're piling up on the stack... you might be surprised.  (FWIW... an array of 1000 x 1000 chars can trash a stack quite easily... which is why I malloc() most everything bigger than a pointer these days.)
 
Another possibility (although far less likely) is that some debuggers have problems with uninitialized variables...
Code: [Select]
// wrong
WIN32_FIND_DATA fd;
 
// correct
WIN32_FIND_DATA fd = {0};
Any variable that is declared inside a function has to be manually initialized. C does not intialize them for you.
 
Well, anyway .... good luck with this, I'm thinking you got a bit of a row to hoe here...
 
 
 
 
 

Offline Bitbeisser

  • Global Moderator
  • Member
  • *****
  • Posts: 772
Re: Is my Pelles C Debugger skipping lines?
« Reply #28 on: November 25, 2012, 04:09:57 AM »
Well, I would expect to be able to step through my code, without the debugger deciding to do something else for some indiscernible reason. If I click "Step Into", I expect to step into the next line.
Sorry, that is not correct.

"Step into" means that you want to follow the function call and that's where I guess your program goes south. As mentioned, if that function call is in a 3rd party DLL (or any object file linked in that is compiled without debug info for that matter!), the debugger will perform a "Step over", which will move the debugger to the next source code line that is reachable, after returning from that function call.
Quote
If I hit "Step Into" and it pretends to be "Go/Debug" in certain instances only instead, then that doesn't make sense.
Well, you are a bit unclear as to what exactly is happening and unfortunately, those people that are trying to help you out here (including me) can't properly reproduce this problem without that specific DLL...  :-\

My best guess is that this is somehow related to the DLL call itself or something in the parameters in the called function that is messing with the call stack that prevents the debugger from behaving nicely...

What I would test in your case, place a breakpoint right in front and right behind the function call in question. If the call to the DLL returns properly, the second on should stop the program again.
I don't use Pelle's C as much as CommonTater for example is, but in those cases where I have traced code (no DLLs involved though), I have never seen such behavior as you are describing...

Ralf

CommonTater

  • Guest
Re: Is my Pelles C Debugger skipping lines?
« Reply #29 on: November 25, 2012, 04:54:55 AM »
Ralf speaks the truth ...  :D  (Hi Ralf)

Looking at the part of your code where you open your file, there is a far simpler way of doing that...

1) Use GetFileAttributesEx() to get the file size and attributes.
2) Use calloc() or malloc() to create the buffer, with a few extra bytes for good measure.
3) Open the file using the winapi  CreateFile() call
4) Read the whole thing into memory in one go with ReadFile()
5) Close the file with FileClose()

Now you have an array of bytes and can access the entire thing using simple notation like ...  bmp[offset] without any seeks pre-reading or backtracking...
 
Think what happens if the file size in the header is wrong...

Even more clever you can design a struct for the header information and overlay that on the buffer to access the variables directly from the buffer... none of this Read4Bytes crap.
« Last Edit: November 25, 2012, 05:01:29 AM by CommonTater »