Function execution time is weird - c++

I am trying to evaluate the time difference between looping in a linked list with an operation on each element in these two scenarios:
1) Doing the operation inside a function
2) Doing the operation without a function call in the same place
I was expecting that the variation with the function call with be a lot costlier due to the OS overhead of creating and destroying a stackframe for every call, but the results I got was just the opposite. I could not understand why. Could someone please explain what happened?
This is my program:
// ConsoleApplication4.cpp : Defines the entry point for the console application.
#include "stdafx.h"
#include<iostream>
#include<chrono>
#include<stdlib.h>
#define _CRT_SECURE_NO_WARNINGS
class linked_list_node
{
int a;
public :
std::string var;
bool eval()
{
if (var == "abc")
return true;
return false;
}
linked_list_node() { a = rand() % 100; if (a % 2 == 0) var = "abc"; }
linked_list_node* nxt;
std::string getVar() { return var; }
linked_list_node* getNext()
{
return nxt;
}
};
int _tmain(int argc, _TCHAR* argv[])
{
linked_list_node *head = new linked_list_node();
linked_list_node *trav = head;
int len = 75000;
while (len != 0)
{
linked_list_node *n = new linked_list_node();
trav->nxt = n;
trav = n;
len--;
}
trav->nxt = NULL;
//traversal with function
int length = 0;
trav = head;
std::chrono::steady_clock::time_point begin = std::chrono::steady_clock::now();
while (trav != NULL)
{
length++;
if (trav->eval())
std::cout << "";
trav = trav->nxt;
}
std::chrono::steady_clock::time_point end = std::chrono::steady_clock::now();
std::cout << "Time difference with function == " << std::chrono::duration_cast<std::chrono::nanoseconds>(end - begin).count() << std::endl;
//traversal without function
trav = head;
length = 0;
begin = std::chrono::steady_clock::now();
while (trav != NULL)
{
length++;
if (trav->var =="abc")
std::cout << "";
trav = trav->nxt;
}
end = std::chrono::steady_clock::now();
std::cout << "Time difference without function = " << std::chrono::duration_cast<std::chrono::nanoseconds>(end - begin).count() << std::endl;
getchar();
return 0;
}
These are my results :
Time difference with function == 18100
Time difference without function = 33700000

First difference:
In the function, you are comparing the value of var to"abc".
In the non-function call code, you are comparing the value of var to "ram".
The second difference, the most important one:
In the first case, you are using std::chrono::microseconds.
In the second case, you are using std::chrono::nanoseconds
After I fix those errors, I get consistently lower value for the second number than the first one.

You're measuring time in different units: std::chrono::duration_cast<std::chrono::nanoseconds>(end - begin) vs std::chrono::duration_cast<std::chrono::microseconds>(end - begin).

Related

C++ binary search tree creates segmentation fault

I'm trying to make a program that identifies AVR assembly instructions by opcode, since those are just a list of 1's and 0's I thought it would be a good project to make a binary search tree for.
Sadly I keep getting segmentation faults when trying to search through the tree. As I understand it a seg fault is usually the result of trying to do stuff with a pointer that doesn't point to anything, but since I have a Boolean that I check first that should never happen.
I'm pretty sure it has something to do with the way I use pointers, as I'm not very experienced with those. But I can't seem to figure out what's going wrong.
Below is the code involved (SearchTree is only a global variable in this minimal example, not in the real program.):
The code:
#include <iostream>
void ADD(short &code) {std::cout << code << "\n";}
void LDI(short &code) {std::cout << code << "\n";}
void SBRC(short &code){std::cout << code << "\n";}
struct node
{
void(* instruct)(short &code);
bool hasInst = false;
struct node *zero;
bool hasZero = false;
struct node *one;
bool hasOne = false;
};
node SearchTree;
auto parseOpcode(short code, node *currentRoot)
{
std::cout << "Looking for a: " << ((code >> 15) & 0b01 == 1) << std::endl;
std::cout << "Current node 1: " << (*currentRoot).hasOne << std::endl;
std::cout << "Current node 0: " << (*currentRoot).hasZero << std::endl;
// Return instruction if we've found it.
if ((*currentRoot).hasInst) return (*currentRoot).instruct;
// Case current bit == 1.
else if ((code >> 15) & 0b01 == 1)
{
if ((*currentRoot).hasOne) return parseOpcode((code << 1), (*currentRoot).one);
else throw "this instruction does not exist";
}
// Case current bit == 0.
else {
if ((*currentRoot).hasZero) return parseOpcode((code << 1), (*currentRoot).zero);
else throw "this instruction does not exist";
}
}
void addopcode(void(& instruct)(short &code), int opcode, int codeLength)
{
node *latest;
latest = &SearchTree;
for (int i = 0; i <= codeLength; i++)
{
// Add function pointer to struct if we hit the bottom.
if (i == codeLength)
{
if ((*latest).hasInst == false)
{
(*latest).instruct = &instruct;
(*latest).hasInst = true;
}
}
// Case 1
else if (opcode >> (codeLength - 1 - i) & 0b01)
{
if ((*latest).hasOne)
{
latest = (*latest).one;
}
else{
node newNode;
(*latest).one = &newNode;
(*latest).hasOne = true;
latest = &newNode;
}
}
// Case 0
else {
if ((*latest).hasZero)
{
latest = (*latest).zero;
}
else{
node newNode;
(*latest).zero = &newNode;
(*latest).hasZero = true;
latest = &newNode;
}
}
}
}
int main()
{
addopcode(ADD, 0b000011, 6);
addopcode(LDI, 0b1110, 4);
addopcode(SBRC, 0b1111110, 7);
short firstOpcode = 0b1110000000010011;
void(* instruction)(short &code) = parseOpcode(firstOpcode, &SearchTree);
instruction(firstOpcode);
return 0;
}
EDIT: I still had some #includes at the top of my file that linked to code I didn't put on StackOverflow.
The error happened because I forgot to use the new keyword and was therefor populating my search tree with local variables (which were obviously now longer around by the time I started searching through the tree).
Fixed by using:
node *newNode = new node();
(*latest).one = newNode;
(*latest).hasOne = true;
latest = newNode;
Instead of:
node newNode;
(*latest).one = &newNode;
(*latest).hasOne = true;
latest = &newNode;

C++ Calculating Shortest Path in a Directed Graph

I am tasked with writing a program to maintain the representation of a simple network(weighted directed graph) and compute the best path between two given nodes upon request.
Currently, I am attempting to write a function to compute the simplest between two nodes, however, when attempting to run my program, I get two specific error
Severity Code Description Project File Line Suppression State
Error C3863 array type 'bool [openNode]' is not assignable P 127
and
Severity Code Description Project File Line Suppression State
Error C3863 array type 'int [openNode]' is not assignable
I am unable to debug since these two primary errors are not allowing my program to run. Is there any particular reason for these errors?
Thanks in advance!
This is the node structure defined in Graph.h
struct GraphNode
{
char ID;
std::string name;
int inNodes = 0;
int outNodes = 0;
std::vector<std::pair<GraphNode*, int>> connection;
int connections = 0;
};
And here is the particular code that causes the errors.
#include "Graph.h"
std::vector<GraphNode*> _graph;
int openNode = 0;
//Obligatory constructor
void Graph()
{
}
void shortestPath(char fromNode, char toNode)
{
bool known[openNode];
int distance[openNode];
GraphNode* previous[openNode];
int numbChecked = 0;
for (int i = 0; i < openNode; i++)
{
known[i] = false;
distance[i] = 999999;
previous[i] = nullptr;
}
distance[findNode(fromNode)] = 0;
while (numbChecked < openNode)
{
int smallestUnknown = 9999999;
int locationOfSmall = 0;
for (int i = 0; i < openNode; i++)
{
if (known[i] == false && distance[i] < smallestUnknown)
{
smallestUnknown = distance[i];
locationOfSmall = i;
}
}
if (distance[locationOfSmall] == 0)
{
previous[locationOfSmall] = nullptr;
}
known[locationOfSmall] = true;
numbChecked++;
if (_graph[locationOfSmall]->outNodes > 0)
{
for (int i = 0; i < _graph[locationOfSmall]->outNodes; i++)
{
int newDistanceLocation = findNode(_graph[locationOfSmall]->connection[i].first->ID);
if (known[newDistanceLocation] == false && (distance[locationOfSmall] + _graph[locationOfSmall]->connection[i].second) < distance[newDistanceLocation])
{
distance[newDistanceLocation] = distance[locationOfSmall] + _graph[locationOfSmall]->connection[i].second;
previous[newDistanceLocation] = _graph[locationOfSmall];
}
}
}
}
int destination = findNode(toNode);
std::string output;
std::string charTransfer;
charTransfer = toNode;
output = charTransfer;
while (previous[destination] != nullptr)
{
destination = findNode(previous[destination]->ID);
charTransfer = _graph[destination]->ID;
output = charTransfer + "->" + output;
}
if (_graph[destination]->ID != fromNode)
{
std::cout << "The nodes are not connected." << std::endl;
}
else
{
std::cout << "The path is: " << output << std::endl;
std::cout << "The distance is: " << distance[findNode(toNode)] << std::endl;
}
}
Any change suggestions would be much appreciated!
You have invalid code at the beginning of your shortestPath function:
bool known[openNode];
int distance[openNode];
GraphNode* previous[openNode];
You cannot use variables to create arrays on the stack (which is what you are trying to do there), because the compiler doesn't know the value of openNode at compile time (which is needed to determine the stack size).
Why don't you use a vector, like:
std::vector<bool> known(openNode, false);
std::vector<int> distance(openNode, 999999);
std::vector<GraphNode*> previous(openNode, nullptr);
Using this method makes the for loop below obsolete aswell.

Assigning a struct pointer value from struct vector

#include <iostream>
#include <vector>
using namespace std;
struct Sn {
int SnId;
double spentEnergy;
};
class Node {
//other stuff
private:
vector<Sn> SnRecord;
public:
int getBestSn(Sn* bestSn);
void someFunction();
};
int main()
{
Node nd;
nd.someFunction();
return 0;
}
void Node::someFunction() {
//adding some records in vector just for testing purpose
Sn temp;
temp.SnId = 1; temp.spentEnergy = 5;
SnRecord.push_back(temp);
temp.SnId = 2; temp.spentEnergy = 10;
SnRecord.push_back(temp);
temp.SnId = 2; temp.spentEnergy = 10;
SnRecord.push_back(temp);
cout << "Size of SnReocord is " << SnRecord.size() << endl;
//choosing best sn
Sn *bestSn;
int returnCode = -1;
returnCode = getBestSn(bestSn);
if (returnCode == 0){ //means there is a best SN
cout<< "Found best SN with id = "<< bestSn->SnId << endl;
}
else {
cout <<"NO SN "<< endl;
}
}
int Node::getBestSn(Sn* bestSn) {
int tblSize = (int)SnRecord.size();
if (tblSize == 0)
return -1;
//here i have to assign *bestSn a selected value from vector
//suppose SnRecord[2] is best Sn
cout << "Best sn id is " << SnRecord[2].SnId<< endl; //works OK,
bestSn = &SnRecord[2]; ///// giving me core dump ERROR in my own program but in this simplified version it only gives wrong value
return 0;
}
The output now is:
Size of SnReocord is 3
Best sn id is 2
Found best SN with id = 520004336
In my own program it gives me Core dump error, if I comment this line (and make proper other comments according to function call), the error is gone and simulation executes normally.
I saw examples with arrays, the work if a pointer is assigned a value in this way:
int numbers[5];
int * p;
p = &numbers[2]; //works OK.
but for vectors its not working. Or may be its problem of vector of structures, I'm unable to figure out. Any suggestions?
Ok actually the problem is solved by using suggestion of Sn* & bestSn. But I don't understand this solution. Why can't I pass a pointer variable and it saves a pointer value in it which latter could be accessed?

trouble with linked list values C++

I'm trying to teach myself c++. to do so I made a challenge for myself to write a prime finder app. I've succeeded once in python (to learn python) with a less efficient algorithm. I'm using a doubly linked list to store the primes. currently I'm just trying to run this in a single thread but I made it doubly linked so I could multithread it later on.
anyway, TL;DR the debugger is showing the program getting stuck trying to assign a value to the start link's prm int in the Prime constructor I've done a bunch of searching but I can't figure out what I'm doing wrong. (also note the bings are debug messages)
#include <iostream>
#include <math.h>
#include <cmath>
using namespace std;
using std::cout;
struct PLink{
int prm;
PLink *next;
PLink *prev;
};
class Prime{
public:
PLink *start, *end;
Prime(){
start -> prm = 2;
end -> prm = 3;
start->next = end;
end->next = NULL;
start->prev = NULL;
end->prev = start;
addToEnd(5);
cout <<"cbing" << endl;
}
void insert(int val){
}
void addToEnd(int val){//adds a new prime to the end of the list
PLink *tmp = new PLink;
tmp->prm = val;
tmp->prev = end;
end->next = tmp;
tmp->next = NULL;
tmp = end;
cout << tmp->prm << endl;
cout << "addbing" << endl;
}
bool comp(int pot){ //compares the potential prime against known primes via modulo
int lim = sqrt(pot);
PLink * current = start;
bool check = false;
cout<<"bing " << pot << endl;
while (current->prm < lim && check == false){
if (pot%current->prm == 0) {
check = true;}
current = current->next;
}
return check; //false means its prime true means its not
}
};
int main()
{
Prime primeList;
int cap = 10000;
int beg = 5;
int count = 3;
bool toggle = false;
bool check = false;
cout << "2 \n3 \n5" << endl;
while(count < cap){
beg += 2;
cout << "bing" << endl;
if (toggle){
beg += 2;}
toggle = !toggle;
check = primeList.comp(beg);
if (check == false){
primeList.addToEnd(beg);
count++;
cout << "bing2" << endl;
}
}
};
using namespace std;
using std::cout;
the second using std::cout; is redundant, you can read some documents about C++ name visibility, like this:
http://www.cplusplus.com/doc/tutorial/namespaces/
http://www.tutorialspoint.com/cplusplus/cpp_namespaces.htm
Prime(){
start -> prm = 2;
end -> prm = 3;
start->next = end;
end->next = NULL;
start->prev = NULL;
end->prev = start;
addToEnd(5);
cout <<"cbing" << endl;
}
Note: when you declare a pointer like PLink *start, *end; C++ complier(say 'gcc' or clang) only allocate memory to store that pointer, but not allocate memory to store what your pointer is pointed(here it means your PLink object).
So, you should allocate memory for your PLink object pointed by these two pointers: PLink *start, *end;, that is to say, you have to change the above code to:
Prime(){
start = new PLink(); // use the default constructor generated by C++ complier since you haven't declared one in struct PLink
end = new PLink()
start -> prm = 2;
end -> prm = 3;
start->next = end;
end->next = NULL;
start->prev = NULL;
end->prev = start;
addToEnd(5);
cout <<"cbing" << endl;
}
Well, in order not to cause memory leak and double free the same pointer, you should carefully manipulate the object you created.

getting mergesort to work on linked-list?

Apologies if this is a silly / simple question.. but I'm very lost. I'm having trouble getting this program to run. I've written this program to read in 2 values, the first being a number of elements in a linked list, and the second to be the maximum random value that can be put into each element.
It should then use the merge sort algorithm included to sort and reprint the sorted list.
Ok, so I'm getting errors like:
base operand of `->' has non-pointer type `LIST'
and
request for member `element' in `conductor', which is of non-aggregate type `LIST *'
...(and a few others).
Yes this is for a class.. I've written the program but I'm not sure what I've done wrong here or why I'm getting errors? Any help is appreciated! Thank you
#include <cstdlib>
#include <iostream>
#include <math.h>
#include <sys/time.h>
using namespace std;
typedef struct LIST {
int element;
LIST *next;
};
LIST split(LIST list)
{
LIST pSecondCell;
if (list == NULL)
return NULL;
else if (list.next == NULL)
return NULL;
else {
pSecondCell = list.next;
list.next = pSecondCell.next;
pSecondCell.next = split(pSecondCell->next);
return pSecondCell;
}
}
LIST merge(LIST list1, LIST list2)
{
if (list1 == NULL)
return list2;
else if (list2 == NULL)
return list1;
else if (list1.element <= list2.element) {
list1.next = merge(list1.next, list2);
return list1;
} else {
list2.next = merge(list1, list2.next);
}
}
LIST MergeSort(LIST list)
{
LIST SecondList;
if (list == NULL)
return NULL;
else if (list.next == NULL)
return list;
else {
SecondList = split(list);
return merge(MergeSort(list), MergeSort(SecondList));
}
}
int main(int argCount, char *argVal[])
{
int i, number, max;
struct timeval time1;
struct timeval time2;
//check for correct number of arguments
if (argCount != 3) {
cout << "Incorrect number of arguments" << endl;
return 0;
}
// initialize read in n and max values
number = atoi(argVal[1]);
max = atoi(argVal[2]);
// create list and fill with random numbers
LIST *conductor;
LIST *root = new LIST;
conductor = root;
for (i = 0; i < number; i++) {
conductor.element = rand() % max;
conductor.next = new LIST;
conductor = conductor.next;
}
// time how long it takes to sort array using mergeSort
gettimeofday(&time1, NULL);
mergeSort(root);
gettimeofday(&time2, NULL);
// print name, sorted array, and running time
cout << "Heather Wilson" << endl;
conductor = root;
for (i = 0; i < number - 2; i++) {
cout << conductor.element << ", ";
conductor = conductor.next;
}
double micro1 = time1.tv_sec * 1000000 + time1.tv_usec;
double micro2 = time2.tv_sec * 1000000 + time2.tv_usec;
cout << conductor.element << endl;
cout << "Running time: " << micro2 - micro1 << " microseconds" << endl;
return 0;
}
For base operand of->' has non-pointer type LIST'
Replace the -> with a .. You want to access a member of a local LIST, not a member of a pointed at object.
request for memberelement' in conductor', which is of non-aggregate type LIST *
This is the opposite. Replace the . with a ->. You want to access a member of the pointed at LIST, not a member of the pointer.
For clarification, I didn't read the code. There's too much of it. But those are the usual ways to address those specific errors. parapura seems to have actually read the code.
First: you should never have let the code grow this big with so many errors. You should start small and simple, then build up, testing at every stage, and never add to code that doesn't work.
Here's a stripped-down beginning of your code, with some bugs fixed:
#include <iostream>
using namespace std;
typedef struct LIST{
int element;
LIST *next;
};
int main(){
int i, number, max;
number = 5;
max = 100;
// create list and fill with random numbers
LIST *conductor;
LIST *root = new LIST;
conductor = root;
for(i=0; i<number; i++){
conductor->element = rand() % max;
cout << "element " << i << " is " << conductor->element << endl;
conductor->next = new LIST;
conductor = conductor->next;
}
conductor = root; // Forgot this, didn't you!
for(i=0; i<number-2;i++){
cout << conductor->element << ", ";
conductor = conductor->next;
}
return 0;
}
Take a look at this, verify that it works, make sure you understand the changes I made, then you can take a crack at implementing your split, merge and MergeSort functions and the I/O (one at a time, and testing at every stage, naturally).
I think all the places you are passing
LIST merge ( LIST list1 , LIST list2 )
it should be
LIST* merge ( LIST* list1 , LIST* list2 )