I'm having trouble finding any information regarding the following warning when linking a dynamic library:
In function `MyClass::myfunc()':
MyClass.cpp:(.text+0x14e4): warning: memset used with constant zero length parameter; this could be due to transposed parameters
Here is an excerpt of myfunc:
void MyClass::myfunc() {
vector<Variable*>::const_iterator it;
for (it = m_vars.begin();
it != m_vars.end();
++it) {
if ((*it)->recordme) {
MyRecord* r = new MyRecord(*it);
initMyRecord(*r);
m_records.push_back(r);
}
}
}
So I'm pretty much stuck on were should I be looking for possible causes for this memset. The call to the new operator is my first suspect, but I'm not even sure if it's worth looking for this. I'm not sure either if I should take this warning seriously or let it pass.
Question: what should I do about this warning? And what kind of patterns should I look out for in order to assure that I'm not going to shoot myself in the foot later?
Update:
Here is the MyRecord constructor, which is in a header file, so it might or might not be inlined, if I understand correctly.
class MyRecord {
public:
MyRecord(const Variable* var) :
buffer(0),
lastSave(-1 * std::numeric_limits<double>::max()),
sample(100),
bufsize(100),
gv(var),
rec_function(0)
{};
virtual ~Record() {
if (rec_function)
delete rec_function;
rec_function = 0;
};
private:
Record(const Record&);
Record& operator=(const Record& rec);
public: // #todo: remove publicness
boost::circular_buffer< boost::tuple<double,boost::any> > buffer;
double lastSave;
double sample;
unsigned int bufsize;
const Variable* gv;
RecordFunctor* rec_function;
};
The RecordFunctor is a pure-virtual struct:
struct RecordFunctor {
virtual ~RecordFunctor() {};
virtual void record(const double) = 0;
};
Additional info? I'm compiling with flags -O2 and g++ (Ubuntu/Linaro 4.6.1-9ubuntu3) 4.6.1
The behavior of the memset() function with a size of 0 is well defined, as long as the pointer argument is valid.
See section 7.21.1 of the C99 standard, or 7.24.1 of the C11 standard:
Where an argument declared as size_t n specifies the length of the
array for a function, n can have the value zero on a call to that
function.
On the other hand, the warning is a sensible one; a call like memset(s, 0, 0) is not dangerous, but it's not useful (it does nothing), and could easily indicate a programming error.
Greg's answer explains how to avoid it in this case.
You are calling the boost::circular_buffer constructor with a capacity of 0. This probably causes that constructor to call memset() to initialise the storage used by the circular buffer, but you've told it you want a buffer of zero size.
The solution is to give the circular_buffer constructor the actual size you want, not zero (zero doesn't make sense).
Related
use of a function returning an integer and (possibly) modifying a base pointer causes undesired behavior in returning the intended member of an array.
this concerns quite old legacy code; modern options using containers will solve the problem (No need to tell me, please!), but I want to point this out and ask whether the behavior is intentional under C++17, as contrasted with up to and including C++14.
The code looks like:
// dosomething() returns an integer.
// ArrayPointer is a class member
somememberfunction(args)
{
...
return ArrayPointer[dosomething()];
}
The problem arises from the fact that dosomething() will change ArrayPointer and the old value of ArrayPointer is used instead of the new (under C++17, not under C++14).
The workaround is to define an intermediate variable:
const int index=dosomething();
return ArrayPointer[index];
The question is: is there an explanation (depending on the standard), or is this to be regarded as a bug, rather than just undesired behavior from my point of view?
PS: complet(er C) code, as requested, mind the non-essential parts, variable declarations omitted:
struct BKPRArray // struct for applying meteocorrection
{
double *findprarray(const char *bks)
{
// check earlier allocations (NR)
for (int n = 0; n < arrays; n++)
if (!_stricmp(this->bk[n], bks))
{
if (!PRarray[n]) PRarray[n] = (NUMTYPE*)calloc(FL_alloced, sizeof(NUMTYPE));
return PRarray[n];
}
// combined return statement will fail under C++17 by using the old value of PRarray.
// This MAY be caused by order of evaluation, rule 17: https://en.cppreference.com/w/cpp/language/eval_order
// allocate and prepare (preparation code omitted) a new array.
//return PRarray[addarray(bks, defaultMeteoCorrection)];
const auto index = addarray(bks, defaultMeteoCorrection);
return PRarray[index]; // zet factor op +20%, want bk niet specifiek vermeld bij input.
}
....
int addarray(const char *bks, const double fact = defaultMeteoCorrection)
{
PRarray = (double**)realloc(PRarray, (arrays + 1) * sizeof(*PRarray));
if (FL_alloced) PRarray[arrays] = (NUMTYPE*)calloc(FL_alloced, sizeof(NUMTYPE));
else PRarray[arrays] = NULL;
...
return arrays++;
}
....
private:
double **PRarray; // etc.
};
Order of evaluation between ArrayPointer and dosomething() is unspefified before C++17. (So the fact that it "works" in C++14 is by "chance").
In C++17, ArrayPointer should be evaluated before dosomething().
see Order of evaluation, Rule 17.
My compiler (C++Builder6) syntactically allows array member initialization (at least with zero), but actually it doesn't really do it. So the assert in the example given below fails depending from the context.
#include <assert.h>
struct TT {
char b[8];
TT(): b() {}
};
void testIt() {
TT t;
assert(t.b[7] == 0);
}
Changing the compiler isn't an option at the moment. My question is: what will be the best way to "repair" this flaw with respect to future portability and standard conformance?
Edit:
As it turns out, my first example was too short. It missed the point, that the fill level of the array is so essential, that it has to be stored very close to the array, which is: in the same class.
Even if the original problem remains, my actual problem pattern is usually this:
struct TT2 {
int size;
char data[8];
// ... some more elements
TT2(): size(0), data() {}
// ... some more methods
};
I think you may use this:
TT() { std::fill(b, b + 8, char()); }
This way you will solve your problem while nothing is wrong with portability and standard conformance!
You may use fill_n like suggested in:
C/C++ initialization of a normal array with one default value
If no fill_n is available, you can always use memset like:
TT() {memset(b, 0, sizeof b);}
I would like to append previous posts that if you are using a character array as a string then it is enough to write in the constructor
TT() { b[0] = '\0'; }
I have a global array, which is indexed by the values of an enum, which has an element representing number of values. The array must be initialized by a special value, which unfortunately is not a 0.
enum {
A, B, C, COUNT
};
extern const int arr[COUNT];
In a .cpp file:
const int arr[COUNT] = { -1, -1, -1 };
The enum is occasionally changed: new values added, some get removed. The error in my code, which I just fixed was an insufficient number of initialization values, which caused the rest of the array to be initialized with zeroes. I would like to put a safeguard against this kind of error.
The problem is to either guarantee that the arr is always completely initialized with the special value (the -1 in the example) or to break compilation to get the developers attention, so the array can be updated manually.
The recent C++ standards are not available (old ms compilers and some proprietary junk). Templates can be used, to an extent. STL and Boost are strongly prohibited (don't ask), but I wont mind to copy or to reimplement the needed parts.
If it turns out to be impossible, I will have to consider changing the special value to be 0, but I would like to avoid that: the special value (the -1) might be a bit too special and encoded implicitly in the rest of the code.
I would like to avoid DSL and code generation: the primary build system is jam on ms windows and it is major PITA to get anything generated there.
The best solution I can come up with is to replace arr[COUNT] with arr[], and then write a template to assert that sizeof(arr) / sizeof(int) == COUNT. This won't ensure that it's initalized to -1, but it will ensure that you've explicitly initialized the array with the correct number of elements.
C++11's static_assert would be even better, or Boost's macro version, but if you don't have either available, you'll have to come up with something on your own.
This is easy.
enum {
A, B, C, COUNT
};
extern const int (&arr)[COUNT];
const int (&arr)[COUNT] = (int[]){ -1, -1, -1};
int main() {
arr[C];
}
At first glance this appears to produce overhead, but when you examine it closely, it simply produces two names for the same variable as far as the compiler cares. So no overhead.
Here it is working: http://ideone.com/Zg32zH, and here's what happens in the error case: http://ideone.com/yq5zt3
prog.cpp:6:27: error: invalid initialization of reference of type ‘const int (&)[3]’ from expression of type ‘const int [2]’
For some compilers you may need to name the temporary
const int arr_init[] = { -1, -1, -1};
const int (&arr)[COUNT] = arr_init;
update
I've been informed the first =(int[]){-1,-1,-1} version is a compiler extension, and so the second =arr_init; version is to be preferred.
Answering my own question: while it seems to be impossible to provide the array with the right amount of initializers directly, it is really easy to just test the list of initializers for the right amount:
#define INITIALIZERS -1, -1, -1,
struct check {
check() {
const char arr[] = {INITIALIZERS};
typedef char t[sizeof(arr) == COUNT ? 1: -1];
}
};
const int arr[COUNT] = { INITIALIZERS };
Thanks #dauphic for the idea to use a variable array to count the values.
The Boost.Preprocessor library might provide something useful, but I doubt whether you will be allowed to use it and it might turn out to be unwieldy to extract from the Boost sources.
This similar question has an answer that looks helpful:
Trick : filling array values using macros (code generation)
The closest I could get to an initialization rather than a check is to use a const reference to an array, then initialize that array within a global object. It's still runtime initialization, but idk how you're using it so this may be good enough.
#include <cstring>
enum {A, B, C, COUNT};
namespace {
class ArrayHolder {
public:
int array[COUNT]; // internal array
ArrayHolder () {
// initialize to all -1s
memset(this->array, -1, sizeof(this->array));
}
};
const ArrayHolder array_holder; // static global container for the array
}
const int (&arr)[COUNT] = array_holder.array; // reference to array initailized
// by ArrayHolder constructor
You can still use the sizeof on it as you would before:
for (size_t i=0; i < sizeof(arr)/sizeof(arr[0]); ++i) {
// do something with arr[i]
}
Edit
If the runtime initialization can never be relied on you should check your implementation details in the asm because the values of arr even when declared with an initializer may still not be known at until runtime initialization
const int arr[1] = {5};
int main() {
int local_array[arr[0]]; // use arr value as length
return 0;
}
compiling with g++ -pedantic gives the warning:
warning: ISO C++ forbids variable length array ‘local_array’ [-Wvla]
another example where compilation actually fails:
const int arr1[1] = {5};
int arr2[arr1[0]];
error: array bound is not an integer constant before ']' token
As for using an array value as a an argument to a global constructor, both constructor calls here are fine:
// [...ArrayHolder definition here...]
class IntegerWrapper{
public:
int value;
IntegerWrapper(int i) : value(i) {}
};
const int (&arr)[COUNT] = array_holder.array;
const int arr1[1] = {5};
IntegerWrapper iw1(arr1[0]); //using = {5}
IntegerWrapper iw2(arr[0]); //using const reference
Additionally the order of initalization of global variables across different source files is not defined, you can't guarantee the arr = {-1, -1, -1}; won't happen until run time. If the compiler is optimizing out the initialization, then you're relying on implementation, not the standard.
The point I really wanna stress here is: int arr[COUNT] = {-1, -1, -1}; is still runtime initialization unless it can get optimized out. The only way you could rely on it being constant would be to use C++11's constexpr but you don't have that available.
I want to specialize a template for a certain GUID, which is a 16 byte struct. The GUID object has internal linkage, so I can't use the address of the object itself, but I thought I could use the contents of the object, since the object was a constant. But this doesn't work, as illustrated by this example code:
struct S
{
int const i;
};
S const s = { 42 };
char arr[s.i];
Why isn't s.i a constant if s is? Any workaround?
The initialization of the struct s can happen at run time. However, the size of an array must be known at compile time. The compiler won't (for sure) know that the value of s.i is known at compile time, so it just sees you're using a variable for something you shouldn't be. The issue isn't with constness, it's an issue of when the size of the array is needed.
You may be misunderstanding what const means. It only means that after the variable is initialized, it is never changed. For example this is legal:
void func(int x){
const int i = x*5; //can't be known at compile-time, but still const
//int array[i]; //<-- this would be illegal even though i is const
}
int main(){
int i;
std::cin >> i;
func(i);
return 0;
}
To get around this limitation, in C++11 you can mark it as constexpr to indicate that the value can be determined at compile time. This seems to be what you want.
struct S
{
int const i;
};
int main(){
constexpr S const s = { 42 };
char arr[s.i];
return 0;
}
compile with:
$ c++ -std=c++11 -pedantic file.cpp
in C99, what you're doing is legal, the size of an array does not need to be known at compile time.
struct S
{
int const i;
};
int main(){
struct S const s = { 42 };
char arr[s.i];
return 0;
}
compile with:
$ cc -std=c99 -pedantic file.c
At least most of the time, const really means something much closer to "read-only" than to "constant". In C89/90, essentially all it means is "read-only". C++ adds some circumstances in which it can be constant, but it still doesn't even close to all the time (and, unfortunately, keeping track of exactly what it means when is non-trivial).
Fortunately, the "workaround" is to write your code the way you almost certainly should in any case:
std::vector<char> arr(s.i);
Bottom line: most use of a built-in array in C++ should be considered suspect. The fact that you can initialize a vector from a non-constant expression is only one of many advantages.
int add (int x, int y=1)
int main ()
{
int result1 = add(5);
int result2 = add(5, 3);
result 0;
}
VS
int add (int x, int y)
int main ()
{
int result1 = add(5, 1);
int result2 = add(5, 3);
result 0;
}
What is the advantage of using the default function parameter, in term of execution speed, memory usage and etc? For beginner like me, I sometimes got confused before I realized this usage of default function parameter; isn't it coding without default function parameter made the codes easier to read?
Your add function is not a good example of how to use defaulted parameters, and you are correct that with one it is harder to read.
However, this not true for all functions. Consider std::vector::resize, which looks something like:
template<class T>
struct vector_imitation {
void resize(int new_size, T new_values=T());
};
Here, resizing without providing a value uses T(). This is a very common case, and I believe almost everyone finds the one-parameter call of resize easy enough to understand:
vector_imitation<int> v; // [] (v is empty)
v.resize(3); // [0, 0, 0] (since int() == 0)
v.resize(5, 42); // [0, 0, 0, 42, 42]
The new_value parameter is constructed even if it is never needed: when resizing to a smaller size. Thus for some functions, overloads are better than defaulted parameters. (I would include vector::resize in this category.) For example, std::getline works this way, though it has no other choice as the "default" value for the third parameter is computed from the first parameter. Something like:
template<class Stream, class String, class Delim>
Stream& getline_imitation(Stream &in, String &out, Delim delim);
template<class Stream, class String>
Stream& getline_imitation(Stream &in, String &out) {
return getline_imitation(in, out, in.widen('\n'));
}
Defaulted parameters would be more useful if you could supply named parameters to functions, but C++ doesn't make this easy. If you have encountered defaulted parameters in other languages, you'll need to keep this C++ limitation in mind. For example, imagine a function:
void f(int a=1, int b=2);
You can only use the given default value for a parameter if you also use given defaults for all later parameters, instead of being able to call, for example:
f(b=42) // hypothetical equivalent to f(a=1, b=42), but not valid C++
If there is a default value that will provide correct behavior a large amount of the time then it saves you writing code that constantly passes in the same value. It just makes things more simple than writing foo(SOME_DEFAULT) all over the place.
It has a wide variety of uses. I usually use them in class constructors:
class Container
{
// ...
public:
Container(const unsigned int InitialSize = 0)
{
// ...
}
};
This lets the user of the class do both this:
Container MyContainer; // For clarity.
And this:
Container MyContainer(10); // For functionality.
Like everything else it depends.
You can use it to make the code clearer.
void doSomething(int timeout=10)
{
// do some task with a timeout, if not specified use a reasonable default
}
Is better than having lots of magic values doSomething(10) throughout your code
But be careful using it where you should really do function overloading.
int add(int a)
{
return a+1;
}
int add(int a,int b)
{
return a+b;
}
As Ed Swangren mentioned, some functions have such parameters that tend to have the same value in most calls. In these cases this value can be specified as default value. It also helps you see the "suggested" value for this parameter.
Other case when it's useful is refractoring, when you add some functionality and a parameter for it to a function, and don't want to break the old code. For example, strlen(const char* s) computes the distance to the first \0 character in a string. You could need to look for another characted, so that you'll write a more generic version: strlen(const char* s, char c='\0'). This will reuse the code of your old strlen without breaking compatibility with old code.
The main problem of default values is that when you review or use code written by others, you may not notice this hidden parameter, so you won't know that the function is more powerful than you can see from the code.
Also, google's coding style suggests avoiding them.
A default parameter is a function parameter that has a default value provided to it. If the user does not supply a value for this parameter, the default value will be
used. If the user does supply a value for the default parameter, the user-supplied value is used.
In computer programming, a default argument is an argument to a function that a programmer is not required to specify. In most programming languages, functions may take one or more arguments. Usually, each argument must be specified in full (this is the case in the C programming language)
Advantages of using default parameter, as others have pointed out, is indeed the "clarity" it brings in the code with respect to say function overloading.
But, it is important to keep in mind the major disadvantage of using this compile-time feature of the language: the binary compatibility and default function parameter does not go hand in hand.
For this reason, it is always good to avoid using default params in your API/interfaces classes. Because, each time you change the default param to something else, your clients will need to be recompiled as well as relinked.
Symbian has some very good C++ design patterns to avoid such BC.
Default parameters are better to be avoided.
let's consider the below example
int DoThis(int a, int b = 5, int c = 6) {}
Now lets say you are using this in multiple places
Place 1: DoThis(1);
Place 2: DoThis(1,2);
Place 3: DoThis(1,2,3);
Now you wanted to add 1 more parameter to the function and it is a mandatory field (extended feature for that function).
int DoThis(int a, int x, int b =5, int c=6)
Your compiler throws error for only "Place 1". You fix that. What about other others?
Imagine what happens in a large project? It would become a nightmare to identify it's usages and updating it rightly.
Always overload:
int DoThis(int a) {}
int DoThis(int a, int b {}
int DoThis(int a, int b, int c) {}
int DoThis(int a, int b, int c, int x) {}