Visual Basic's On Error Resume Next for c++? - c++

Is there an equivalent to Visual Basic‘s On Error Resume Next for C++ where by if an error occurs code continues to execute without prompting user?
Ideally, would like to catch any exceptions and log them to log.txt file and examined later instead of having exceptions abruptly exiting code.
Visual Basic:
For i = 1 to 100
On Error Resume Next
ReturnedOpcVal[i] = OPC.ReadTag(“Server.Path.Tag” & "TagName_" & Cstr(i))
Next i
C++, I’m thinking this:
Try {
// Try looping through code here
For (i = 1; i <= 100; i++)
{
// Read OPC tags code here
}
}
Catch(…)
{
// log error to file code
}

There's nothing like that. You'd have to write your code to catch and swallow the exception. Something like this:
for(int i=1; i<=100; i++)
{
try
{
// Read OPC tags code here
}
catch(...)
{
// Log something
}
}

This would be the equivalent of the VB code:
for (i = 1; i <= 100; i++)
{
try {
// Read OPC tags code here
catch(…)
{
}
}
}
but you may want to wrap another try catch block round the whole lot as well.

Related

Raycast check crashing UE5

I am trying to check what a multi line trace by channel is hitting by printing every hit object's name to the log, however the engine keeps crashing due to (I assume) a memory error.
I've tried only printing the first object, which works, but since this a multi line trace I would like to check every object that is being hit
Here is my code:
TArray<FHitResult> hits = {};
ECollisionChannel channel(ECC_GameTraceChannel1);
FCollisionQueryParams TraceParams(FName(TEXT("")), false, GetOwner());
GetWorld()->LineTraceMultiByChannel(
OUT hits,
camWorldLocation,
end,
channel,
TraceParams
);
DrawDebugLine(GetWorld(), camWorldLocation, end, FColor::Green, false, 2.0f);
if (!hits.IsEmpty())
{
for (int i = 0; i < sizeof(hits); i++)
{
if (&hits[i] != nullptr) {
if (hits[i].GetActor() != nullptr)
{
UE_LOG(LogTemp, Error, TEXT("Line trace has hit: %s"), *(hits[i].GetActor()->GetName()));
}
}
else
{
break;
}
}
}
sizeof(hits) gives you the size of the C++ object in bytes, not the number of items in the container.
You need to use
for (int i = 0; i < hits.Num(); i++)

Simulating Leach has encounter a problem. Finished with error in omnet++

When running the simulation in omnet++ 5.7 the execution stops suddenly and closes.
This is the code that is being run in omnet
auto simulation = getSimulation();
for (i = 1; i <= simulation->getLastComponentId(); i++) {
int x, y, id;
//scan the simulation module vector
mod = (cModule*)simulation->getModule(i);
if (strcmp(mod->getName(), "node") == 0) {
id = ((Node*)mod)->myId;
x = ((Node*)mod)->xpos;
y = ((Node*)mod)->ypos;
nodePtr[id] = ((Node*)mod);
if (id != this->myId) {
cGate* g;
char gName1[32], gName2[32];
// make new gate here
if (this->hasGate(gName1)) {
this->gate(gName1)->disconnect();
this->deleteGate(gName1);
}
this->addGate(gName1, cGate::OUTPUT, false);
// make new gate at other side
if (mod->hasGate(gName2)) {
mod->gate(gName2)->disconnect();
mod->deleteGate(gName2);
}
mod->addGate(gName2, omnetpp::cGate::INPUT, false);
//CHANNEL
cIdealChannel* ch = NULL;
this->gate(gName1)->connectTo(mod->gate(gName2), ch);
g = this->gate(gName1);
g->setDisplayString(g->getDisplayString());
}
}
}
I assume that the last line g->setDisplayString(g->getDisplayString()); is probably where the code breaks. The code repeats in the for loop with i<= simulation->getLastComponentId(). I'm new to Omnet++. Any suggestion to fix this would be helpful.
Thanks.
Several things in your code may be source of crashing:
getModule(i) may return nullptr, see OMNeT++ Simulation API, so you should check in the code whether result is not nullptr.
gName1 and gName2 are not set!
Other issues:
instead of (Node*)mod use dynamic_cast<Node*)>(mod) and check whether results is not nullptr.
instead of strcmp(mod->getName(), "node") == 0 I advice using mod->isName("node") - see OMNeT++ Simulation API
if you want to obtain a module whose name is "node", you do not need to manually check the name of every module - there is a useful method getModuleByPath() see OMNeT++ Simulation Manual

protobuf SerializeToArray rasie segmentation fault at InternalSerializeWithCachedSizesToArray

To reuse protobuf messages, I firstly allocate it(msg_test,msg_proto), and then send it in an loop(for every loop do something like clear,set,send).
protobuf syntax = "proto3";
Call:
int i=0;
while(true){
SendTestImprove(i++);
usleep(1000*1000);
}
Function:
int SendTestImprove(int count)
{
msg_test->Clear();
msg_test->set_count(count);
msg_proto->Clear();
msg_proto->set_allocated_count(msg_test);
msg_proto->set_tick_count(GetTickCount());
zmq_msg_t zmsg;
int size = msg_proto->ByteSize();
int rc = zmq_msg_init_size(&zmsg,size);
if(rc==0){
try
{
rc = msg_proto->SerializeToArray(zmq_msg_data(&zmsg),size)?0:-1;
}
catch (google::protobuf::FatalException fe)
{
LOGFMTE("PbToZmq error: %s",fe.message().c_str());
}
}
int zsize = zmq_msg_size(&zmsg);
rc = zmq_msg_send(&zmsg,m_pub,0);
zmq_msg_close(&zmsg);
LOGFMTD("zmq_msg_send,size=%d,zsize=%d",rc,zsize);
return 0;
}
The error occurred when i=1, at the line :
rc = msg_proto->SerializeToArray(zmq_msg_data(&zmsg),size)?0:-1;
error info is like:
stopped:segmentation fault,at
InternalWriteMessageNoVirtualToArray
,InternalSerializeWithCachedSizesToArray
Can anyone help?
The likely problem is that you're assigning ownership of msg_test to msg_proto in each iteration of the loop, by calling msg_proto->set_allocated_count(msg_test). The first time you do that it's fine, but then the next time through the loop when you call set_allocated_count() a second time, the proto will delete msg_test and reassign the now dangling pointer. The simplest solution is to avoid calling set_allocated_count() and instead just assign a copy of msg_test, like this:
*msg_proto->mutable_count() = msg_test;

catch error from blank xml file

I am using C++ and I read in and parse an XML file. If the file does not exist it gets created and if it does exist and has correctly formatted data in it there no errors. My problem is when I try to read in a blank XML file (completely blank not even the header) my program crashes as it tries to process the data from the XML file. I need to be able to catch the error before that happen so I can wright the correct settings back to the file or remove the file and make a new one. Is there a way to do this such as checking to see if a node is NULL? And how would I do it?
class XmlDomErrorHandler : public HandlerBase
{
public:
void fatalError(const SAXParseException &exc) {
printf("Fatal parsing error at line %d\n", (int)exc.getLineNumber());
exit(-1);
}
};
void XmlParentNode::refreshAllNodes()
{
m_children.clear();
m_childrernByName.clear();
for(int j =0; j < getInnerParentNode()->getChildNodes()->getLength(); ++j) //crashes here on first pass if xmlfile is empty
{
//code that is never reached
}
XmlDocument::XmlDocument(String name):
XmlParentNode(),
m_pOwner(NULL)
{
if(XmlManager::Get()->initialize())
{
XMLCh* xmlName = XMLString::transcode(StringA(name));
setInnerNode(XmlManager::Get()->getDOMImplementation()->createDocument(NULL, xmlName , NULL));
XMLString::release(&xmlName);
}
}
XmlDocument::XmlDocument(FilePath path):
XmlParentNode(),
m_pOwner(NULL)
{
XMLCh* xmlPath = XMLString::transcode(StringA(path.ToString()));
XercesDOMParser* parser = new XercesDOMParser();
parser->parse(xmlPath);
if(!parser)
{
ErrorHandler* errorHandler = (ErrorHandler*) new XmlDomErrorHandler();
parser->setErrorHandler(errorHandler);
}
DOMDocument* p_Doc= parser->getDocument();
m_pOwner = parser;
XMLString::release(&xmlPath);
if (p_Doc!= NULL)
{
setInnerNode(p_Doc);
refreshAllNodes();
}
}
Sadly I can't stop people for editing the XML file as users need access to it so they can edit settings.
I am new to XML so maybe I'm missing something easy.
I have been using XML Parsing with DOM and a guide I found here
I solved the problem.
I added a check before the for loop that crashed.
if(getInnerParentNode() && getInnerParentNode()->getChildNodes())
{
for(int j =0; j < getInnerParentNode()->getChildNodes()->getLength(); ++j) //was crashing here on first pass if xmlfile is empty
{
//code that was not being reached
}
}

Check user input for errors elegantly

My program waits for user input, and when appropriate, will process it. I need to check the user input to make sure it fulfils certain criteria, and if it doesn't fulfil all of those criteria it will be rejected.
Pseudo-code is something like:
if (fulfills_condition_1)
{
if (fulfills_condition_2)
{
if (fulfills_condition_3)
{
/*process message*/
}
else
cout << error_message_3; //where error_message_1 is a string detailing error
}
else
cout << error_message_2; //where error_message_2 is a string detailing error
}
else
cout << error_message_1; //where error_message_3 is a string detailing error
There is the possibility that the number of these conditions could increase, and I was wondering if there was a neater way to represent this using a switch or something like that instead of lots of cascading if statements.
I know there is the possibility of using
if (fulfills_condition_1 && fulfills_condition_2 && fulfills_condition_3)
/*process message*/
else
error_message; //"this message is not formatted properly"
but this is less useful than the first, and does not say where the issue is.
The conditions can roughly be arranged in increasing importance i.e. checking for condition_1 is more important than checking for condition_3, so the if statements do work - but is there a better way in general for doing this?
How about
if (!fulfills_condition_1) throw BadInput(error_message_1);
if (!fulfills_condition_2) throw BadInput(error_message_2);
if (!fulfills_condition_3) throw BadInput(error_message_3);
/* process message */
Then your exception handler can report the error message, and retry or abort as appropriate.
If what bothers you are the cascading ifs, you could go for one of the following:
Using a boolean:
bool is_valid = true;
string error = "";
if (!condition_one) {
error = "my error";
is_valid = false;
}
if (is_valid && !condition_two) {
...
}
...
if (!is_valid) {
cout << error;
} else {
// Do something with valid input
}
Using exceptions:
try {
if (!condition_one) {
throw runtime_error("my error");
}
if (!condition_two) {
...
}
...
} catch (...) {
// Handle your exception here
}
I suggest you can use "early return" technique:
if (!fulfills_condition_1)
// error msg here.
return;
// fulfills_condition1 holds here.
if (!fulfills_condition_2)
// error msg here.
return;
// Both conditon1 and condition2 hold here.
if (!fulfills_condition_3)
// error msg here.
return.
If this was going to be reused in a few places, I would make a DSL:
Validator inputType1Validator =
Validator.should(fulfill_condition_1, error_message_1)
.and(fulfill_condition_2, error_message_2)
.and(fulfill_condition_3, error_message_3)
inputType1Validator.check(input);