I have a problem with the background compiler in Delphi7: in my project there is a single line of code that causes the background compiler to stop with an error message so that no CodeCompletion is possible. The normal compiler and the syntax check have no problem with this code and the resulting application is correct.
My question is if there is any way to skip this codeline when the background compilation is performed (e.g. compiler directive).
Example code to reproduce the error:
procedure ProduceKibitzError;
var
v : Variant;
begin
v.End; // This line stops kibitz compiler
end;
This code is placed in a unit "Error.pas" which is used in the main unit.
If you try to call CodeCompletion in the main-unit, it stops with the message "Error.pas could not be compiled" (real message is in german).
Interestingly the error only occurs until the project is compiled or syntax check is performed for the first time.
After compilation the CodeCompletion is working and Delphi has to be restarted to reproduce the error.
Update:
Adding an empty Assembler block with an end label is a solution for the problem.
Here is the changed example code that doesn't stop the background compiler:
procedure ProduceKibitzError;
var
v : Variant;
begin
asm
##END:
end;
v.End;
end;
Many thanks,
Christian
The background compiler does not do procedure body analysis when parsing to get to the position of the cursor. Instead, it uses simple syntax matching (such as begin/end pairs). If simple syntax matching indicates that the final end in the unit has been met, then it exits early.
This is what's happening with your example. The first End token is not escaped by the late binding logic because it's not being parsed by the real expression compiler, and instead it's being read as the end of the procedure. The second end looks like the end of the unit, and the background compiler never sees any further.
Added: You might try adding an empty asm/end block to this routine. It prevents the kibitz compiler skipping procedure analysis. Graphics.pas has an asm/end block with an ##end label, and the compiler handles asm/end blocks specially because of it.
Looks like the background compilation doesn't know what to do with the late binding.
Do you know which COM type library is used to make the call on the object? It would benefit both the compilation and the application's performance if you could export and use the pascal-wrapper unit based on the type library. (See Import Type Library option in the main menu)
Try escaping the token with & ?
so
v.&end;
Related
when i compile my code i can see that some lines are not compiled. Due to this issue some codes does not execute according to the way i want.
i have attached a screenshot of the delphi IDE in the debug mode. Blue dots on the left shows the lines which are compiled and those lines without the blue dots does not function properly or not complied
As can see on the watch window that variable dPcnt value is 0 taxP, srvP, serv_charge does not have a proper value but in the code window can see that the variables have been initialized to 0
Can someone help me out to correct the issue.
It is the optimizer that has removed useless lines like
srvP := 0;
because you don't use that value before you assign a new value on line 770.
I can not see how and where the other variables are used, but I bet the reason is similar.
You can turn optimization on and off with the compiler directive {$O+} or {$O-} {$OPTIMIZATION ON} or {$OPTIMIZATION OFF}. But, please note what help says about it:
Other than for certain debugging situations, you should never have a
need to turn optimizations off. All optimizations performed by the
Delphi compiler are guaranteed not to alter the meaning of a program.
In other words, the compiler performs no "unsafe" optimizations that
require special awareness by the programmer.
If you have compiler hints turned on ({$HINTS ON}) you will see hints in the form H2077 Value assigned to '%s' never used for lines that are 'useless'.
Further info here:
H2077 Value assigned to '%s' never used #Delphi#
I have the following very simple piece of code in Ada which is giving me grief. I trimmed down the code to the minimum to show the problem, the only thing you need to know is that Some_Task is a task type:
task body TB is
Task1 : Some_Task_Ref;
begin
Task1 := new Some_Task;
loop
Put_Line("Main loop is running, whatever...");
delay 5.0;
end loop;
end TB;
From what I understand about task activation in Ada this should be sufficient: I'm creating a task of type "Some_Task" and I don't have to do anything with it, it will execute it's main loop without any intervention. It's not like in java where you have to call a "start" method on the task object.
But if I'm correct, why is the compiler refusing to build, giving me the error:
warning variable "Task1" is assigned but never read
Why should I be forced to "read" Task1? It's a task, all it needs to do is run... what am I missing?
Note: this seems to happen only when I use GNAT in "Gnat mode" (switch -gnatg). Unfortunately I need this mode for some advanced pragmas, but it seems it introduces some "overzelous" checks like the one causing the problem above. How can I deactivate that check?
It's a warning, not an error, and does not prevent building an executable (unless you've turned on "treat warnings as errors"). It's a hint from the compiler that you may have made a mistake in creating a variable that is never used. You can tell the compiler that you don't indend to use Task1 by declaring it as a constant, like this:
Task1 : constant Some_Task_Ref := new Some_Task;
Just to answer this question, since the answer was posted in a comment, which cannot be marked as an answer.
As Holt said (all props to him) this can be fixed by using:
pragma Warnings (Off, Some_Task_Ref) ;
Delphi 7 - if I make a new project and add a line
spacePos := LastDelimiter(' ' , 'spaced out');
it builds.
If I try to use LastDelimiter in my own project it fails.
I started with a stamenet comparing LastDelimter(#$D#$A, myString) and wen that failed I tried with the lien above, which also failed.
I do use SysUtils, but that wasn't even necessary when I created a new project.
If I comment out that line my real project builds just fine. If I uncomment it I get "missing operator or semicolon". Same thing if I move the LastDelimiter to an assignment, even on the fist line of the function which it is in - it really doesn't look like a problem with a previous line.
Any ideas (short of me posting a few klocs)?
Thanks
Perhaps somewhere in your scope is a global variable defined similar to the following:
var
LastDelimiter: Integer;
Check the units used in your project. It should be a global variable declared in the interface section.
Or it could be a constant, declared in the interface section, similar to this:
const
LastDelimiter = 32;
You have learned what a namespace or identifier or "scope collision" is, today. Some unit in your implementation or interface uses clause, also defines LastDelimiter, and since it is the innermost or most recent declaration, it renders that particular identifier in SysUtils invisible until you specify the SysUtils prefix.
When you have namespace collisions, you should qualify the function name with its unit name, and it will then compile for you:
x := SysUtils.LastDelimiter( .... );
For this very reason, some developers who are comfortable with languages like C# and Java are used to always requiring namespaces to be specified, thus their code looks like this:
x := namespace.Thing1.Thing2.GetInput( ... );
Just because we don't always do that in Delphi doesn't mean there aren't times when you SHOULD be doing that.
I am debugging a DirectShow filter I created with the DSPACK code library using Delphi 6 Pro. When a breakpoint I set is hit in one particular unit named BaseClass.pas, and I begin tracing, the Execution Point jumps to strange places in the source code. This usually indicates that the source code being traced does not match the source code that was compiled into one of the packages being used by the Delphi application. Oddly enough it is only the BaseClass unit since I have traced other units belonging to the DSPACK code library and they do not exhibit this problem. I am not using run-time packages.
I scanned my disk and found only one copy of BaseClass.dcu with a modification date equal to the last time I built the program. I have not modified the source for that unit or any other belonging to DSPACK. Since my Filter is part of the main application this indicates that BaseClass.pas would be subject to a dual use situation since it is used to build the DSPACK component package (dpk), and is also referenced by my main application directly via the TBCSource object my Filter descends from. Note, I did try adding the unit PAS file directly to my Project but that didn't fix anything.
I also went back and re-opened each of the DSPACK package files and did a full re-build. None of this helped. Is there something else I can try to get the source synchronized with the compiled image of the BaseClass unit? Or is a different problem altogether and if so, what is it and how can I fix it?
Sometimes this happens when code is copied/pasted from web pages or other sources, and the lines don't end with CR/LF pairs (#13#10 or 0x0D0A, standard for Windows) but end in only LF (#10 or 0x0A, typically the line ending in *nix systems) or CR (#13 or 0x0D, typical with Mac OSX/iOS). The incorrect line terminators confuse the debugger - this has been an issue for the past several Delphi versions.
You can sometimes fix this by opening the source file using a text editor like Notepad, making a small meaningless change (insert and then delete a blank line, for instance), and then save the file.
I had same problem and made a similar utility. Fixed it.
Basically, just this:
procedure adjustCRLF(filename : String);
var
strList : TStringList;
begin
strList := TStringList.Create;
try
strList.LoadFromFile(filename);
strList.Text := AdjustLineBreaks(strList.Text);
strList.SaveToFile(filename);
finally
strList.Free;
end;
end;
There is another way this can happen: if the IDE erroneously opens another source file with the same name (but different, such as an earlier version) then all the debug points will be incorrect, and the debugger will even allow you to step through the incorrect file.
I've seen Delphi 7 do this once.
Make sure that when you rebuild it, that in the compiler options for your project that you have "Debug Information" turned on. In fact, most of the options under Debugging should be set in your project's Compiler options.
Also, if you haven't already, restart Delphi.
I am a long time Delphi dev and in the past I use a third party tool for logging and debugging while developing (called Smart Inspect) however now that I've upgraded to Delphi XE I want to try and use the IDE for debugging.
My question is, given a function like
procedure MyFunction;
var
str : string;
begin
str := 'Foo';
//Debug, show value of str?
str := AnotherFunction(str);
//Debug, show value of str?
end;
how can I debug and get the value of str, without doing stupid things like
showmessage(str);
if there is a video somewhere (or article) then I am more than happy to read.
Is there a way to watch/output the value of variables.
If you want to use the IDE Debugger only, then do the following:
put a breakpoint somewhere
right click on the breakpointr circle and choose "Breakpoint Properties ..."
press "Advanced" button to show more options
uncheck "Break" checkbox
then use "Log message" and "Eval expression" edit boxes to enter trace values
Such messages will be send to "Event Log" debugger pane. Right click on the pane and choose "Properties". There you can filter ("Messages") / hilight ("Colors") the trace messages as you whish.
Well, Delphi XE comes with CodeSite logging, but I get the feeling you're talking about the debugger itself.
If you place a breakpoint in a routine, it will break to the debugger when it hits it. From there, you've got a Local Variables pane and a Watches pane along the left side of the IDE. Local Variables will show the value of all locals, and Watches lets you set up expressions whose value it will keep track of.
You can also get something similar to a watch, but with more detailed information (especially for structured types such as objects) by using Inspect (Alt-F5). Also, the Evaluate/Modify (Ctrl-F7) will allow you to type in expressions and evaluate them. It's not quite as detailed as Inspect, but it gives you a lot more flexibility.
If you familiarize yourself with these tools, you'll find debugging much easier.
1) You can use OutputDebugString Function to output string to debug window
2) You can use CodeSite Express. I recommend video from CodeRage 5 as a starting point for using CodeSite
Other answers are all correct.
My personal favorite technique (same as the answer by da-soft) is to create a breakpoint, that logs a message to the event log, containing a value that I want logged, and does not actually "break" (that is, execution continues without you hitting the Run icon). Then every time that line of code is reached, I get my message, and my values in the log. Since I can go back and read the history, as well as see the current values, I find this more useful than merely using the debugger watch window.
But since Delphi XE includes CodeSite, you can go far beyond what expression evaluation in breakpoints does for you. Code Site however requires that you modify your code to add some logging. But it's much better than a message box.
You can also use OutputDebugString(PChar(s)) to output any string to the debugger. Since this can contain whatever you want, it's a very nice way to debug but not show stuff to the end user.
In many of my applications, I have a special trace buffer, which is circular (that is, it keeps only the last 500 or so lines). When ever I see a problem, not only do I get a stack traceback, I also save that in-memory trace log, so I have some history on what was going on just before my problem.
You can also check out the Log 4 Delphi project.
I prefer debugger hints. After breaking to the debugger move your mouse to the "str" anywhere in your code and you will see its current value. Also you can highlight some statement by a mouse and evaluate it. For example highlight "AnotherFunction(str)" and place your mouse over it.
Nothing wrong with any of the other answers but I just wanted to add these useful functions.
procedure DebugString ( const s : string ) ; overload ;
begin
{$IFDEF DEBUG}
OutputDebugString ( PChar ( s ) ) ;
{$ENDIF}
end ;
procedure DebugString ( const s : string ; args : array of const ) ; overload ;
begin
{$IFDEF DEBUG}
OutputDebugString ( PChar ( Format ( s , args ) ) ) ;
{$ENDIF}
end ;