I am getting the following error from PVS Studio
V669 The 'fetch_mask' argument is a non-constant reference. The analyzer is unable to determine the position at which this argument is being modified. It is possible that the function contains an error.
This is the line:
XXH64_state_t* hash_state, uint32_t& fetch_mask
I was figuring the error was the & isn't part of fetch_mask I fixed it like:
XXH64_state_t* hash_state, uint32_t &fetch_mask
The error goes away. However, travis.cl test says I need to reformat and fails.
I think found problem original codes.
void TextureCache::HashTextureBindings(
XXH64_state_t* hash_state, uint32_t& fetch_mask,
const std::vector<Shader::TextureBinding>& bindings) {
for (auto& binding : bindings) {
uint32_t fetch_bit = 1 << binding.fetch_constant;
if (fetch_mask & fetch_bit) {
void HashTextureBindings(XXH64_state_t* hash_state, uint32_t& fetch_mask,
const std::vector<Shader::TextureBinding>& bindings);
I removed the & since I think it is supposed to be uint32_t fetch_mask instead of uint32_t& fetch_mask
As I understand we are talking about this code. I’ll write the whole body of a function:
void TextureCache::HashTextureBindings(
XXH64_state_t* hash_state, uint32_t& fetch_mask,
const std::vector<Shader::TextureBinding>& bindings) {
for (auto& binding : bindings) {
uint32_t fetch_bit = 1 << binding.fetch_constant;
if (fetch_mask & fetch_bit) {
// We've covered this binding.
continue;
}
auto& regs = *register_file_;
int r = XE_GPU_REG_SHADER_CONSTANT_FETCH_00_0 + binding.fetch_constant * 6;
auto group =
reinterpret_cast<const xenos::xe_gpu_fetch_group_t*>(®s.values[r]);
auto& fetch = group->texture_fetch;
XXH64_update(hash_state, &fetch, sizeof(fetch));
}
}
As you can see, the variable fetch_mask is used only for reading in the expression if (fetch_mask & fetch_bit). It is strange to pass an integer variable by reference and not to modify it. This is often a sign that the code contains an error. Yes, it's not always a mistake, but this code should be carefully verified.
For PVS-Studio analyzer it does not matter, if uint32_t& fetch_mask or uint32_t &fetch_mask is written. In any case, it will issue the warning .
Probably, there is no error here. You can eliminate the warning by removing the link & as you did. Another option is to use one of the mechanisms of suppression of false positives.
The error indicates, that you are passing a non-const reference to a variable into a function, but PVS-Studio is unable to see, whether that variable actually gets modified. The purpose of passing an argument by reference is, that a function can modify the original value. If a function doesn't modify a value passed by reference, that reference should be const instead (i.e. uint32_t const& fetch_mask).
Passing a variable by value is another way to express, that a function doesn't modify the original value (although I prefer to pass by const value as well, so that it doesn't get accidentally assigned). For integral data types it is common to pass them by (const) value.
The diagnostic is essentially questioning, whether the intended purpose and code match up. The purpose of the code is, that the variable passed through the fetch_mask formal parameter can be modified, yet the implementation doesn't attempt to do so (unless it's doing so in a way that PVS-Studio cannot see, e.g. by aliasing it).
For reference, here is the official documentation for V669:
The analyzer has detected that an argument is being passed by reference into a function but not modified inside the function body. This may indicate an error which is caused, for example, by a misprint.
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 have a C++ function in which I have two int's, who's purpose is to serve as counters, that are declared outside of the function in my main code. My goal is to update the counter variables with the result from the execution of the function.
I have them declared as such
int cor_letters = 0;
int cor_place = 0;
and then call my function like
res = compare(input, secret_word, &cor_letters, &cor_place);
My compare function header is:
bool compare(string user_input, string secret, int * correct_letters, int * correct_place)
and in my compare code, when I get the final values of the counters, I update them as such:
correct_letters = &cor_l;
correct_place = &cor_p;
I arrived at this solution after carefully reading through my compiler errors, and this seems to work. However, I don't quite understand why this works. In the beginning, I take the address of the two variables and pass them into the function. But the function takes two pointers. So the pointers point to the address of the passed in variables.
Up to this point I seem to grasp what's going on. But its the final assignments that I'm confused by - the pointers (note they're the var names from the function header) are then being updated to the address of the temporary inner function variables that I'm using. Why does this get me the values?
I'm more of a visual learner, and pointers are hard to grasp by just reading some text, so if you wouldn't mind making some quick text diagram to represent what's going on, that would be great. Thank you
I guess you ended up with
correct_letters = &cor_l;
correct_place = &cor_p;
in order to make the compiler stop complaining.
Your analyse about taking the address of local variable is correct.
You probably want to do this
*correct_letters = cor_l;
*correct_place = cor_p;
in order to assign the correct values to the variables
which are outside the function.
A brief memo about reference (&) and dereference (*) operations.
TYPE var_a=..., var_b=...; // some variables of a chosen type
TYPE *ptr=NULL; // a pointer on such a type, but not referencing anything yet
ptr=&var_a; // now ptr memorises the address of var_a (reference operation)
var_b=*ptr; // access the value which is stored at the address memorised
// by ptr (dereference operation) in order to read it
// (here, this has the same effect as var_b=var_a; )
*ptr=var_a+var_b; // access the value which is stored at the address memorised
// by ptr (dereference operation) in order to alter it
// (here, this has the same effect as var_a=var_a+var_b; )
I'm just trying to run this simple line of code:
for (Client c : clients) {
c.timeSinceLastPacket++;
std::cout << c.timeSinceLastPacket << std::endl;
}
Unfortunately this always returns 1 after the increment. If I put a print before the increment it returns 0.
Here is my struct:
struct Client {
int timeSinceLastPacket = 0;
sf::IpAddress ip;
unsigned short port = 0;
unsigned short id = 0;
};
I'm using SFML.
Here's what I've tried:
Changed the ++ to += 1
Removed every instance in which the packet's value is defined as 0 (this can be seen in the code I have linked)
Changed the value of the packet to float
I should also mention that my original intention was to use sf::Time but that didn't work either
If I replace c with clients[0] it works fine
The code isn't too long but I don't want to put it in the question. I'll link you to it here:
Server.h
Server.cpp
for (Client c : clients) {
Here you make a copy, named c. Your original in clients is unaffected.
If you want to mutate the original elements, use a reference:
for (Client& c : clients) {
By typing the loop variable as Client, you're making a copy of the element in the array on every iteration. Changes within the loop update the copy, not the original item stored in clients.
Make it a reference instead:
for (Client& c : clients) {
Unlike Java or C#, C++ defaults to value types rather than references, so you must explicitly state that you want a reference (or a pointer, but the syntax is slightly messier).
Using a non-reference type here can also lead to some perf issues if the type is complex, or performs significant processing its copy constructor. (That's not really a concern for the type you've outlined here, but can be an issue in other cases.)
I've been using C/C++ for about three years and I can't believe I've never encountered this issue before!
This following code compiles (I've just tried using gcc):
#include <iostream>
int change_i(int i) {
int j = 8;
return j;
}
int main() {
int i = 10;
change_i(10);
std::cout << "i = " << i << std::endl;
}
And, the program prints i = 10, as you might expect.
My question is -- why does this compile? I would have expected an error, or at least a warning, saying there was a value returned which is unused.
Naively, I would consider this a similar case to when you accidentally forget the return call in a non-void function. I understand it's different and I can see why there's nothing inherently wrong with this code, but it seems dangerous. I've just spotted a similar error in some very old code of mine, representing a bug which goes back a long time. I obviously meant to do:
i = change_i(10);
But forgot, so it was never changed (I know this example is silly, the exact code is much more complicated). Any thoughts would be much appreciated!
It compiles because calling a function and ignoring the return result is very common. In fact, the last line of main does so too.
std::cout << "i = " << i << std::endl;
is actually short for:
(std::cout).operator<<("i =").operator<<(i).operator<<(std::endl);
... and you are not using the value returned from the final operator<<.
Some static checkers have options to warn when function returns are ignored (and then options to annotate a function whose returns are often ignored). Gcc has an option to mark a function as requiring the return value be used (__attribute__((warn_unused_result))) - but it only works if the return type doesn't have a destructor :-(.
Ignoring the return value of a function is perfectly valid. Take this for example:
printf("hello\n");
We're ignoring the return value of printf here, which returns the number of characters printed. In most cases, you don't care how many characters are printed. If compilers warned about this, everyone's code would show tons of warnings.
This actually a specific case of ignoring the value of an expression, where in this case the value of the expression is the return value of a function.
Similarly, if you do this:
i++;
You have an expression whose value is discarded (i.e. the value of i before being incremented), however the ++ operator still increments the variable.
An assignment is also an expression:
i = j = k;
Here, you have two assignment expressions. One is j = k, whose value is the value of k (which was just assigned to j). This value is then used as the right hand side an another assignment to i. The value of the i = (j = k) expression is then discarded.
This is very different from not returning a value from a non-void function. In that case, the value returned by the function is undefined, and attempting to use that value results in undefined behavior.
There is nothing undefined about ignoring the value of an expression.
The short reason it is allowed is because that's what the standard specifies.
The statement
change_i(10);
discards the value returned by change_i().
The longer reason is that most expressions both have an effect and produce a result. So
i = change_i(10);
will set i to be 8, but the assignment expression itself also has a result of 8. This is why (if j is of type int)
j = i = change_i(10);
will cause both j and i to have the value of 8. This sort of logic can continue indefinitely - which is why expressions can be chained, such as k = i = j = 10. So - from a language perspective - it does not make sense to require that a value returned by a function is assigned to a variable.
If you want to explicitly discard the result of a function call, it is possible to do
(void)change_i(10);
and a statement like
j = (void)change_i(10);
will not compile, typically due to a mismatch of types (an int cannot be assigned the value of something of type void).
All that said, several compilers (and static code analysers) can actually be configured to give a warning if the caller does not use a value returned by a function. Such warnings are turned off by default - so it is necessary to compile with appropriate settings (e.g. command line options).
I've been using C/C++ for about three years
I can suppose that during these three years you used standard C function printf. For example
#include <stdio.h>
int main( void )
{
printf( "Hello World!\n" );
}
The function has return type that differs from void. However I am sure that in most cases you did not use the return value of the function.:)
If to require that the compiler would issue an error when the return value of a function is not used then the code similar to the shown above would not compile because the compiler does not have an access to the source code of the function and can not determine whether the function has a side effect.:)
Consider another standard C functions - string functions.
For example function strcpy is declared like
char * strcpy( char *destination, const char *source );
If you have for example the following character arrays
char source[] = "Hello World!";
char destination[sizeof( source )];
then the function usually is called like
strcpy( destination, source );
There is no sense to use its return value when you need just to copy a string. Moreover for the shown example you even may not write
destination = strcpy( destination, source );
The compiler will issue an error.
So as you can see there is sense to ignore sometimes return values of functions.
For your own example the compiler could issue a message that the function does not have a side effect so its call is obsolete. In any case it should issue a message that the function parameter is not used.:)
Take into account that sometimes the compiler does not see a function definition that is present in some other compilation unit or in a library. So the compiler is unable to determine whether a function has a side effect,
In most cases compilers deal with function declarations. Sometimes the function definitions are not available for compilers in C and C++.
(Major edit: The way I posed the original question was bit confusing. So, I am trying to improve the question)
I am trying to convert “int32_t” to “static const int32_t” type. However, I could not figure out how to use static_cast and const_cast together. Any help would be appreciated.
I want to do this so that rather than initializing my “static const int32_t IRF_MAX_ENVELOPE_ELEMENTS2” to a hardcore value, I would like to set this based on value passed to the relevant function.
Say, the value of iNoOfSamples_In is 128, I would like to set IRF_MAX_ENVELOPE_ELEMENTS2 to 128 too; but, as as a “static const int32_t” like this:
int32_t iNoOfSamples_In = 128;
static const int32_t IRF_MAX_ENVELOPE_ELEMENTS2 = iNoOfSamples_In;
However, when I go to declare an array of size IRF_MAX_ENVELOPE_ELEMENTS2
double dTime_Scale[IRF_MAX_ENVELOPE_ELEMENTS2]; // Line 80
I get the following errors (line 80 marked in code snippet):
SpecialPulses.cpp(80) : error C2057: expected constant expression
SpecialPulses.cpp(80) : error C2466: cannot allocate an array of constant size 0
SpecialPulses.cpp(80) : error C2133: 'dTime_Scale' : unknown size
So, it seems that max_envelope_elements is not constant.
Just as the error message says, you can't declare a variable as const and then change its value. However, if you are trying to call a function that takes a const int_32, that's fine - just declare the variable as int_32. In that case, the const just says that the function doesn't change the value of the parameter inside the function, but even if it did it wouldn't affect your variable anyway.
By const it means that it's constant and by definition a constant is:
a situation or state of affairs that does not change. - google"
so you cannot change the value of the const variable after you initiated it.
Please do note that const are used most of the time for code readability in replacement for magic numbers in code.
take this for example
if(a>b%2)
//do something
What the heck is 2 and what does that do?
while if you actually can use something like this.
if(a>b%SOME_CONST_VALUE)
//do something
you can actually tell by the const variable what you are actually doing rather than having the programmer/developer who will maintain your code what the heck does that if statement does.
const_cast<int32_t>(IRF_MAX_ENVELOPE_ELEMENTS2)=256;
You can change your constant values like that, I hope this will help your problem.