Why these two functions does not behave the same - c++

For empty vector Fun1 returns 0. Function Fun2, which should be equivalent to Fun1 (only one small change, see below), crashes with error vector subscript out of range. Any ideas why is that?
Code run in Visual Studio 2017
int Fun1(vector<int> service_times) {
sort(service_times.begin(), service_times.end());
int sum = 0;
int sumi = 0;
int st = service_times.size() - 1;//condition stired in variable
for (int i = 0; i < st; i++)
{
sumi += service_times[i];
sum = sum + sumi;
}
return sum;
}
int Fun2(vector<int> service_times) {
sort(service_times.begin(), service_times.end());
int sum = 0;
int sumi = 0;
for (int i = 0; i < (service_times.size() - 1); i++)//condition
//directly written
{
sumi += service_times[i];
sum = sum + sumi;
}
return sum;
}

Since service_times is an empty vector, service_times.size() ought to return 0, no?
No. It returns size_t(0), which is an unsigned type. Therefore, service_times.size() - 1 is a unsigned - signed operation, where the signed value (1) is "promoted" to unsigned type. Therefore, 0 - 1 is actually numeric_limits<size_t>::max().
In the first function, you saved it by storing it again in an int variable: it becomes -1 again. Therefore, i < st is i < -1, which worked incidentally. However, in the second function, i < st is actually i < <some ultra big value>, which, LOL.

Related

C++ dynamic array allocation and strange use of memset

I recently ran into this code in C++:
int m=5;
int n=4;
int *realfoo = new int[m+n+3];
int *foo;
foo = realfoo + n + 1;
memset(realfoo, -1, (m+n+2)*sizeof(int));
Only the variable "foo" is used in the rest of the code, "realfoo" is never used (just freed at the very end).
I can't understand what that means.
What kind of operation is foo = realfoo + n + 1;? How is it possible to assign an array plus an int?
The memset sets every value of "realfoo" to -1. How does this affect "foo"?
EDIT
Since many have asked for the entire code. Here it is:
int Wu_Alg(char *A, char *B, int m, int n)
{
int *realfp = new int[m+n+3];
int *fp, p, delta;
fp = realfp + n + 1;
memset(realfp, -1, (m+n+2)*sizeof(int));
delta = n - m;
p = -1;
while(fp[delta] != n){
p=p+1;
for(int k = -p; k <= delta-1; k++){
fp[k]=snake(A, B, m, n, k, Max(fp[k-1]+1, fp[k+1]));
}
for(int k = delta+p; k >= delta+1; k--){
fp[k] = snake(A, B, m, n, k, Max(fp[k-1]+1, fp[k+1]));
}
fp[delta] = snake(A, B, m, n, delta, Max(fp[delta-1]+1, fp[delta+1]));
}
delete [] realfp;
return delta+2*p;
}
int snake(char *A, char *B, int m, int n, int k, int j)
{
int i=j-k;
while(i < m && j < n && A[i+1] == B[j+1]){
i++;
j++;
}
return j;
}
Source: http://par.cse.nsysu.edu.tw/~lcs/Wu%20Algorithm.php
The algorithm is: https://publications.mpi-cbg.de/Wu_1990_6334.pdf
This:
foo = realfoo + n + 1;
Assigns foo to point to element n + 1 of realfoo. Using array indexing / pointer arithmetic equivalency, it's the same as:
foo = &realfoo[n + 1];
memset is not setting the value to -1. It is used to every byte to -1
You should create a loop to iterate every element to assign correctly.
for(size_t i= 0; i< m+n+3; i++){
realfoo[i] = -1;
}
What kind of operation is foo = realfoo + n + 1;?
This is an assignment operation. The left hand operand, the variable foo, is assigned a new value. The right hand operand realfoo + n + 1 provides that value.
How is it possible to assign an array plus an int?
Because the array decays to a pointer.
The memset sets every value of "realfoo" to -1.
Not quite. All except the last value is set. The last one is left uninitialised.
Note that technically each byte is set to -1. If the system uses one's complement representation of signed integers, then the value of the resulting integer will not be -1 (it would be -16'843'009 assuming a 32 bit integer and 8 bit byte).
How does this affect "foo"?
foo itself is not affected. But foo points to an object that is affected.
Bonus advice: The example program leaks memory. I recommend avoiding owning bare pointers.

Pass arrays between VB.NET and VC++

I've a written a function to calculate the correlation matrix for variables (risks) held in a flat file structure. I.e. RiskID | Year | Amount
I have written the function because the library routines that I can find necessitate a matrix input. That is, RiskID as 2nd dimension and year as the 1st dimension - with amounts as actual array values. The matrix needs to be complete, in that zero values must be included also and hence for sparsely populated non zero data - this leads to wasted iterations which can be bypassed. The routine relies upon the data being sorted first by Year (asc) then by RiskID (asc)
I have written the routine in C++ (for speed) to be compiled as a dll and referenced in VB.NET. I need to pass 3 arrays (one each for each of the headers) and return a 2 dimensional array back to VB.NET. I guess I'm cheating by passing 3 individual 1d arrays instead of a 2d array but there you go. I'll post the full C++ routine as others may find it useful if seeking to do something similar. I'd be surprised if this hasn't been done before - but I just can't find it.
I lack the interop knowledge to implement this properly and am getting nowhere googling around. As far as I can workout I may need to use SAFEARRAY ?
Or is there a quick fix to this problem? Or is SAFEARRAY a piece of cake. Either way an example would be very helpful.
Also, as a side note - I'm sure the memory management is failing somewhere?
Here is the Visual C++ (VS2013)
Header File
#ifndef CorrelLib_EXPORTS
#define CorrelLib_API __declspec(dllexport)
#else
#define CorrelLib_API __declspec(dllimport)
#endif
// Returns correlation matrix for values in flat file
extern "C" CorrelLib_API double** __stdcall CalcMatrix(int* Risk, int* Year, double* Loss, const int& RowNo, const int& RiskNo, const int& NoSimYear);
CPP File
#include "stdafx.h"
#include "CorrelLib.h"
#include <memory>
#include <ctime>
using namespace std;
extern "C" CorrelLib_API double** __stdcall CalcMatrix(int* Risk, int* Year, double* Loss, const int& RowNo, const int& RiskNo, const int& NoSimYear)
{
int a, b;
int i, j, k;
int YearCount, MissingYears;
int RowTrack;
//Relies on Year and Risk being sorted in ascending order in those respective orders Year asc, Risk asc
double *RiskTrack = new double[RiskNo](); //array of pointers?
int *RiskTrackBool = new int[RiskNo](); //() sets inital values to zero
double *RiskAvg = new double[RiskNo]();
double *RiskSD = new double[RiskNo]();
//Create 2d array to hold results 'array of pointers to 1D arrays of doubles'
double** Res = new double*[RiskNo];
for (i = 0; i < RiskNo; ++i)
{
Res[i] = new double[RiskNo](); //()sets initial values to zero
}
//calculate average
for (i = 0; i < RowNo; i++)
{
a = Risk[i];
RiskAvg[a] = RiskAvg[a] + Loss[i];
}
for (i = 0; i < RiskNo; i++)
{
RiskAvg[i] = RiskAvg[i] / NoSimYear;
}
//Enter Main Loop
YearCount = 0;
i = 0; //start at first row
do {
YearCount = YearCount + 1;
a = Risk[i];
RiskTrack[a] = Loss[i] - RiskAvg[a];
RiskTrackBool[a] = 1;
j = i + 1;
do
{
if (Year[j] != Year[i])
{
break;
}
b = (int)Risk[j];
RiskTrack[b] = Loss[j] - RiskAvg[b];
RiskTrackBool[b] = 1;
j = j + 1;
} while (j < RowNo);
RowTrack = j;
//check through RiskTrack and if no entry set to 0 - avg
for (j = 0; j < RiskNo; j++)
{
if (RiskTrackBool[j] == 0)
{
RiskTrack[j] = -1.0 * RiskAvg[j];
RiskTrackBool[j] = 1;
}
}
//Now loop through and perform calcs
for (j = 0; j < RiskNo; j++)
{
//SD
RiskSD[j] = RiskSD[j] + RiskTrack[j] * RiskTrack[j];
//Covar
for (k = j + 1; k < RiskNo; k++)
{
Res[j][k] = Res[j][k] + RiskTrack[j] * RiskTrack[k];
}
}
//Reset RiskTrack
for (k = 0; k<RiskNo; k++)
{
RiskTrack[k] = 0.0;
RiskTrackBool[k] = 0;
}
i = RowTrack;
} while (i < RowNo);
//Account For Missing Years
MissingYears = NoSimYear - YearCount;
for (i = 0; i < RiskNo; i++)
{
//SD
RiskSD[i] = RiskSD[i] + MissingYears * RiskAvg[i] * RiskAvg[i];
//Covar
for (j = i + 1; j < RiskNo; j++)
{
Res[i][j] = Res[i][j] + MissingYears * RiskAvg[i] * RiskAvg[j];
}
}
//Covariance Matrix
for (i = 0; i < RiskNo; i++)
{
//SD
RiskSD[i] = sqrt(RiskSD[i] / (NoSimYear - 1));
if (RiskSD[i] == 0.0)
{
RiskSD[i] = 1.0;
}
//Covar
for (j = i + 1; j < RiskNo; j++)
{
Res[i][j] = Res[i][j] / (NoSimYear - 1);
}
}
//Correlation Matrix
for (i = 0; i < RiskNo; i++)
{
Res[i][i] = 1.0;
for (j = i + 1; j < RiskNo; j++)
{
Res[i][j] = Res[i][j] / (RiskSD[i] * RiskSD[j]);
}
}
//Clean up
delete[] RiskTrack;
delete[] RiskTrackBool;
delete[] RiskAvg;
delete[] RiskSD;
//Return Array
return Res;
}
Def File
LIBRARY CorrelLib
EXPORTS
CalcMatrix
VB.NET
I've created a simple winform with a button which triggers the code below. I wish to link to the dll, pass the arrays and receive the result as a 2d array.
Imports System
Imports System.Runtime.InteropServices
Public Class Form1
<DllImport("CorrelLib.dll", EntryPoint:="CalcMatrix", CallingConvention:=CallingConvention.StdCall)> _
Public Shared Function CorrelMatrix2(ByRef Risk_FE As Integer, ByRef Year_FE As Integer, ByRef Loss_FE As Double, _
ByRef RowNo As Long, ByRef RiskNo As Long, ByRef NoSimYear As Long) As Double(,)
End Function
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim i As Integer, j As Integer
Dim Risk() As Long, Year() As Long, Loss() As Double
Dim NoRisks As Long, NoSimYear As Long, NoRows As Long
Dim counter As Long
Dim Result(,) As Double
NoRisks = 50
NoSimYear = 10000
NoRows = NoRisks * NoSimYear
ReDim Risk(0 To NoRows - 1), Year(0 To NoRows - 1), Loss(0 To NoRows - 1)
counter = 0
For i = 1 To NoSimYear
For j = 1 To NoRisks
Risk(counter) = j
Year(counter) = i
Loss(counter) = CDbl(Math.Floor((1000000 - 1 + 1) * Rnd())) + 1
counter = counter + 1
Next j
Next i
Dim dllDirectory As String = "C:\Users\Documents\Visual Studio 2013\Projects\CorrelLibTestForm"
Environment.SetEnvironmentVariable("PATH", Environment.GetEnvironmentVariable("PATH") + ";" + dllDirectory)
Result = CorrelMatrix2(Risk(1), Year(1), Loss(1), NoRows, NoRisks, NoSimYear)
End Sub
End Class
Current Error Message
An unhandled exception of type >'System.Runtime.InteropServices.MarshalDirectiveException' occurred in >CorrelLibTestForm.exe
Additional information: Cannot marshal 'return value': Invalid >managed/unmanaged type combination.
A double ** pointer to a pointer is not the same with a 2 dimension array in vb. Your best bet is to return just a pointer:
double *pdbl;
pdbl = &res[0][0];
return pdbl; //pdbl points to the first element
In vb you use an IntPtr to get the pointer:
Dim Result As IntPtr = Marshal.AllocHGlobal(4)
Dim dbl As Double
Result = CorrelMatrix2(Risk(1), Year(1), Loss(1), NoRows, NoRisks, NoSimYear)
//derefference the double pointer, i(integer) is actually the index in the array of doubles
dbl = CType(Marshal.PtrToStructure(IntPtr.Add(Result, i * 8), GetType(Double)), Double)
Your res array in c++ function needs to be public so the memory allocated to it is valid after the function returns.

error on using Boolean in c++

Given an array of start-times and end-times, sort them based on the end-times.
Here's what my function description looks like
// sort() - sorts an array of floats returning sorted indices
// On return, indx[] is an array of indices such that data[indx[0]],
// data[indx[1]], ..., data[indx[len-1]] is data[] in ascending order.
// Parameters
// data[] - float array of data to be ordered
// indx[] - int array, same length as data[], to hold indices
// len - int specifying the length of data[] and indx[]
and here's the code
#include<iostream>
#include<string>
#include sched.h
void sort(float data[], int indx[], int len);
int main() {
int indx[NUM_EVENTS];
int scheduledEvents[NUM_EVENTS];
int numSched;
// Sort by event ending times
sort(endTime, indx, NUM_EVENTS);
// Call greedy scheduling algorithm
numSched = sched(startTime, endTime, indx, scheduledEvents, NUM_EVENTS);
// Display scheduled events
for (int i = 0; i < numSched; i++)
printEvent(startTime[scheduledEvents[i]], endTime[scheduledEvents[i]],
description[scheduledEvents[i]]);
return 0;
}
my sorting algorithm inducing a for loop to check out the outputs
looks like
void sort(float data[], int indx[], int len){
for (int i = 0; i < 10; i++){
indx[i];
}
float smallestIndex;
bool flag = 1;
while (flag == 1){
flag == 2;
for (int i = 0; i < len-1; i++){
if (data[indx[i]] > data[indx[i + 1]]){
smallestIndex = indx[i + 1];
indx[i + 1] = indx[i];`
indx[i] = smallestIndex;
flag == 1;
}
}
}
for (int i = 0; i < 10;i++){
cout << data[indx[i]] << endl;
}
doing do I got an error that looks like
> warning C4806: '==' : unsafe operation: no value of type 'bool'
promoted to type 'int' can equal the given constant
1>sched.obj : error LNK2019: unresolved external symbol "void __cdecl
printEvent(float,float,class std::basic_string,class std::allocator >)"
(?printEvent##YAXMMV?$basic_string#DU?$char_traits#D#std##V?$allocator#D#2##std###Z)
referenced in function _main
bool is a type that usually accepts true and false. Internally it is handled as an int. That is why you can assign numeric values to it. However, if you would like to do this, use int.
Also notice that your line with:
flag == 2;
has no effect. You compare flag to 2 and the result of this comparison (either true or false) is just left in the air. This is not an error but the whole expression does not do anything.
The variable flag only ever holds one of two values, so this would work, leaving your other logic (may not be the most efficient), "as is."
bool flag = true;
while (flag == true){
flag = false; // Tentative "stop"
for (int i = 0; i < len-1; i++){
if (data[indx[i]] > data[indx[i + 1]]){
smallestIndex = indx[i + 1];
indx[i + 1] = indx[i];`
indx[i] = smallestIndex;
flag = true; // Keep going.
}
}
}
A bool can only be true or false, it is binary. You can assign 1 or 0 to an int to get the same result as if you had used a bool if you don't want to use a bool.
Also you use == which is to check equivalence. A single = is for assigning a number which it looks like you want to do when,
flag == 2;
It should be declared and int (or something similar)
int flag = 0;
flag = 2

C++ Fibonacci Errors

I'm having some trouble with this non recursive Fibonacci function. I am using this array of numbers and passing it to FiboNR, however I am getting large negative values and Access Violation errors.
int n[15] = { 1,5,10,15,20,25,30,35,40,45,50,55,60,65,70 };
int FiboNR(int n) // array of size n
{
int const max = 100;
int F[max];
F[0] = 0; F[1] = 1;
for (int i = 2; i <= n; i++) {
F[n] = F[n - 1] + F[n - 2];
}
return (F[n]);
}
The function was one provided by the instructor and I assume its correct if he's giving it out but with these memory errors I don't fully understand what's going on. The only way I'm calling the in a loop to go through the array and outputting the answer like cout << FiboNR(n[i]);
First of all, your trouble is in loop. Replace:
F[n] = F[n - 1] + F[n - 2];
with:
F[i] = F[i - 1] + F[i - 2];
Because i is your iterator and n is only the limit.
Just FYI, the braces ( ) in return statement are not needed, you can ignore them.
I am using this array of numbers and passing it to FiboNR
You are not supposed to do that since FiboNR() excepts its argument to be an integer (one, not an array of integers). So you should pass only one number to your function, like: FiboNR(n[2]).
You get a negative numbers due to int overflow for int array (n > 46).
Change array type from int to long long.
Other solutions: change array type to float/double type with less precision of the results or use long arithmetic.
Type | Typical Bit Width | Typical Range
int | 4bytes| -2147483648 to 2147483647
Link: C++ Data Types
Example of code below.
#include <iostream>
long long FiboNR(int n);
long long FiboNR(int n) {
int const max = 100;
long long F[max];
if (n > max) {
n = max;
}
F[0] = 0;
F[1] = 1;
for (int i = 2; i <= n; i++){
F[i] = F[i - 1] + F[i - 2];
}
return (F[n]);
}
int main() {
for (int i=0; i < 100; i++) {
std::cout << "i = " << i << " : " << FiboNR(i) << std::endl;
}
return 0;
}

Effect on performance when using objects in c++

I have a dynamic programming algorithm for Knapsack in C++. When it was implemented as a function and accessing variables passed into it, it was taking 22 seconds to run on a particular instance. When I made it the member function of my class KnapsackInstance and had it use variables that were data members of that class, it started taking 37 seconds to run. As far as I know, only accessing member functions goes through the vtable so I'm at a loss to explain what might be happening.
Here's the code of the function
int KnapsackInstance::dpSolve() {
int i; // Current item number
int d; // Current weight
int * tbl; // Array of size weightLeft
int toret;
tbl = new int[weightLeft+1];
if (!tbl) return -1;
memset(tbl, 0, (weightLeft+1)*sizeof(int));
for (i = 1; i <= numItems; ++i) {
for (d = weightLeft; d >= 0; --d) {
if (profitsWeights.at(i-1).second <= d) {
/* Either add this item or don't */
int v1 = profitsWeights.at(i-1).first + tbl[d-profitsWeights.at(i-1).second];
int v2 = tbl[d];
tbl[d] = (v1 < v2 ? v2 : v1);
}
}
}
toret = tbl[weightLeft];
delete[] tbl;
return toret;
}
tbl is one column of the DP table. We start from the first column and go on until the last column. The profitsWeights variable is a vector of pairs, the first element of which is the profit and the second the weight. toret is the value to return.
Here is the code of the original function :-
int dpSolve(vector<pair<int, int> > profitsWeights, int weightLeft, int numItems) {
int i; // Current item number
int d; // Current weight
int * tbl; // Array of size weightLeft
int toret;
tbl = new int[weightLeft+1];
if (!tbl) return -1;
memset(tbl, 0, (weightLeft+1)*sizeof(int));
for (i = 1; i <= numItems; ++i) {
for (d = weightLeft; d >= 0; --d) {
if (profitsWeights.at(i-1).second <= d) {
/* Either add this item or don't */
int v1 = profitsWeights.at(i-1).first + tbl[d-profitsWeights.at(i-1).second];
int v2 = tbl[d];
tbl[d] = (v1 < v2 ? v2 : v1);
}
}
}
toret = tbl[weightLeft];
delete[] tbl;
return toret;
}
This was run on Debian Lenny with g++-4.3.2 and -O3 -DNDEBUG turned on
Thanks
In a typical implementation, a member function receives a pointer to the instance data as a hidden parameter (this). As such, access to member data is normally via a pointer, which may account for the slow-down you're seeing.
On the other hand, it's hard to do more than guess with only one version of the code to look at.
After looking at both pieces of code, I think I'd write the member function more like this:
int KnapsackInstance::dpSolve() {
std::vector<int> tbl(weightLeft+1, 0);
std::vector<pair<int, int> > weights(profitWeights);
int v1;
for (int i = 0; i <numItems; ++i)
for (int d = weightLeft; d >= 0; --d)
if ((weights[i+1].second <= d) &&
((v1 = weights[i].first + tbl[d-weights[i-1].second])>tbl[d]))
tbl[d] = v1;
return tbl[weightLeft];
}