In this code snippet, the Init() function acts as a on-demand initializer that fills in all member variables of the structure. This is done to avoid calling default constructors all members of a large array on the stack:
struct Foo {
int m_Member;
void Init(int i);
};
void Foo::Init(int i) {
m_Member = i;
// Many other members initialized here.
}
void SomeFunction(int n) {
Foo buffer[64];
assert(n <= 64);
// Explicitly initialize what is needed.
for (int i = 0; i < n; ++i) {
buffer[i].Init(i * 3);
}
// Use buffer[0] - buffer[n-1] somehow.
}
This triggers a static analysis error in VS2012 with /analyze:
warning C6001: Using uninitialized memory 'buffer'.: Lines: 17, 19, 20
I'm looking for a way to annotate Foo::Init() so that this warning doesn't occur. There are plenty of other ways to make the warning go away, including:
Adding an empty constructor
Moving Init() to the constructor and calling placement new in the loop
But I'd like to avoid changing the structure of the code.
I've tried the following annotation without success:
void _At_(this, _Out_) Init();
This syntax is accepted, but only changes the warning to be:
warning C6001: Using uninitialized memory 'buffer'.: Lines: 18, 20, 21
warning C6001: Using uninitialized memory 'buffer[BYTE:0]'.: Lines: 18, 20, 21
Does anyone know how I can declare the intent of this Init() function to the static analysis engine?
Your question is somewhat elusive. You have shown SomeFunction taking int, but want annotation for method Init or constructor.
The warning shown is absolutely correct, assert won't hide the warning. You need to put if to check if n is greateer than 64 and reset n (or do something else, but not to loop when n>=64).
For annotation you need to use __in_bcount or similar alternative. An example:
bool SetBuffer(__in_bcount(8) const char* sBuffer);
Whichs says sBuffer is of 8 bytes (not elements).
You can read this this article for more information.
Too ugly to add an extra helper?
struct Foo {
int m_Member;
void Init(int i);
};
void Foo::Init(int i) {
m_Member = i;
// Many other members initialized here.
}
void Initialize(__in_bcount(sizeof(Foo) * n) Foo* buffer, int n) {
// Explicitly initialize what is needed.
for (int i = 0; i < n; ++i) {
buffer[i].Init(i * 3);
}
}
void SomeFunction(int n) {
Foo buffer[64];
assert(n <= 64);
Initialize(buffer, n);
// Use buffer[0] - buffer[n-1] somehow.
}
I found a work around by implementing a function to index the array. I flagged the return value as invalid so that this new function only escapes the uninitialized value check in the specific case where the return value is only used to initialize. I've only tested this in VS2017.
#define _Ret_invalid_ _SAL2_Source_(_Ret_invalid_, (), _Ret1_impl_(__notvalid_impl))
template <typename T>
_Ret_invalid_ T& UninitialzedIndex(T* pt, int index)
{
return pt[index];
}
Then, where the value is indexed, I call UninitialzedIndex instead of operator[]
void SomeFunction(int n) {
Foo buffer[64];
if (n <= 64)
return;
// Explicitly initialize what is needed.
for (int i = 0; i < n; ++i) {
UninitialzedIndex(buffer, i).Init(i * 3);
}
// Use buffer[0] - buffer[n-1] somehow.
}
Just add a default constructor (that calls Init()). What is wrong with that?
[Edit] The root problem is not how to lie to the static analyzer or your compiler. It is how to enforce that you don't leave foo in an uninitialized state. There is nothing wrong with adding a default constructor. I'd say the desire to NOT do it imposes risk.
Perhaps some client will use that poorly constructed foo class (Long after you wrote it and long after you are gone) and perhaps they will forget to call .Init() ?? What then? They will be left with data that is uninitialized.
If you are looking to enforce that rule, no amount of static analysis will help you there.
Take care of the foundation before you put on the roof.
Related
i am new in this and i am working on App of media player and recording app. in which i have shown song list of device in the listview and recording start / stop / play. Now i want to convert that .mp3 recorded file into .mp4 and one image will show on behalf of a video in that file. Help me to achive this i have no idea and i refer many links and i didnt find anything.
Please check this link for your first question:
Why can't we initialize class members at their declaration?
Usually constructor is use to initialize value to data variables of class.
For 2nd Question:
If data member is not initialize after creation of object, It will contain garbage value. So initialize or assign suitable value to as per your need.
Check below code:
#include<iostream>
using namespace std;
class swap_values
{
int a, b, temp;
public:
swap_values(){
a=0;b=0;temp=0;
}
swap_values(int x, int y){
a = x;
b = y;
temp = 0;
}
void swapped()
{
temp = b;
b=a;
a=temp;
}
void print(){
cout<<"a: "<<a<<" b: "<<b<<endl;
}
};
int main()
{
int x =10; int y = 20;
swap_values obj(x, y);
obj.print();
obj.swapped();
obj.print();
return 0;
}
Everything can be done in better ways but just using your code this will work for you -
#include <iostream>
using namespace std;
class Swap {
private:
int a,b,temp;
public:
Swap()
{
a=10;
b=20;
temp=0;
}
void swapNums()
{
temp=a; a=b; b=temp;
cout<<a<<" " <<b<<endl;
}
};
int main() {
Swap s;
s.swapNums();
return 0;
}
You can avoid using class name as some function name. You can instead use constructor without a return type where you can initialise the member variables. swap method looks fine.
i am not able to initialize my variable in class.
class swap
{
int a=10; \\cannot declare here
int b=20; \\ cannot declare here
}
Since C++11, this is fine, you can have default member initialization.
The error is due to missing semicolon after }.
why it has garbage value with b ??
a=b;
b=temp;
temp=a;
Since temp was never initialized before assigning it to b, temp has an indeterminate value.
Any usage will lead to undefined behavior.
Here's a simple Swap struct:
struct Swap
{
int a = 10; // default member initialization
int b = 20; // default member initialization
Swap(int a = 20, int b = 10): a(b), b(a) {}; // swap on initialization
// using member initializer list
};
Swap s;
std::cout << s.a // 20
<< s.b // 10
<< std::endl;
In this example, default member initialization is "obsolete" / "redundant" due to member initializer list.
I would have posted this in the spinroot Bug Reports, but the spinroot forum is not currently accepting new users... If someone out there in charge of that is reading this, please let me in :)
Something very odd is happening when I try to use the select statement. Promela does not allow select() to be called on the field of a struct, so I have to make a temporary variable like this:
typedef someStruct {
int someField;
}
someStruct struct;
inline SetSelect() {
int temp;
select(temp: -1 .. 1);
struct.someField = temp;
}
init{
SetSelect();
}
This runs fine. I tested it and struct.someField is correctly set to either -1, 0, or 1. However, when I try to just put the inlined code straight into the init() process, I get a syntax error. The code looks like this:
typedef someStruct {
int someField;
}
someStruct struct;
init{
int temp;
select(temp: -1 .. 1);
struct.someField = temp;
}
And the error message is:
spin: select_test.pml:9, Error: syntax error saw ''-' = 45'
BUG:
Indeed, it looks like a bug for version 6.4.6 of Spin.
(The bug is fixed in version 6.4.7)
Interestingly, You can make it go away by simply writing temp : instead of temp:.
I suggest you to contact Gerard Holzmann for filing a bug report. I would also mention the fact that select does not seem to work with a struct field, perhaps that can be fixed too (even if it might be by design).
SUGGESTION:
I am not entirely happy of creating an alias variable to get around the issue of the built-in select function with struct fields. Since the implementation of select is rather trivial, as can be found in the docs, I would introduce a novel inline function to replace the built-in select function:
typedef Struct
{
int field;
}
inline my_select (var, lower, upper)
{
var = lower;
do
:: var < upper -> var++;
:: break;
od;
}
init
{
Struct st;
my_select(st.field, -1, 1);
printf("%d\n", st.field);
}
I have a question concerning working with classes in c++. I must say I'm a beginner. For example, i have this class:
class student {
private:
char* name;
public:
int nrcrt;
student() {
name = new char[7];
name = "Anonim";
nrcrt = 0;
}
student(char* n, int n) {
this->name = new char[7];
strcpy(name, n);
nrcrt = nr;
}
~student() {
delete [] name;
}
char* get_name() {
return this->name;
}
}
void main() {
student group[3];
group[0] = student("Ana", 1);
group[1] = student("Alex", 2);
group[2] = student("Liam", 5);
for (i=0; i<3; i++) {
if (group.nrcrt[i] != 0)
cout << group[i].get_name() << Endl;
}
}
My question is why is it displaying different characters?
first of all your code is not working.
3.cpp:40:18: error: request for member ‘nrcrt’ in ‘group’, which is of non-class type ‘student [3]’
if(group.nrcrt[i]!=0)
i is also not declared.please make proper changes.
group.nrcrt[i]
should be changed to:
group[i].nrcrt
When the array is created, your default constructor is used.
When you assign to the elements, your destructor is called, deleting name.
The default constructor is assigning a literal to name, and deleting that memory has undefined behaviour.
In your default constructor, replace
name = "Anonim";
with
strcpy(name, "Anonim");
Your compiler should have warned you about the assignment.
If it didn't, increase the warning level of your compiler.
If it did, start listening to your compiler's warnings.
do not worry. C++ could look a bit scary as first but it is ok when you get into it. First, let's say that all classes it is good to start with upper case letters. Secondly, you have two constructors (default without parameters and one or more with, in our case one). Default consructor you need to declare an array of objects:
Student group[3];
The next important thing is that you then do not need the rest of the constructors in that case.
group[0]=student("Ana",1);
group[1]=student("Alex",2);
group[2]=student("Liam",5);
Remember to include ; at the end of class declaration. To put all the statements and expression throughout your interation within the same loop. Here is what I found as an errors anf fix them. Could probably have more.
class Student
{
private:
char* name;
public:
int nrcrt;
Student()
{
name=new char[7];
strcpy(name, "Anonim");
nrcrt=0;
}
Student( char* n, int n)
{
this->name=new char[7];
strcpy(name, n);
nrcrt=nr;
}
~Student()
{
delete [] name;
}
char* get_name()
{
return this->name;
}
};
int main()
{
Student group[3];
for(int i=0;i<3;i++)
{
if(group.nrcrt[i]!=0)
cout<<group[i].get_name()<<endl;
}
return 0;
}
I am trying to check if my program is assigning memory correctly -
so i have series of pointers of different types,
pData1 = 0x844c458 ( result of malloc(5 * size of (double*))
pData2 = 0x844c470 (result of malloc (10 size of (double));
pData3 = 0x844c3a0(result of malloc(44 * size 0f (double*));
pData4 = 0x844c358
So i think double = 8 bytes , 5 *8 = 40 bytes, which means first two addresses will overlap and similarly last two ?
I am getting invalid free, so i am investigating a memory corruption in my code so trying to find where this might be happening.
-----Edit ------- Adding code details
THis is the struct -
struct _ELEMENT
{
short s;
char arr[20];
int size;
void *ptr1;
void *ptr2;
}ELEMENT;
There are two classes Parent and Derived ( child of Parent)
Class Parent
{
protected:
int size;
ELEMENT *ele1;
ELEMENT *ele2;
public:
void func();
...
}
Class Child::public Parent
{
int a,b,c;
}
Parent::Parent()
{
ele1 = NULL;
ele2= NULL;
}
Parent::~Parent()
{
for (int i =0; i< size; i++)
{
free(ele1[i].p1);
free(ele2[i].p1);
}
free(ele1);
free(ele2);
}
Child::Child()
{
a=0;...
}
Child::~Child()
{
for (int i =0; i< size; i++)
{
free(ele1[i].p1);
free(ele2[i].p1);
}
free(ele1);
free(ele2);
}
Parent::func ()
{
ele1 = (ELEMENT*)malloc (n * sizeof(ELEMENT));
ele2 = (ELEMENT*)malloc (n* sizeof(ELEMENT));
for (int i =0; i <somenumber; i++)
{
...some processing...
ele1[i].size = n;
ele2[i].size = x;
ele1[i].p1 = malloc (ele1[i].size);
ele2[i].p1 = malloc(ele2[i].size);
}
}
main ()
{
Parent *p;
CHild *c;
p = new Parent();
c= new Child();
p->func();
c->func();
delete(p);
delete(c);
}
The _glibc:invalid free comes at first free of parent destructor. This code was working fine in SOlaris for years but porting it in linux is giving this issue...
Thanks!
The answer to your question is that your program is allocating memory correctly, the first problem you had/have is that you don't know the size of your data types and so your computations are incorrect.
If you would post your code and the actual errors that you are getting, it's possible that we can figure this out. As it is, the deep problem of invalid free cannot be answered.
To whom it may concern, is this an answer or a comment?
sizeof(double) is 8 bytes and sizeof(double*) is 4 (on your 32 bit system).
Memory obtained by malloc will not overlap unless freed in the meantime.
Use a memory debugger such as valgrind
It looks that way... how did you end up with these pointers? In principle it's OK to have different pointers pointing to the same space - you just shouldn't be "freeing" except from a pointer that was assigned with malloc (or calloc). The glibc actually keeps some data "just below the pointer" that tells it how big the block is etc, so it can free "cleanly". If you change the value of the pointer, you can't "free part of a block" since the information about how big the block is isn't available (only if the pointer is unchanged). Could that be the source of your problem?
//Block.h
#pragma once
class Block
{
public:
CRect pos;
int num;
public:
Block(void);
~Block(void);
};
//view class
public:
Block currentState[5]; // stores the current state of the blocks
void CpuzzleView::OnDraw(CDC* pDC)
{
CpuzzleDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
if (!pDoc)
return;
//draw the 4 blocks and put text into them
for(int i=0;i<4;i++)
{
pDC->Rectangle(currentState[i].pos);
// i'm getting an error for this line:
pDC->TextOut(currentState[i].pos.CenterPoint(), currentState[i].num);
}
pDC->TextOut(currentState[i].pos.CenterPoint(), currentState[i].num);
The error says that no instance of overloaded function CDC::TextOutW() matches the argument list . But the prototype for the function is:
CDC::TextOutW(int x, int y, const CString &str )
all i've done is that instead of the 2 points i've directly given the point object returned by CenterPoint() ... shouldn't it work?
That's because you didn't supplied arguments list correctly. Please read compiler error message carefully, it's usually helps to solve the problem.
TextOut(currentState[i].pos.CenterPoint(), currentState[i].num);
In this call you passed CPoint object and int. This is not correct, you need to pass int, int and CString (or const char* and int length).
To fix this you shall do something like this:
CString strState;
strState.Format("%d", currentState[i].num); // Or use atoi()/wtoi() functions
TextOut(currentState[i].pos.CenterPoint().x, currentState[i].pos.CenterPoint().x, strState);