I want to keep all the warnings enabled so -Wno-array-bound is not an option for me.
I am using variable size array work around using a structure (zero size array in a struct) and this is causing me to run causing me warnings.
Is there an attribute method to suppress these warnings where they occur?
To reproduce the warning:
#include <iostream>
struct A
{
int a;
char ch[0];
};
int main()
{
volatile A* test = (A*)malloc(sizeof(A) + (sizeof(char) * 10));
test->a = 1;
test->ch[0] = 'a';
}
Compile with:
g++ -O2 -Warray-bounds=2 t.cpp
warning generated:
t.cpp: In function ‘int main()’:
t.cpp:30:15: warning: array subscript 0 is above array bounds of ‘volatile char [0]’ [-Warray-bounds]
30 | test->ch[0] = 'a';
| ~~~~~~~~~~^
The below code works perfectly with strings but with char it gives segmentation fault.
#include<iostream>
using namespace std;
class salary
{
public:
int empno;
float inctax;
float netsal;
int gross;
short int age;
char name[50];
salary(){
empno=0;
gross=0;
age=0;
strcpy(name,'\0');
}
salary(int empn,int gros,short int ag,char nam[]){
empno=empn;
gross=gros;
age=ag;
strcpy(name,nam);
}
void calc(){
inctax=0.0;
if(gross>1000000)
inctax=0.3*gross;
else if(gross>=500000 && gross<=1000000)
inctax=0.2*gross;
else if(gross>=250000 && gross<500000)
inctax=0.1*gross;
else
inctax=0.0;
netsal=gross-inctax;
cout<<"inctax"<<inctax;
cout<<"net sal"<<netsal;
}
};
int main(){
salary *r=new salary();
salary *r1=new salary(112,500000,21,"Arnab");
r1->calc();
return 0;
}
I agree with vu1p3n0x's comment,
the problem is in the default constructor.
strcpy(name, '\0'); // This is wrong!
strcpy() takes two char arrays as arguments, but a character itself was passed as the second argument in your code.
The syntax of strcpy() is:
char * strcpy ( char * destination, const char * source );
In order to create null string using char arrays, you should probably use,
strcpy(name, "\0");
/*or*/
name[0] = '\0';
More on copying string, Reference and tutorialspoint
Your main problem is that your compiler isn't telling you about the obvious errors in the code. If you have correctly told it to report errors, then you perhaps need a better compiler. Here's the output I get when I compile:
g++ -std=c++14 -fPIC -g -Wall -Wextra -Wwrite-strings -Wno-parentheses 38113648.cpp -o 38113648
38113648.cpp: In constructor ‘salary::salary()’:
38113648.cpp:18:25: error: ‘strcpy’ was not declared in this scope
strcpy(name,'\0');
^
38113648.cpp: In constructor ‘salary::salary(int, int, short int, char*)’:
38113648.cpp:25:24: error: ‘strcpy’ was not declared in this scope
strcpy(name,nam);
^
38113648.cpp: In function ‘int main()’:
38113648.cpp:46:48: warning: ISO C++ forbids converting a string constant to ‘char*’ [-Wwrite-strings]
salary *r1=new salary(112,500000,21,"Arnab");
^
38113648.cpp:45:13: warning: unused variable ‘r’ [-Wunused-variable]
salary *r=new salary();
^
When I add
#include <cstring>
and change the constructor to take char const[], I get
g++ -std=c++14 -fPIC -g -Wall -Wextra -Wwrite-strings -Wno-parentheses 38113648.cpp -o 38113648
38113648.cpp: In constructor ‘salary::salary()’:
38113648.cpp:19:25: warning: null argument where non-null required (argument 2) [-Wnonnull]
strcpy(name,'\0');
^
Obviously you meant that to be "\0". Better still, provide an initializer:
salary()
: empno{0},
gross{0},
age{0},
name{0}
{
}
salary(int empno, int gross, short int age, char const name[])
: empno{empno},
gross{gross},
age{age}
{
strcpy(this->name, name);
}
(I've also given the formal parameters more meaningful names, as this often forms the documentation of the constructor).
Adding -Weffc++ may also be worthwhile - in this case it warns that you don't initialize inctax or netsal in the constructors. If you're happy to have part-initialized objects, you'll obviously need to use Valgrind to check that these values are indeed set before they are used, because it can't be determined statically.
consider the following: I have a class A with a constructor which takes an array of ints of size 3 as argument.
Now I want to construct a shared_ptr to A. If I use
shared_ptr<>(new A (parameter))
everything is fine.
But if I try using
make_shared<A>(parameter)
the compiler gives an error message. This happens only if the parameter-array is declared on the stack AND with a variable as array size (int parameter [n])
The problem disappears when using static arrays (int parameter[3]) or allocating the array on the heap with new.
I mean, this is no serious issue as there are the mentioned workarounds. Still, I would appreciate any explanation on why whis happens...
Btw I'm using g++ 4.8.2.
Here is a minimal example and the error log:
#include <iostream>
#include <memory>
using namespace std;
// some simple class
class A
{
public:
A () {};
A (int var[3]) {}; // some non-default constructor with an array as argument
void foo (){cout << "foo()" << endl;};
};
int main()
{
// make a shared_ptr to A
shared_ptr<A> ptr;
// allocate an array var1 of size nVars=3 on the stack
int nVars = 3;
int var1[nVars];
ptr = shared_ptr<A> (new A(var1)); // without make_shared, the c'tor is recognized
ptr->foo();
ptr = make_shared<A> (var1); // <- error at compile time!
ptr->foo();
// same with static array var2 of size 3
int var2[3];
ptr = make_shared<A> (var2); // <- no compilation error
ptr->foo();
// same with dynamic array var3 of size 3
int* var3 = new int[nVars];
ptr = make_shared<A> (var3); // <- no compilation error
ptr->foo();
return 0;
}
build log:
g++ -std=c++0x -D__GXX_EXPERIMENTAL_CXX0X__ -O0 -g3 -Wall -c -fmessage-length=0 -MMD -MP -MF"main.d" -MT"main.d" -o "main.o" "../main.cpp"
../main.cpp: In function ‘int main()’:
../main.cpp:25:28: error: no matching function for call to ‘make_shared(int [(((sizetype)(((ssizetype)nVars) + -1)) + 1)])’
ptr = make_shared<A> (var1); // <- error at compile time!
^
../main.cpp:25:28: note: candidate is:
In file included from /usr/include/c++/4.8/memory:82:0,
from ../main.cpp:2:
/usr/include/c++/4.8/bits/shared_ptr.h:610:5: note: template<class _Tp, class ... _Args> std::shared_ptr<_Tp1> std::make_shared(_Args&& ...)
make_shared(_Args&&... __args)
^
/usr/include/c++/4.8/bits/shared_ptr.h:610:5: note: template argument deduction/substitution failed:
../main.cpp:25:28: note: variable-sized array type ‘int (&)[(((sizetype)(((ssizetype)nVars) + -1)) + 1)]’ is not a valid template argument
ptr = make_shared<A> (var1); // <- error at compile time!
^
Cheers and thanks in advance for your answers!
Juri
When I run my code I get this error at compile time:
# g++ -std=c++0x sixteen.cpp -O3 -Wall -g3 -o sixteen
sixteen.cpp: In function ‘int main()’:
sixteen.cpp:10: error: call of overloaded ‘stoi(char&)’ is ambiguous
/usr/lib/gcc/x86_64-redhat-linux/4.4.7/../../../../include/c++/4.4.7/bits/basic_string.h:2565: note: candidates are: int std::stoi(const std::string&, size_t*, int) <near match>
/usr/lib/gcc/x86_64-redhat-linux/4.4.7/../../../../include/c++/4.4.7/bits/basic_string.h:2626: note: int std::stoi(const std::wstring&, size_t*, int) <near match>
I looked up that error and followed the instructions that other questions on here have done, however I still get that error after removing using namespace std;. Why is this still happening and what can I do to get rid of it?
Code:
#include <iostream>
#include <string>
int main() {
std::string test = "Hello, world!";
std::string one = "123";
std::cout << "The 3rd index of the string is: " << test[3] << std::endl;
int num = std::stoi(one[2]);
printf( "The 3rd number is: %d\n", num );
return 0;
}
std::stoi takes a std::string as its argument, but one[2] is a char.
The easiest way to fix this is to use the fact that the digit characters are guaranteed to have contiguous values, so you can do:
int num = one[2] - '0';
Alternatively, you can extract the digit as a substring:
int num = std::stoi(one.substr(2,1));
And another alternative, you can construct a std::string using the constructor that takes a char and the number of times that char should appear:
int num = std::stoi(std::string(1, one[2]));
When I compile the code below with g++ 4.8.1 (64bit) in this way:
$ g++ -Wconversion -o main main.cpp
I get this result:
main.cpp: In function ‘int main()’:
main.cpp:12:20: warning: conversion to ‘int’ from ‘long unsigned int’ may alter its value [-Wconversion]
int i = sizeof(x)/sizeof(x[0]);
^
My expectation would be that the compiler should be able to evaluate the expression at compile time. If you make a similar program in plain c, gcc works like a charm.
Should this be considered a bug in g++ (e.g. clang++ does not have this problem)?
if you change the problematic line to something like:
char c = 0x10000000/0x1000000;
then the compiler does not complain. This suggest that some constant evaluation is done before warning generation.
main.cpp:
#include <iostream>
struct foo {
int a;
int b;
};
foo x[50];
int main()
{
int i = sizeof(x)/sizeof(x[0]);
std::cout << i << std::endl;
return 0;
}
int i = sizeof(x)/sizeof(x[0]);
//int <-- std::size_t <-- std::size_t / std::size_t
The type of the expression sizeof(x)/sizeof(x[0]) is std::size_t which on your machine is unsigned long int. So conversion from this type to int is data-loss, if the source is bigger in size than the target.
Though, I agree that in your case, there would not be actual data-loss if the compiler actually computes the value, but I guess it applies -Wconversion before the actual computation.
sizeof() returns you std::size_t not int! So cast it or declare i as std::size_t.
std::size_t i = sizeof(x)/sizeof(x[0]);