C++ Code Smell: Incorrect Initializer Braces Placement - c++

I am trying to fix the following code smell within my C++ code generated from Klocwork(KW):
MISRA.INIT.BRACES: Incorrect initializer braces placement
Below is a snippet of the code I am attempting to clean this up on.
typedef char charString[10];
enum SomeEnum
{
BLAH1_e,
BLAH2_e,
BLAH3_e
};
struct ParentStruct
{
SomeEnum myEnumValue;
charString myCharStringValue;
};
// This is the the part that KW is not happy about
// KW complaining about initializer bracer placement
const ParentStruct myParent[3] =
{
{BLAH1_e, "String1"},
{BLAH2_e, "String2"},
{BLAH3_e, "String3"}
}
I've attempted many variations of bracer placement and can't seem to figure out the exact issue with bracer placement I currently have. This doesn't generate any compile errors nor does this have a negative outcome on the code. Maybe it's just KW but just wanted to get some thoughts before I give up completely.
Below is an alternative bracer placement I attempted as well in case someone throws it out as an answer:
// compiles but KW does not like this as well
const ParentStruct myParent[3] =
{
{BLAH1_e, {"String1"}},
{BLAH2_e, {"String2"}},
{BLAH3_e, {"String3"}}
}

Please do run the analysis with the latest version of Klocwork and check if this issue has been reported by Klocwork at your end.
I am using Klocwork 2021.3 and it seems that MISRA.INIT.BRACES checker is not reporting any issue on your code as expected.

Related

Cannot access member functions of vector<int>

I've been attempting to figure out this bug for about an hour now. It's probably a really obvious syntax thing I'm overlooking. This is my first C++ project, and I don't have a good handle on the structure of the language.
Here's my header file:
#pragma once
#include <vector>
class BoardState
{
private:
std::vector<int> numbers;
int SIZE;
public:
BoardState();
std::vector<int> getState();
bool isZero();
};
And here's the implementation, in a separate file:
#include "BoardState.h"
BoardState::BoardState(){
SIZE = 4;
numbers.push_back(1);
numbers.push_back(3);
numbers.push_back(5);
numbers.push_back(7);
}
std::vector<int> BoardState::getState() { return numbers; }
bool BoardState::isZero() {
for (int i = 0; i < numbers.size(); i++) {
if (numbers[i] != 0) { return false; }
}
return true;
}
This code is really simple, so I have no clue what could be going wrong to produce the errors. However, on every method call, push_back and size, I am getting errors, saying that class "std::vector<int, allocator>" has no member "method_name_here".
My background is Java, so my first thought was that I wasn't able to call these methods because numbers is not initialized. However, any attempt I made to initialize numbers in the header file resulted in an error as well. I tried std::vector<int> numbers = { 1,3,5,7 };, I tried std::vector<int> numbers(4,0);, I even tried creating an array and constructing the vector from that. Not only did all those attempts cause errors, they also didn't fix the method calls either.
What am I missing? Do I need to initialize the vector, or is what I have in the header file enough? Any advice would be helpful here, since I can't find anything online about similar errors. I've even copy-pasted code from StackOverflow answers about similar problems, and that produced errors as well.
EDIT: I've pared down the code as much as possible while keeping the error:
#include <vector>
class BoardState
{
std::vector<int> numbers;
BoardState() { numbers.push_back(1); }
int getSize() {
int i = numbers.size();
return i;
}
};
On the line numbers.push_back(1);, my compiler underlines the token "push_back", and highlighting it reads:
class "std::vector<int, allocator>" has no member "push_back"
On the line int i = numbers.size();, the token "size" is underlined, and the error reads:
class "std::vector<int, allocator>" has no member "size"
I still have no clue what's going on.
Edit 2: Put the method calls into a constructor and a function. This changed the error message associated with push_back().
Edit 3: I have discovered something very disconcerting. This code works perfectly fine in a different compiler. I copy-pasted in the exact code from Edit 1 and it ran with no issues. I think the problem must be with Visual Studio rather than the actual code. Thank you all for helping me out with this. I think I'm just going to switch to a different compiler and hope for the best.
Edit 4: Just to prove to pm100 that my code is exactly as I've said, here's a screenshot from visual studio.
Here it is.
Aside from the main method, this is character-for-character what I've put in this question. I have a guess as to why this doesn't work, though. I modified my version of Visual Studio 2019 to run .386 assembly code for a college class. While I think I followed the guide to do that without affecting anything else, it may have screwed up parts of the C++ compiler.
I suggest that you could select Tools->Import and Export Settings->Reset all settings-> Visual C++ to restore the default settings.
If it does not work, you could reinstall VS.

error C2797 : list initialization inside member initializer list

I was watching MVA's tutorial on C++ and the code I'm mentioning below is written by Kate not me. However she seems to get around with it without compiling showing any error but in my case I get the following error:
Error 1 error C2797: 'NamedRectangle::_name': list initialization
inside member initializer list or non-static data member initializer
is not implemented c:\users\abhimanyuaryan\documents\visual studio
2013\projects\kate demos\17
inheritance\inheritance\namedrectangle.h 12 1 Inheritance
Line 12 in the code is from my NameRectangle class which inherits from Rectangle class:
class NamedRectangle : public Rectangle
{
public:
NamedRectangle() { }
NamedRectangle(std::string initial_name, int initial_width, int initial_height)
: Rectangle{ initial_width, initial_height }, _name{ initial_name } //--> This line
{}
std::string get_name() const { return _name; }
private:
std::string _name;
};
when I remove std::string initial_name from constructor as well as _name{initial_name} the code compiles. Please explain me with not taking me as a higher standard experienced programmer. I started C++ yesterday only.
tl;dr: The solution in Kate's answer worked for the OP; the explanation is incorrect. The code in question is actually correct and does compile in VS2015. The error (in VS2013 Update 3) is a consequence of how MS handled a bug that was uncovered in VS2013 RTM (they didn't actually fix it with an update, but they did break some working code). It is fixed correctly in VS2015.
Your code works fine in VS2015. According to Microsoft, in VS2013,
Yes, we inserted these errors into the compiler in Update 3 because our implementation of non-static data member initialization was incomplete.
List/braced initialization in a member initialization list is also broken in VS2013. The problem with their implementation is illustrated best with a vector, which has an initializer_list constructor that should greedily match any initialization that uses braces with convertable arguments, but it fails to do so:
struct S {
S() : v1{1} {} // C2797, VS2013 RTM incorrectly calls 'vector(size_type)'
std::vector<int> v1;
std::vector<int> v2{1, 2}; // C2797, VS2013 RTM incorrectly calls
// 'vector(size_type, const int &)'
};
The compiler too readily falls back to normal overload resolution. Instead of using the std::initializer_list constructor, it calls the size_t constructor. As their comments indicate, this is wrong! So, because of their flawed implementation, Microsoft decided to disable the ability to use braced initialization in this context.
For a std::string s, there should be no issue because the right thing for s{"duh"} is to call std::string(const char*), but because of the flaw, MS gives an error anyway. The workaround is to explicitly use parenthesis in place of braces (or upgrade to VS2015), as stated in Kate's answer. But the correct reason for the error is as stated above.
This applies to Non-Static Data Member Initialization (NSDMI) as well as to initialization lists. This is explained more in this Visual C++ Team Blog. As for why VS2013 never got fixed:
We originally planned to fix this bug in an update to Visual Studio 2013, but from an engineering perspective, the right thing to do is to avoid another kludge and thoroughly address the handling of initialization. But overhauling compiler architecture is a massive task due to the amount of fundamental code that needs to be modified. We could not risk creating incompatibilities or large bug tails in an update, so a correct implementation of NSDMI could only be shipped in a major release.
Apparently, the fix made it into Visual Studio 2015, but will never be in an update to 2013.
There was a compiler change between the time James and I wrote the code we used for the MVA day and today. What's happening is that
_name{ initial_name }
is being interpreted as creating an initializer-list with one item in it and using that to initialize the member variable. Which you can't do.
The fix is to switch to round brackets:
_name(initial_name)
This is causing confusion for a number of people and I have at least one client for whom this broke working code.
I solve it.
class Namedrectangle : public Rectan
{
public:
Namedrectangle(){}
Namedrectangle(string intname, int init_width, int init_height)
: Rectan{ init_width, init_height }
{
this->_name=intname;************
}
string get_name() const
{
return _name;
}
private:
string _name;
};
I think İt can't initialize because variable can't find or load

Calling Function Overwrites Value

I have several configuration flags that I am implementing as structs. I create an object. I call a method of the object with a flag, which eventually triggers a comparison between two flags. However, by this time, one of the flags has been overwritten somehow.
To clarify, here's a VERY simplified version of the code that should illustrate what I'm seeing:
class flag_type { unsigned int flag; /*more stuff*/ };
flag_type FLAG1
flag_type FLAG2
class MyObject {
public:
void method1(const flag_type& flag_arg) {
//conditionals, and then:
const flag_type flag_args[2] = {flag_arg,flag_arg};
method2(flag_args);
}
void method2(const flag_type flag_args[2]) {
//conditionals, and then:
method3(flag_args[0]);
}
void method3(const flag_type& flag_arg) { //Actually in a superclass
//stuff
if (flag_arg==FLAG1) { /*stuff*/ }
//stuff
}
};
int main(int argc, const char* argv[]) {
//In some functions called by main:
MyObject* obj = new MyObject();
//Later in some other functions:
obj->method1(FLAG1);
}
With a debugger and print statements, I can confirm that both FLAG1 and flag_arg/flag_args are fine in both "method1" and "method2". However, when I get to method3, "FLAG1.flag" has been corrupted, so the comparison fails.
Now, although I'm usually stellar about not doing it, and it passes MSVC's static code analysis on strictest settings, this to me looks like the behavior of a buffer overrun.
I haven't found any such error by looking, but of course one usually doesn't. My question isA: Am I screwing up somewhere else? I realize I'm not sharing any real code, but am I missing something already? This scheme worked before before I rewrote a large portion of the code.
B: Is there an easier way than picking through the code more carefully until I find it? The code is cross-platform, so I'm already setting it up to check with Valgrind on an Ubuntu box.
Thanks to those who tried to help. Though, it should be noted that the code was for clarification purposes only; I typed it from scratch to show generally was was happening; not to compile. In retrospect, I realize it wasn't fair to ask people to solve it on so little information--though my actual question "Is there an easier way than picking through the code more carefully" didn't really concern actually solving the problem--just how to approach it.
As to this question, on Ubuntu Linux, I got "stack smashing" which told me more or less where the problem occurred. Interestingly, the traceback for stack smashing was the most helpful. Long story short, it was an embarrassingly basic error; strcpy was overflowing (in the operators for ~, | and &, the flags have a debug string set this way). At least it wasn't me who wrote that code. Always use strncpy, people :P

Anonymous Functions, "Parse Issue: Expected Expression"

I'm getting the titular error, but I can't for the life of me figure out how to resolve it. I've scoured the internet a fair bit, but for the most part I can't find anything that pertains directly to, or solves, the problem I'm having, and all the information I read about anonymous classes, seems to agree with the code I wrote.
The essence of what I'm trying to do is; I have a struct, and I want that struct to contain a function pointer. What I'm having trouble with is when I define an instance of the struct, I'm trying to create and pass an anonymous function to the struct. But it's giving me a compile error.
Anyways, here are the details of the actual problem, the error occurs on this line,
[&](int x) { this->moveLeft(); };
It says "Parse Issue: Expected expression" and points to the ']'
of the following code
Combatant::CharacterData Combatant::characters = {
/*Name */"SomeName",
/*Folder */"SomeFolder",
/*Offense */1.0f,
/*Defense */1.0f,
/*Combos */{
{KeyMemory(KeyMemory::MOVE_LEFT, KeyMemory::JUMP),
[&](int x) { this->moveLeft(); };
},
{KeyMemory(KeyMemory::MOVE_LEFT, KeyMemory::JUMP),
[&](int x) { this->moveLeft(); };
}
}
}
The CharacterData struct is defined by this code:
struct Combo {
KeyMemory controls;
void (*execute)(int);
};
struct CharacterData {
std::string name;
std::string folder;
float offense;
float defense;
Combo comboList[5];
};
Any help, would be much appreciated. ^_^
You might need to use a std::function<void(int)> to hold your lambda. (Particularly since you are using [&]).
Also, I'm not sure [&] actually makes sense in a global context. Maybe you should be passing in the object to call moveLeft on, and using []. Also, that change might let you use your simple function pointer instead of a std::function.
The problem turned out to be that Clang, which is the compiler used by Xcode/Apple doesn't yet support lambda functions. From what I read however the feature is coming in the future.

What could cause initialization order to corrupt the stack?

Question is in bold below :
This works fine:
void process_batch(
string_vector & v
)
{
training_entry te;
entry_vector sv;
assert(sv.size() == 0);
...
}
However, this causes the assert to fail :
void process_batch(
string_vector & v
)
{
entry_vector sv;
training_entry te;
assert(sv.size() == 0);
...
}
Now I know this issue isn't shrink wrapped, so I'll restrict my question to this: what conditions could cause such a problem ? Specifically: variable initialization getting damaged dependant on appearance order in the stack frame. There are no malloc's or free's in my code, and no unsafe functions like strcpy, memcpy etc... it's modern c++. Compilers used: gcc and clang.
For brevity here are the type's
struct line_string
{
boost::uint32_t line_no;
std::string line;
};
typedef std::vector<boost::uint32_t> line_vector;
typedef std::vector<line_vector> entry_vector;
typedef std::vector<line_string> string_vector;
struct training_body
{
boost::uint32_t url_id;
bool relevant;
};
struct training_entry
{
boost::uint32_t session_id;
boost::uint32_t region_id;
std::vector< training_body> urls;
};
p.s., I am in no way saying that there is a issue in the compiler, it's probably my code. But since I am templatizing some code I wrote a long time ago, the issue has me completely stumped, I don't know where to look to find the problem.
edit
followed nim's suggestion and went through the following loop
shrink wrap the code to what I have shown here, compile and test, no problem.
#if 0 #endif to shrink wrap the main program.
remove headers till it compiles in shrink wrapped form.
remove library links till compiles in shrink wrapped form.
Solution: removing link to protocol buffers gets rid of the problem
The C++ standard guarantees that the following assertion will succeed:
std::vector<anything> Default;
//in your case anything is line_vector and Default is sv
assert(Default.size() == 0);
So, either you're not telling the whole story or you have a broken STL implementation.
OR: You have undefined behavior in your code. The C++ standard gives no guarantees about the behavior of a program which has a construct leading to UB, even prior to reaching that construct.
The usual case for this when one of the created objects writes beyond
its end in the constructor. And the most frequent reason this happens
in code I've seen is that object files have been compiled with different
versions of the header; e.g. at some point in time, you added (or
removed) a data member of one of the classes, and didn't recompile all
of the files which use it.
What might cause the sort of problem you see is a user-defined type with a misbehaving constructor;
class BrokenType {
public:
int i;
BrokenType() { this[1].i = 9999; } // Bug!
};
void process_batch(
string_vector & v
)
{
training_entry te;
BrokenType b; // bug in BrokenType shows up as assert fail in std::vector
entry_vector sv;
assert(sv.size() < 100);
...
}
Do you have the right version of the Boost libaries suited for your platform? (64 bit/32 bit)? I'm asking since the entry_vector object seems to be have a couple of member variables of type boost::uint32_t. I'm not sure what could be the behaviour if your executable is built for one platform and the boost library loaded is of another platform.