Debugger Tip lazarus / 12-Debugger ---------------------------------------------------------------------- JimKueneman · 2013-11-02 13:16 I am usually very good at finding bugs in my applications but this one has me stumped on how to even use the debugger to find it.  The app will run in XP all day long but compile and run in OSX it will crash in the first 10 seconds.  When it crashes it has a dialog: QuoteError Project OPstackTest raised exception class 'External: SIGPIPE'. At address 9575E917 It has stopped in the assembly window "GetIntlCAcheData" If I "Show Execution Point" it has stopped here: Code: [Select]{------------------------------------------------------- -----------------------   Method:  TCarbonControlWithEdit.SetText   Params:  S - New text   Returns: If the function succeeds   Sets the text of edit control  --------------------------------------------------------------------- ---------} function TCarbonControlWithEdit.SetText(const S: String): Boolean; ...     if OSError(       SetControlData(ControlRef(Widget), GetEditPart, kControlEditTextCFStringTag,         SizeOf(CFStringRef), @CFString),       Self, SSetText, SSetData) then Exit;  The one thing I have noticed is in this app I am trying to develop a library for a micro controller (using mikroPascal) so I am writing and testing it in Lazarus since it is easier. What this means is that I can't use pascal style strings in the library as that compiler does not support them in a Pascal way, it uses more of a C null terminated approach so I am manipulating all the strings as array of characters.  I am then assigning them into strings to show in the UI for testing.  I have noticed a few crashes over the last few days in that area of the code.  Could the compiler not be handling this correctly on OSX?  How can I tell? Anyone have any hints for what I could do? Thanks, Jim ---------------------------------------------------------------------- Martin_fr · 2013-11-02 13:32 First a none debugger hint Code: [Select]function TCarbonControlWithEdit.SetText(const S: String): Boolean; "const S: string" (can be dangerous, but may be harmless...>) Look up the fpc doc. This prevents internal ref counting. There is one case in which this can backfire (because you may without knowing it, break the documented requirements). IF, and ONLY IF (which I do not know), this code can trigger an event, and IF in this event, you modify the variable that was passed to become "s", then s may be destroyed (because it has no refcount) e.g. Code: [Select]SetText(GlobalVar); // or field in object .... // In Event GlobalVar := 'abc'; When the event returns, and the code is back in SetText, then "s" points to random memory. ------------------- Debugging: I dont know that code, so I cant give you specific tips Check the thread and stack window. The error may be higher up in the stack (in the OS) but since there is no debug info, it will show this line in the editor. Disable inlining, when compiling, recompile the IDE and LCL with -O-1 Set a breakpoint, soit will stop before the exception. That means you can see the data, before it happens. If it is hin a lot, then either: - use none stopping breakpoints and history snapshots - find an outer stackframe, and use a 2nd breakpoint to enable the inner one See breakpointproperties and debug-window history you get there with F1: http://wiki.lazarus.freepascal.org/IDE_Window:_Break_Points#Breakpoint _properties ---------------------------------------------------------------------- JimKueneman · 2013-11-02 15:06 I will give it a try.  Here is a block of code where I have seen problems I can't explain: Code: [Select]   MAX_GRID_CONNECT_LEN = 29; type   TGridConnectString = array[0..MAX_GRID_CONNECT_LEN-1] of char;   PGridConnectString = ^TGridConnectString; // Global variable var   ReceiveGridConnectBuffer: TGridConnectString;                              // Needs to persist between receptions      // ******************************************************************* ********** //  procedure GridConnectToMessage //     Parameters: Message that contains the information in the GridConnect String //                 GridConnectBuffer: array of characters to convert to a Message //     Returns: Pointer to a GridConnectString if a complete one is available, else //              nil.  The caller must use or copy the string before calling the //              function again as the contents will be corrupted after that //     Description: Takes a single character at a time and tries to create a //                  GridConnect string from it in a statemachine // ******************************************************************* ********** function GridConnectDecodeMachine(NextChar: Char): PGridConnectString; begin  Result := nil;  case GridConnectReceiveState of       GRIDCONNECT_STATE_SYNC_START :    ……      GRIDCONNECT_STATE_SYNC_FIND_DATA :         begin            if NextChar = ';'then            begin              if (ReceiveGridConnectBufferIndex + 1) mod 2 = 0 then            // 0 index, add 1 for the actual character count, if not true the result is broken              begin                ReceiveGridConnectBuffer[ReceiveGridConnectBufferIndex] := ';';                ReceiveGridConnectBuffer[ReceiveGridConnectBufferIndex + 1] := #0;                Result := @ReceiveGridConnectBuffer;   <<<<<<<<<<<<<<<<<<<<< nil then     begin       GridConnectStrToIncomingMessageCallback(GridConnectStr);       StringLen := strlen(GridConnectStr^);  <<<<<<<<<  Crashed here at one point       SetLength(Str, StringLen); <<<<<<<<<  or Crashed here at one point       Str := GridConnectStr^; <<<<<<<<<  or Crashed here at one point       if Assigned(Callback) then         Callback('Received: '+GridConnectStr^+LF)     end   end; end;