| 905 | | ||? || class does not have a virtual destructor||Suppress or provide a virtual destructor.||??|| |
| | 905 | == Individual Warnings == |
| | 906 | '''comparison between signed and unsigned integer expressions''' |
| | 907 | |
| | 908 | '''-Wsign-compare''' - enable the warning (also turned on by -Wextra)[[BR]] |
| | 909 | '''-Wno-sign-compare''' - disable the warning[[BR]] |
| | 910 | |
| | 911 | Almost always points to a real issue. The ranges of these are obviously |
| | 912 | different, for example signed char -128 - 127 and unsigned char 0 - 255 for |
| | 913 | |
| | 914 | range bit pattern |
| | 915 | signed char -128 to 127 01111111 to 10000000 |
| | 916 | unsigned char 0 to 255 00000000 to 11111111 |
| | 917 | |
| | 918 | That means: signed char unsigned char |
| | 919 | 0 to 127 + + |
| | 920 | 128 to 255 - + |
| | 921 | |
| | 922 | In the range from 128 to 255 a comparison from one to the other makes no |
| | 923 | sense. They can have the same bit pattern, yet test as not equal. This |
| | 924 | is the source of many subtle and hard to find bugs. |
| | 925 | |
| | 926 | The same problem can occur with all of the integral types. For example with |
| | 927 | 16-bit short int unsigned ranges from -32768 to 32767, and the signed short |
| | 928 | ranges from 0 to 65535. |
| | 929 | |
| | 930 | To fix, if you are sure that all the values for both things being compared |
| | 931 | fall into the overlap where their values are the same, you can static_cast |
| | 932 | one type to the other, if you must, but if you can change one of the types |
| | 933 | it's a better solution. If you are sure that you can fit all values into |
| | 934 | the compared range, i.e. positive numbers from |
| | 935 | 0 to (1<<(sizeof(IntegralType)*8-1))-1, it would make more sense to |
| | 936 | declare the signed one as an unsigned equivalent, (perhaps size_t). In |
| | 937 | general, if you don't intend for a variable to ever have negative values, |
| | 938 | take advantage of the diagnostic capabilities of the compiler and don't |
| | 939 | declare it as an unsigned type. After you've done this, if you see the |
| | 940 | warning again for one of these same variables, it is warning you of this |
| | 941 | same danger again. |
| | 942 | |
| | 943 | This often shows up with loop counters. We all learned to use int, but |
| | 944 | if it's truly counting only positive numbers, size_t is better. |
| | 945 | |
| | 946 | '''missing braces around initializer for ‘main()::X''' |
| | 947 | |
| | 948 | '''-Wmissing-braces''' - enable the warning (also turned on by -Wall)[[BR]] |
| | 949 | '''-Wno-missing-braces''' - disable the warning |
| | 950 | |
| | 951 | This warning is trying to let you know that what you think you're |
| | 952 | initializing may not actually be what you're initializing. |
| | 953 | |
| | 954 | |
| | 955 | {{{ |
| | 956 | struct X { int i; int j;}; |
| | 957 | struct Y { struct X x; int j; }; |
| | 958 | |
| | 959 | Y y={1,2}; |
| | 960 | return 0; |
| | 961 | |
| | 962 | }}} |
| | 963 | |
| | 964 | The above example initializes both the elements of X in Y, but doesn't |
| | 965 | initialize j. Change to: |
| | 966 | |
| | 967 | {{{Y y={{1},2};}}} |
| | 968 | |
| | 969 | to initialize half of X and all of Y, or better something like: |
| | 970 | |
| | 971 | {{{Y y={{1,2},3};}}} |
| | 972 | |
| | 973 | The same kind of problem can come up with: |
| | 974 | |
| | 975 | {{{int a[2][2]={ 0, 1, 2 };}}} |
| | 976 | |
| | 977 | versus: |
| | 978 | |
| | 979 | {{{int a[2][2]={ {0,1},2};}}} or {{{int a[2][2]={ 0, {1,2}};}}} |
| | 980 | |
| | 981 | '''deprecated conversion from string constant to ‘char*’''' |
| | 982 | '''-Wwrite-strings''' - enable this warning (disabled by default for C and enabled by default for C++) |
| | 983 | '''-Wno-write-strings''' - disable this warning |
| | 984 | |
| | 985 | For C will warn about trying to modify string constants, but only if defined const. |
| | 986 | For C++ often symptomatic of a real bug since string literals are not writeable in C++. |
| | 987 | |
| | 988 | This one shows up when you have a string literal, like "Hello world!" which |
| | 989 | is arguably const data, and you assign it no a non-const char* either |
| | 990 | directly or via passing as an argument to a functions which expects a non-const char *. |
| | 991 | both: |
| | 992 | {{{ |
| | 993 | char* cp="Hello world!"; |
| | 994 | }}} |
| | 995 | and |
| | 996 | {{{ |
| | 997 | void foo(char *cp); |
| | 998 | foo("Hello world") |
| | 999 | }}} |
| | 1000 | will get this warning because you're using a string literal where a char* |
| | 1001 | is expected. If you say, so what? See if you can predict what will print |
| | 1002 | in the example below. |
| | 1003 | |
| | 1004 | {{{ |
| | 1005 | #include <iostream> |
| | 1006 | |
| | 1007 | void |
| | 1008 | foo(char *cp) |
| | 1009 | { |
| | 1010 | cp[0]='W'; |
| | 1011 | } |
| | 1012 | |
| | 1013 | int main() |
| | 1014 | { |
| | 1015 | char *str="Hello, world"; |
| | 1016 | foo(str); |
| | 1017 | std::cout << str << std::endl; |
| | 1018 | } |
| | 1019 | }}} |
| | 1020 | |
| | 1021 | If you said that Wello, world will print, think again. Your most likely |
| | 1022 | output is something like: |
| | 1023 | '''Segmentation fault (core dumped)''' |
| | 1024 | A string literal is put into a section that is read only and trying to |
| | 1025 | write to it makes things blow up! |
| | 1026 | |
| | 1027 | The right fix is to make anything that a string literal can be assigned |
| | 1028 | to a const char*. |
| | 1029 | Unfortunately, sometimes you can't fix the problem at the source, because |
| | 1030 | it's someone else's code, and you can't change the declaration. For |
| | 1031 | example, if you had this function: |
| | 1032 | |
| | 1033 | {{{ |
| | 1034 | int PyArg_ParseTupleAndKeywords(PyObject *arg, PyObject *kwdict, |
| | 1035 | char *format, char **kwlist, ...); |
| | 1036 | }}} |
| | 1037 | |
| | 1038 | and you had a keyword list to pass it like this: |
| | 1039 | |
| | 1040 | {{{ |
| | 1041 | static char *kwlist[] = {"fget", "fset", "fdel", "doc", 0}; |
| | 1042 | if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OOOO:property", |
| | 1043 | kwlist, &get, &set, &del, &doc)) |
| | 1044 | }}} |
| | 1045 | |
| | 1046 | you would get the warning on the kwlist assignment, but when you change |
| | 1047 | it to: |
| | 1048 | |
| | 1049 | {{{ |
| | 1050 | static const char *kwlist[] = {"fget", "fset", "fdel", "doc", 0}; |
| | 1051 | }}} |
| | 1052 | |
| | 1053 | you'll get: |
| | 1054 | |
| | 1055 | error: invalid conversion from ‘const char**’ to ‘char**’ |
| | 1056 | |
| | 1057 | unless you change the call to: |
| | 1058 | |
| | 1059 | {{{ |
| | 1060 | if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OOOO:property", |
| | 1061 | const_cast<char **>(kwlist), &get, &set, &del, &doc)) |
| | 1062 | }}} |
| | 1063 | |
| | 1064 | annoyingly having to incorrectly cast away the constness of kwlist. |
| | 1065 | Now the code is arguably correct and it wasn't before. |
| | 1066 | |
| | 1067 | |? || class does not have a virtual destructor||Suppress or provide a virtual destructor.||??|| |