I am using Visual Studio 2019, and I have a piece of code that uses finally block, I have declared a std::string object at the beginning of each Test1(), Test2() and Test3() functions.
I put a break point inside the finally block of each function to see the str variable, and as a result the str variable is reset to Empty in the Test1() and Test2() functions. Only in Test3() function is not reset.
I discovered that str is reset if a return statement is encountered before entering the finally block.
I don't understand what is going on, in the code of my software there are many places where finally block is used like the example above, I need to understand the exact mechanism of it so that I can fix potential bugs in the application.
The following is the code of the Test functions
void Test1()
{
string str = "Test1";
try
{
int* i = NULL;
*i = 0; //This command will raise an exception
return;
}
catch (Exception^ e)
{
return;
}
finally
{
int i = 0; //'str' is rested as empty when entering here
}
}
void Test2()
{
string str = "Test2";
try
{
int* i = NULL;
return;
}
catch (Exception^ e)
{
return;
}
finally
{
int i = 0; //'str' is rested as empty when entering here
}
}
void Test3()
{
string str = "Test3";
try
{
int* i = NULL;
}
catch (Exception^ e)
{
}
finally
{
int i = 0; //'str' is NOT reset to empty when entering here
}
}
Thank you so much!
I debug and double check, found that destructor of local variables will be destroyed when encountering return statement, destructor is called before entering finally block. Only if no return statement is encountered will these destructors be called after the Finally block (regardless of whether an exception occurs or not).
Due to this inconsistency, I could only work around it by not using any finally blocks in the code anymore, replacing it with goto statements or equivalent.
P/S: I am configuring the project with SEH Exceptions (/EHa) option.
Related
I'm new to Swift 2.0 programming (coming from the world of C#), and I'm simply trying to write a function to parse some data from a string and return the result. The function itself works well, but as part of the process, the string functions may throw and error if the input string is improperly formatted and I would like to prepare a catch-all error handler for the function to deal with this. Here's the code for the original function without error handling:
// Parses the numeric value of the BATT return string
private func parseBatteeryLevel(inputStr : String) -> Int {
if inputStr.hasPrefix("BATT") && inputStr.containsString("%") {
let start = inputStr.startIndex.advancedBy(5)
let end = inputStr.characters.indexOf("%")?.advancedBy(-1)
if end != nil {
return Int(inputStr.substringWithRange(start...end!))!
}else{
return 0
}
}else{
printStatus("Return Value Parse Error: \"\(inputStr)\"")
return 0
}
}
As you can see, I did implement a basic sanity check for the strings that could be inputted but it is by no means exaustive. My primary concern is what happens if is passes the checks, but causes the advanceBy() or any of the internal string functions to fail?
I did try to wrap the code in a do-catch block as shown below,
private func parseBatteeryLevel(inputStr : String) -> Int {
if inputStr.hasPrefix("BATT") && inputStr.containsString(" ") {
do {
let start = try inputStr.startIndex.advancedBy(5)
let end = try inputStr.characters.indexOf("%")?.advancedBy(-1)
if end != nil {
return try Int(inputStr.substringWithRange(start...end!))!
}else{
return 0
}
} catch let error as NSError {
printStatus(error.description)
}
}else{
printStatus("Return Value Parse Error: \"\(inputStr)\"")
return 0
}
}
but then I get warnings, next to all the lines inside the do block, marked with the try keyword saying,
No calls to throwing functions occur within 'try' expression
Then, there is another warning next to the catch keyword saying,
'catch' block is unreachable because no errors are thrown in 'do' block
This doesn't make sense because the function clearly crashes the program if an invalid string is entered. This would be painfully simple to deal with in C# but what is the proper way to handle this in Swift 2.0?
So the problem String startIndex and characters functions do not throw and exception that can be caught by the swift do try catch block. See The Swift Programming Language (Swift 2.1) - Error Handling documentation for more info.
So I rewrote the code to deal with parsing of the integer without crashing
func parseBatteeryLevel(inputStr : String) -> Int {
if inputStr.hasPrefix("BATT") && inputStr.containsString("%") {
let start = inputStr.startIndex.advancedBy(5)
let indexOfPercent = inputStr.characters.indexOf("%")
if (indexOfPercent != nil) {
let end = indexOfPercent!.advancedBy(-1)
let batteryLevel = inputStr.substringWithRange(start...end)
if let level = Int(batteryLevel) {
return level
}
}
return 0
} else {
print("Return Value Parse Error: \"\(inputStr)\"")
return 0
}
}
Here is a very strange thing which I don't think should happen:
UnicodeString test = "abc";
try
{
try
{
int a = 123;
return a; // This seems to produce a problem with "test" variable scope
}
catch (Exception &e)
{
// Some exception handler here
}
}
__finally
{
// At this point the "test" variable should still be in scope???
test = "xyz"; // PROBLEM here - test is NULL instead of "abc"! Why?
}
If I remove the return a; in the try-catch block the test variable is still defined. Is there a particular reason why after the above construct the UnicodeString seems to go out of scope? Is it a bug with C++ Builder 2010? I understand that return returns from function but it should still retain variable scope in the __finally block shouldn't it?
I did a bit more analysis and it seams that once you execute return statement all local objects from stack are acting as destroyed. If you try using heap objects instead this won't happen.
UnicodeString *test = new UnicodeString("abc");
try
{
try
{
int a = 123;
return a; // This seems to produce a problem with "test" variable scope
}
catch (Exception &e)
{
// Some exception handler here
}
}
__finally
{
ShowMessage(*test); // "abc"
*test = "xyz";
}
delete test;
Using smart pointers like unique_ptr will again result in loosing an object in __finally since return will initiate it's destruction.
(Remy posted this in comments but did not post an answer here)
When a return statement is hit within a try...finally block, what happens is that any local objects are destroyed (as they would be for any other return) before the __finally block is entered.
So by the time your code gets up to test = "xyz";, test has already been destroyed, causing undefined behaviour.
I guess it is a matter of semantics whether you call this a bug or a design flaw, but either way it is something to bear in mind when using try...finally. My personal advice would be to just not use it at all; the Standard C++ techniques of try...catch and RAII can solve any problem.
I am trying to get to grips with C# having not coded for many years and my previous experience being in ANSI C.
I have read a number of books and searched online but one aspect is evading me and I am hoping someone here can help.
In the past I would declare a function and if there was a possibility of something not happening within the function (i.e. file not found etc.) declare the return to be an integer. I would then return 0 if all was well and a value if not. The value would correspond to where the function failed to execute fully and I could branch accordingly from where I called it.
if(function1())
{
// all my error stuff, maybe a switch/case etc.
}
All the examples I have found in C# seem to avoid this technique and I was hoping to get some understanding here.
Thanks in anticipation.
(I know I am a fossil). :)
Exceptions are the approach you use in C# and similar languages.
It goes like this:
try
{
function();
}
catch(FileNotFoundException e)
{
// File not found
}
catch(UnauthorizedAccessException e)
{
// User doesn't have right to access file
}
// etc...
To make this work, function shouldn't return a status code but instead throw an exception in case of an error.
Please note that the exceptions I illustrated in the code block above are thrown by the framework if you try to access a file and one of those errors is happening. So you don't actually have to do this yourself.
Furthermore, in C# there is no implicit conversion from integral values to bool, i.e. if(function()) is invalid, if function returns an int. You would need to write it like this:
if(function() != 0)
{
// all your error stuff
}
There's nothing to stop you doing this (though there are better ways of handling the errors - exceptions for example).
If you do want to carry on with this approach, the biggest problem you are having is that in C# you can't treat an integer as a boolean so your if test won't compile. What you need is:
if (function1() != 0)
{
}
But to check the value you'd need:
int result = function1();
switch (result)
{
case 1:
// Handle this case
break;
case 2:
// Handle this case
break;
default:
// All OK
break;
}
It would be better to return an enumerated type for each error case so that you don't have magic numbers, but exceptions are the way to go:
try
{
function1();
}
catch (SpecificException1 e1)
{
// Handle this case
}
catch (SpecificException2 e2)
{
// Handle this case
}
What you shouldn't have is a general exception handler:
catch (Exception e)
{
}
This just hides other potential problems.
If you want to follow that pattern of checking return value instead of managing errors, you better use enumarations than plain numbers.
For example:
public enum ResultType
{
Error = 0,
Success,
Waiting
}
public ResultType function()
{
if (still_waiting)
return ResultType.Waiting;
if (error_has_occured)
return ResultType.Error;
return ResultType.Success;
}
public void Main()
{
ResultType result = function();
switch (result)
{
case ResultType.Success:
MessageBox.Show("all is good");
break;
case ResultType.Waiting:
MessageBox.Show("still waiting...");
break;
case ResultType.Error:
MessageBox.Show("error has occurred");
break;
}
}
Behind the scenes, it's still using numbers but you put some meaning to each number.
if(function()==1)
{
}
int function()
{
int returnVal =0;
// do stuff
// if true return returnVal =1 else set returnVal =0;
return returnVal;
}
Hi i am trying to grab a value from my threading but it seem work not so find to me course i found that my code structure are unstable enough..here is my code i name my thread class as "clsThreadCount" and below is my implementation
public volatile bool Grab = false;
public volatile int count = 0;
public void Initialization(int i)
{
count = i;
}
public void Play()
{
Grab = false;
_shouldStop = false;
ThreadTest();
}
public void Stop()
{
_shouldStop = true;
workerThread.Join(1);
workerThread.Abort();
}
private void ThreadTest()
{
workerThread = new Thread(DoWork);
workerThread.Start();
while (!workerThread.IsAlive) ;
}
private void DoWork()
{
try
{
while (!_shouldStop)
{
if (Grab)
{
count++;
Grab = false;
}
}
}
catch (Exception)
{
Play();
}
finally
{
}
}
when my program(main menu) are starting to run i will trigger the initialize function at pass the parameter as 7
ObjThreadCount.Initialization(7); // count = 7
ObjThreadCount.Play(); // the thread are running
ObjThreadCount.Grab = true; // the grab equal to true, count++ are trigger
Thread.Sleep(100); // wait awhile
lblResult.Text = ObjThreadCount.count.ToString(); // sometime i can get count++ result (e.g. 8)
ObjThreadCount.Stop(); // thread stop
sometime my program can able to get a right counting from the thread but sometime are not.
i realize at my while loop implementation there are something are missing..
something like waitone or waitautoevent..can i ignore Thread.Sleep(100) ?? what are the suitable code should i add in the while loop ?
Please help me~ :S
** sorry in the first upload i forgot to write down "volatile" into the variable
thank you..
If C# (and C and java, and probably C++), you need to declare _shouldStop and Grab as volatile.
I'm calling a powershell script from C#. The script is pretty small and is "gps;$host.SetShouldExit(9)", which list process, and then send back an exit code to be captured by the PSHost object.
The problem I have is when the pipeline has been stopped and disposed, the output reader PSHost collection still seems to be written to, and is filling up. So when I try and copy it to my own output object, it craps out with a OutOfMemoryException when I try to iterate over it. Sometimes it will except with a Collection was modified message. Here is the code.
private void ProcessAndExecuteBlock(ScriptBlock Block)
{
Collection<PSObject> PSCollection = new Collection<PSObject>();
Collection<Object> PSErrorCollection = new Collection<Object>();
Boolean Error = false;
int ExitCode=0;
//Send for exection.
ExecuteScript(Block.Script);
// Process the waithandles.
while (PExecutor.PLine.PipelineStateInfo.State == PipelineState.Running)
{
// Wait for either error or data waithandle.
switch (WaitHandle.WaitAny(PExecutor.Hand))
{
// Data
case 0:
Collection<PSObject> data = PExecutor.PLine.Output.NonBlockingRead();
if (data.Count > 0)
{
for (int cnt = 0; cnt <= (data.Count-1); cnt++)
{
PSCollection.Add(data[cnt]);
}
}
// Check to see if the pipeline has been closed.
if (PExecutor.PLine.Output.EndOfPipeline)
{
// Bring back the exit code.
ExitCode = RHost.ExitCode;
}
break;
case 1:
Collection<object> Errordata = PExecutor.PLine.Error.NonBlockingRead();
if (Errordata.Count > 0)
{
Error = true;
for (int count = 0; count <= (Errordata.Count - 1); count++)
{
PSErrorCollection.Add(Errordata[count]);
}
}
break;
}
}
PExecutor.Stop();
// Create the Execution Return block
ExecutionResults ER = new ExecutionResults(Block.RuleGuid,Block.SubRuleGuid, Block.MessageIdentfier);
ER.ExitCode = ExitCode;
// Add in the data results.
lock (ReadSync)
{
if (PSCollection.Count > 0)
{
ER.DataAdd(PSCollection);
}
}
// Add in the error data if any.
if (Error)
{
if (PSErrorCollection.Count > 0)
{
ER.ErrorAdd(PSErrorCollection);
}
else
{
ER.InError = true;
}
}
// We have finished, so enque the block back.
EnQueueOutput(ER);
}
and this is the PipelineExecutor class which setups the pipeline for execution.
public class PipelineExecutor
{
private Pipeline pipeline;
private WaitHandle[] Handles;
public Pipeline PLine
{
get { return pipeline; }
}
public WaitHandle[] Hand
{
get { return Handles; }
}
public PipelineExecutor(Runspace runSpace, string command)
{
pipeline = runSpace.CreatePipeline(command);
Handles = new WaitHandle[2];
Handles[0] = pipeline.Output.WaitHandle;
Handles[1] = pipeline.Error.WaitHandle;
}
public void Start()
{
if (pipeline.PipelineStateInfo.State == PipelineState.NotStarted)
{
pipeline.Input.Close();
pipeline.InvokeAsync();
}
}
public void Stop()
{
pipeline.StopAsync();
}
}
An this is the DataAdd method, where the exception arises.
public void DataAdd(Collection<PSObject> Data)
{
foreach (PSObject Ps in Data)
{
Data.Add(Ps);
}
}
I put a for loop around the Data.Add, and the Collection filled up with 600k+ so feels like the gps command is still running, but why. Any ideas.
Thanks in advance.
Found the problem. Named the resultant collection and the iterator the same, so as it was iterating, it was adding to the collection, and back into the iterator, and so forth. Doh!.