I have a function that looks like this, that calls a function from a third party dll:
void f1(const double * const input, double * output){
// this function will modify output[]
// I have no knowledge of the implementation of this function, only that it wants
// 3 doubles as the input parameters, and it will modify the last 3 parameters to
// pass the result to me.
call_to_third_party_dll(input[0], input[1], input[2], output[1], output[2], output[3]);
}
I am calling this function like this:
double value[3] { 1, 2, 3 };
f1(value, value);
// value is now modified
This works, and gives the expected results. (It modifies 'value' as expected.)
I am calling the function with the same pointer for both parameters because it is convenient in the calling context, but I have questioned whether this is safe to do, since I don't know how 'call_to_third_party_dll' handles the parameters. (for example, it might modify one of the 'output' parameters, then use the modified value as an input for a subsequent calculation.)
I would like to construct f1 in a way that the compiler would complain if 'input' and 'output' are the same thing (like my example).
Is there a way to construct f1 so that it can fail at compile time if 'input' and 'output' are pointing to the same thing?
Note, f1 would not have to use double *. Whatever is passed will have to resolve to 3 doubles for the input parameters to the third party dll, and 3 doubles for the output of the third party dll.
No, you can't have such a check at compile time. There are other options you have though, which are done at runtime.
Make a copy of the input. That way, you won't ever get in a situation where you change the same memory. This is of course not very useful if the array is big, but if the array is only 3 doubles, it's no big deal.
Compare the pointers. If the pointers points to the same memory, raise an error. You should also make sure that the pointer with the lower address is at least n * sizeof(type) bytes away from the pointer with the higher address. I'm unsure if this is a good solution, but it might be a "good-enough" protection for debugging.
You change your function to:
std::array<double, 3> f1(std::array<double, 3> input){
std::array<double, 3> output;
call_to_third_party_dll(input[0], input[1], input[2], output[1], output[2], output[3]);
return output;
}
You can be sure that input and output are distinct objects.
Related
I'm trying to understand a Function/Method in a Library in order to port it to Java however some parameters don't make any sense to me and reading the source code the library is based on is not helping.
Function (Note the API has few comments (We can also ignore the calc handle since it's got a supplier method))
Ssr calc_ssr(CalcHandle *calc, NoteInfo *rows, size_t num_rows, float music_rate, float score_goal) {
std::vector<NoteInfo> note_info(rows, rows + num_rows);
auto skillsets = MinaSDCalc(
note_info,
music_rate,
score_goal,
reinterpret_cast<Calc*>(calc)
);
return skillset_vector_to_ssr(skillsets);
}
NoteInfo Struct
struct NoteInfo
{
unsigned int notes;
float rowTime;
};
MinaSDCalc
// Function to generate SSR rating
auto
MinaSDCalc(const std::vector<NoteInfo>& NoteInfo,
const float musicrate,
const float goal,
Calc* calc) -> std::vector<float>
{
if (NoteInfo.size() <= 1) {
return dimples_the_all_zero_output;
}
calc->ssr = true;
calc->debugmode = false;
return calc->CalcMain(NoteInfo, musicrate, min(goal, ssr_goal_cap));
}
Calc expected input file data (Only care about the #Notes: ...)
Pastebin
Question
What is NoteInfo in calc_ssr, I don't know any C or C++ so the *rows to me just seems like a pointer to a Noteinfo instance, however the MinaSDCalc methods requires an Array/Vector which using a pointer to a single instance doesn't make sense to me (pairing this with the fact that NoteInfo needs another parameter rowTime which I think is time of Note occurrence in the file which means that value must not be constant otherwise the produced result would be inaccurate)
Github Project: https://github.com/kangalioo/minacalc-standalone (The code alone may not explain enough but it's worth a try; best to look at API.h and discern what's used from there. Though I do warn you a lot of the Code is esoteric)
Sorry if this doesn't make much sense but I've been looking into this since June/July and this API is the closest abstraction from the bare C++ code I could find.
NoteInfo * rows here is pass by pointer. So, rows actually is a pointer to an instance of type NoteInfo. This is one of the ways to pass arrays in c++ to a function. Since arrays are contiguous in memory so we can just increment the pointer by one and get the next element of the array.
for example look at these three ways to do exactly one thing, parameter to pass an array to a function :-
1. void myFunction(int *param) {}
2. void myFunction(int param[10]) {}
3. void myFunction(int param[]) {}
Look into this link for more understanding : https://www.tutorialspoint.com/cplusplus/cpp_passing_arrays_to_functions.htm
Also search for pass by pointer and pass by reference to look into different ways of passing arguments in c++.
2.however the MinaSDCalc methods requires an Array/Vector which using a pointer to a single instance doesn't make sense to me: as to this question of yours, you can now see MinaSDCalc is actually getting an array and not a single instance as passing the pointer is also one of the ways of passing an array in c++.
I would like to create a function so I can use it in both ways -
I know that my wording is was not good so I deleted it (Because it will cause only confusion) and leaving only the code with the notes inside it:
int CalculationFunc(int i1, int i2, int i3, int i4, int i5) {
/* Some calculation done here */
return (i2*i3)+i5-i2+i4; /* <- this is not good example.. the calculation will be based also on
on values that are changing from time to time.. */
}
int main() {
// Situation 1:
/* In this situation I didn't initialized any parameter before because I didn't
need to.. all I need is to call to the functions with predefined values */
int iAnswer1 = CalculationFunc(1, 2, 3, 4, 5);
/*^ Everything is fine in this case - I Allocate memory only once*/
// ----------------------------------------------------------
// Situation 2:
int iVal1 = 0, iVal3 = 0, iVal5 = 0; // <-- Memory is allocated
/* ... something done here so the values of are not constant ...
(The code for this is not written) */
/*In this situation something different: some values that I going to pass to the
function are not predefined, and they are outcome of some pre-calculation done before,
so there is allocated memory for them. If I call to the functions with these variables: */
int iAnswer2 = CalculationFunc(iVal1, 6, iVal3, 2, iVal5);
/* ^ There is not really a "real-world" problem here. the problem is that what happening
In low-level is this:
a) allocate memory for iVal1 , iVal3 , iVal5
b) copy value of iVal1 to the allocated memory (and the same for iVal3 and iVal5)
c) use the allocated memory..
This is not efficient. What I want to do is to pass pointers for iVal1, iVal3, iVal5
And the function will automatically get the data using the pointers.
So there will not be steps a and b.
This is how I want to call it:
CalculationFunc(&iVal1, 6, &iVal3, 2, &iVal5)
*/
return 0;
}
Thanks for helpers!
You could overload the function to take different sets of parameters as references (or plain pointers), but you would end up with a lot of unnecessary copies of the same piece of code.
If you are planning to do this just for the sake of performance, I advice you not to. You are probably not going to get any performance boost from that, not with such simple data types.
This is better because this way the function does not necessarily require to allocate memory (for just a copy value) to transfer the same data.
When you're passing a variable by a reference or a pointer, the address to the variable needs to be copied. And when the data type of the variable you are referring to is int, the address is about the same size as the variable itself, so passing a pointer to an int is not any faster than passing the int itself. Actually, it is probably slower, because the pointer then needs to be dereferenced when the value is used in the function.
For a data type with larger size passing by pointer/reference could be significantly faster, but not with ints.
I am working on an S function in simulink. There are some variables in the MATLAB workspace available. I want to call them.
So in MATLAB:
a=3;
and in the S function (written in C/C++):
double a = CallFromMATLABWorkSpace(a); //Something like this.
How do I do this? There is something like mexCallMATLAB but it is not clear how I should use this in this situation.
To get data from a workspace use the function mexGetVariable.
However, this is a somewhat unusual thing to do.
Why isn't the data being passed as a parameter to the S-Function?
From what I can see in the documentation for mexCallMATLAB, as well as interoping with C++ source code, it would look something like the following:
Let's say you have a MatLab function MyDoubleFunction that takes a single scalar double value and returns a scalar double value. You would do the following if you wanted to pass the function a value of 4.0 and see what the answer is:
//setup the input args
mxArray* input_args[1] = {mxCreateDoubleScalar(4.0)};
mxArray** output_args; //will be allocated during call to mexCallMATLAB
//make the call to the Matlab function
if (mexCallMATLAB( 1 /* number of output arguments */,
output_args,
1 /* number of input arguments */,
&input_args,
"MyDoubleFunction"))
{
//error if we get to this code block since it returned a non-zero value
}
//inspect the output arguments
double answer = mxGetScalar(*output_args);
I have a two variables:
boost::array my_boost_array_variable_1<float, 3>;
boost::array my_boost_array_variable_2<float, 3>;
now I want to call a C function with the following signature:
int MPI_Allreduce ( void *sendbuf, void *recvbuf, ...);
I want to pass the address of a particular element of my my_boost_array_variable_1 and my_boost_array_variable_2 as a first and second parameter of MPI_Allreduce:
MPI_Allreduce(&my_boost_array_variable_1[2],
&my_boost_array_variable_2[2], ...
or should I rather do:
MPI_Allreduce(my_boost_array_variable_1.c_array() + 2,
my_boost_array_variable_2.c_array() + 2, ...
UPDATE:
The C functions expect a continuous chunk of data, that starts at void *sendbuf. The question here if these two calls are correct in this regard. Does &my_boost_array_variable_1[2] point to the same location as my_boost_array_variable_1.c_array() + 2 ? Are these calls equivalent?
For me first is more clear then second. But in reality i think they are equal.
according to http://www.boost.org/doc/libs/1_52_0/doc/html/boost/array.html NEITHER version will throw.
(could not comment with my little reputation :-))
It is system-depended which one is faster, you can see the assembly code for your self.
First method is safer, since it will throw you exception if you will try to address not legal index.
Second method usually is faster, since you have only a single de-reference.
void pushSynonyms (string synline, char matrizSinonimos [1024][1024]){
stringstream synstream(synline);
vector<int> synsAux;
int num;
while (synstream >> num) {synsAux.push_back(num);}
int index=0;
while (index<(synsAux.size()-1)){
int primerSinonimo=synsAux[index];
int segundoSinonimo=synsAux[++index];
matrizSinonimos[primerSinonimo][segundoSinonimo]='S';
matrizSinonimos [segundoSinonimo][primerSinonimo]='S';
}
}
and the call..
char matrizSinonimos[1024][1024];
pushSynonyms("1 7", matrizSinonimos)
It's important for me to pass matrizSinonimos by reference.
Edit: took away the & from &matrizSinonimos.
Edit: the runtime error is:
An unhandled win32 exception occurred in program.exe [2488]![alt text][1]
What's wrong with it
The code as you have it there - i can't find a bug. The only problem i spot is that if you provide no number at all, then this part will cause harm:
(synsAux.size()-1)
It will subtract one from 0u . That will wrap around, because size() returns an unsigned integer type. You will end up with a very big value, somewhere around 2^16 or 2^32. You should change the whole while condition to
while ((index+1) < synsAux.size())
You can try looking for a bug around the call side. Often it happens there is a buffer overflow or heap corruption somewhere before that, and the program crashes at a later point in the program as a result of that.
The argument and parameter stuff in it
Concerning the array and how it's passed, i think you do it alright. Although, you still pass the array by value. Maybe you already know it, but i will repeat it. You really pass a pointer to the first element of this array:
char matrizSinonimos[1024][1024];
A 2d array really is an array of arrays. The first lement of that array is an array, and a pointer to it is a pointer to an array. In that case, it is
char (*)[1024]
Even though in the parameter list you said that you accept an array of arrays, the compiler, as always, adjusts that and make it a pointer to the first element of such an array. So in reality, your function has the prototype, after the adjustments of the argument types by the compiler are done:
void pushSynonyms (string synline, char (*matrizSinonimos)[1024]);
Although often suggested, You cannot pass that array as a char**, because the called function needs the size of the inner dimension, to correctly address sub-dimensions at the right offsets. Working with a char** in the called function, and then writing something like matrizSinonimos[0][1], it will try to interpret the first sizeof(char**) characters of that array as a pointer, and will try to dereference a random memory location, then doing that a second time, if it didn't crash in between. Don't do that. It's also not relevant which size you had written in the outer dimension of that array. It rationalized away. Now, it's not really important to pass the array by reference. But if you want to, you have to change the whole thingn to
void pushSynonyms (string synline, char (&matrizSinonimos)[1024][1024]);
Passing by reference does not pass a pointer to the first element: All sizes of all dimensions are preserved, and the array object itself, rather than a value, is passed.
Arrays are passed as pointers - there's no need to do a pass-by-reference to them. If you declare your function to be:
void pushSynonyms(string synline, char matrizSinonimos[][1024]);
Your changes to the array will persist - arrays are never passed by value.
The exception is probably 0xC00000FD, or a stack overflow!
The problem is that you are creating a 1 MB array on the stack, which probably is too big.
try declaring it as:
void pushSynonyms (const string & synline, char *matrizSinonimos[1024] )
I believe that will do what you want to do. The way you have it, as others have said, creates a 1MB array on the stack. Also, changing synline from string to const string & eliminates pushing a full string copy onto the stack.
Also, I'd use some sort of class to encapsulate matrizSinonimos. Something like:
class ms
{
char m_martix[1024][1024];
public:
pushSynonyms( const string & synline );
}
then you don't have to pass it at all.
I'm at a loss for what's wrong with the code above, but if you can't get the array syntax to work, you can always do this:
void pushSynonyms (string synline, char *matrizSinonimos, int rowsize, int colsize )
{
// the code below is equivalent to
// char c = matrizSinonimos[a][b];
char c = matrizSinonimos( a*rowsize + b );
// you could also Assert( a < rowsize && b < colsize );
}
pushSynonyms( "1 7", matrizSinonimos, 1024, 1024 );
You could also replace rowsize and colsize with a #define SYNONYM_ARRAY_DIMENSION 1024 if it's known at compile time, which will make the multiplication step faster.
(edit 1) I forgot to answer your actual question. Well: after you've corrected the code to pass the array in the correct way (no incorrect indirection anymore), it seems most probable to me that you did not check you inputs correctly. You read from a stream, save it into a vector, but you never checked whether all the numbers you get there are actually in the correct range. (end edit 1)
First:
Using raw arrays may not be what you actually want. There are std::vector, or boost::array. The latter one is compile-time fixed-size array like a raw-array, but provides the C++ collection type-defs and methods, which is practical for generic (read: templatized) code.
And, using those classes there may be less confusion about type-safety, pass by reference, by value, or passing a pointer.
Second:
Arrays are passed as pointers, the pointer itself is passed by value.
Third:
You should allocate such big objects on the heap. The overhead of the heap-allocation is in such a case insignificant, and it will reduce the chance of running out of stack-space.
Fourth:
void someFunction(int array[10][10]);
really is:
(edit 2) Thanks to the comments:
void someFunction(int** array);
void someFunction(int (*array)[10]);
Hopefully I didn't screw up elsewhere....
(end edit 2)
The type-information to be a 10x10 array is lost. To get what you've probably meant, you need to write:
void someFunction(int (&array)[10][10]);
This way the compiler can check that on the caller side the array is actually a 10x10 array. You can then call the function like this:
int main() {
int array[10][10] = { 0 };
someFunction(array);
return 0;
}