how to detect or avoid using C++ uninitialized pointer? [closed] - c++

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 7 years ago.
Improve this question
I got an uninitialized pointer problem today. unfortunately, it caused core dump after it released.
here is the sample code, and the function print_request() is new code, and this function could be used by several other functions:
// def.h
struct INFO {
uint32_t val1;
uint32_t val2;
};
struct INFO_LIST {
uint32_t id;
struct INFO * data;
};
// util.cpp
void print_request(const struct INFO_LIST req)
{
fprintf(stdout, "%u\t%u\t%u\n", req.id, req.data->val1, req.data->val2);
}
// A.cpp
int parse_ie(...)
{
// ...
struct INFO_LIST req;
req.id = 10;
req.data = new INFO();
req.val1 = 101;
req.val2 = 102;
print_request(req);
// ...
}
// B.cpp
int parse_chrome(...)
{
// ...
struct INFO_LIST req;
req.id = 20;
print_request(req); // core dump here!
// ...
}
here is what I have done:
I have wroten the unit test for print_request(), but I forgot there is an uninitialized pointer while function parse_chrome() use it.
I analyzer the code by using the static code analyzer tool, for example, cppcheck, and there is no error or warning.
it is still ignored after code reviewing.
so, I want to know:
is there any good tool to detect the uninitialized pointer in C++?
how to avoid using uninitialized pointer in C++?
any suggestion would be appreciated, thank you!
PS, I want to write uniform functions to call the pointer, but it would cost much time.
PPS. sorry, variable "req" is not a pointer. my fault.

First, add a default constructor to INFO_LIST:
struct INFO_LIST {
uint32_t id;
struct INFO * data;
INFO_LIST() : id(0), data(nullptr) { ; }
};
Second: Throw an exception in print_request:
// util.cpp
void print_request(const struct INFO_LIST req)
{
if (! req.data->val1 || ! req.data->val2)
throw (std::runtime_error ("Uninitialized pointers"));
fprintf(stdout, "%u\t%u\t%u\n", req.id, req.data->val1, req.data->val2);
}
If you want to catch this at compile time:
struct INFO_LIST {
uint32_t id;
struct INFO * data;
INFO_LIST (struct INFO* d) : data(d) { ; }
private:
INFO_LIST () { ; }
};
Now you will get an error at compile time if you try to construct an INFO_LIST without initializing the data pointer.

You have created a struct pointer at line INFO_LIST * req;, remove a * to create a struct instead. Currently you are using a bare pointer (of type struct INFO_LIST) to nothing.

How avoid using a c++ empty pointer?
Your code looks like c, to me. The languages are different, pick one or the other.
As to your question title:
In C++, you can use the non-nullptr value tested as:
if(ptr) ptr->doSomething();
else doSomethingElse();
NOTE that pointers are POD, and must be explicitly initialized.
So
MyObject* ptr = new MyObject; // default ctor
assert(nullptr != ptr); // check for success
or
MyObject* ptr = nullptr;
// later code sets the pointer to something
I prefer to use the slightly more clear:
if(nullptr != ptr) ptr->doSomething();

Related

What is wrong with this void pointer to struct cast? [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question does not appear to be about programming within the scope defined in the help center.
Closed 2 years ago.
Improve this question
The task here is to call out everything that is wrong with this snippet. I do not know if the code is being presented as C or C++, so either assumption is valid and helpful.
struct MyStructData
{
VOID* pPtr;
UINT32 flags;
}
VOID main()
{
MyStructData* pMyStructData = InitFunction();
// work done here
DeInitFunction(pMyStructData);
}
MyStructData* InitFunction()
{
MyStructData* pMyStructData = malloc(sizeof(MyStructData));
pMyStructData->pPtr = malloc(1024);
return pMyStructData;
}
VOID DeInitFunction(MyStructData* pMyStructData)
{
free(pMyStructData);
}
I see the void pointer is declared, then in InitFunction, pMyStructData has malloc with size of the struct MyStructData. Next the pPtr member is accessed and malloc-ed a big chunk (1024)... this is where I see an issue. Since the pPtr member was declared as void, pMyStructData is too small to allocate 1024 bytes?
Please help me to understand what is happening here, and what I missed.
Answer was provided before language tag was changed from C to C++.
struct MyStructData
{
VOID* pPtr;
UINT32 flags;
}
There are no types VOID or UINT32 in C unless you include some headers providing them. Maybe some Windows stuff?
Also a ; is missing after that struct declaration. (Thanks to wildplasser)
VOID main()
Valid signatures for main are int main(void) or int main (int argc, char *argv[]) or compatible.
{
MyStructData* pMyStructData = InitFunction();
There is no type MyStructData. Use struct MyStructData or add a typedef.
You do not provide a prototype for InitFunction().
// work done here
DeInitFunction(pMyStructData);
}
Same here: No prototype for DeInitFunction
MyStructData* InitFunction()
{
MyStructData* pMyStructData = malloc(sizeof(MyStructData));
Again: Use struct MyStructData.
Use of malloc without prototype. Include proper headers.
pMyStructData->pPtr = malloc(1024);
Basically valid (except for missing prototype), but you should check if pMyStructData is NULL before dereferencing it.
return pMyStructData;
}
VOID DeInitFunction(MyStructData* pMyStructData)
{
free(pMyStructData);
}
As Johnny Mopp mentioned, pMyStructData->pPtr is not freed causing a memory leak.
Again: No type VOID and MyStructData.
Again: Use of function (free) without prototype.
Now regarding your findings:
I see the void pointer is declared, then in InitFunction, pMyStructData has
malloc with size of the struct MyStructData.
Apart from the issues I mentioned abov, that is fine. That is how allocating memory for structs is don.
Next the pPtr member is accessed and malloc-ed a big chunk (1024)... this
is where I see an issue. Since the pPtr member was declared as void,
pMyStructData is too small to allocate 1024 bytes?
That is no issue. The member ptr points to some memory provided by malloc There is no relation to the struct where the pointer itself resides. It does not need to fit into the struct.
You only should check for NULL before this.

Save reference to void pointer in a vector during loop iteration

Guys I have a function like this (this is given and should not be modified).
void readData(int &ID, void*&data, bool &mybool) {
if(mybool)
{
std::string a = "bla";
std::string* ptrToString = &a;
data = ptrToString;
}
else
{
int b = 9;
int* ptrToint = &b;
data = ptrToint;
}
}
So I want to use this function in a loop and save the returned function parameters in a vector (for each iteration).
To do so, I wrote the following struct:
template<typename T>
struct dataStruct {
int id;
T** data; //I first has void** data, but would not be better to
// have the type? instead of converting myData back
// to void* ?
bool mybool;
};
my main.cpp then look like this:
int main()
{
void* myData = nullptr;
std::vector<dataStruct> vec; // this line also doesn't compile. it need the typename
bool bb = false;
for(int id = 1 ; id < 5; id++) {
if (id%2) { bb = true; }
readData(id, myData, bb); //after this line myData point to a string
vec.push_back(id, &myData<?>); //how can I set the template param to be the type myData point to?
}
}
Or is there a better way to do that without template? I used c++11 (I can't use c++14)
The function that you say cannot be modified, i.e. readData() is the one that should alert you!
It causes Undefined Behavior, since the pointers are set to local variables, which means that when the function terminates, then these pointers will be dangling pointers.
Let us leave aside the shenanigans of the readData function for now under the assumption that it was just for the sake of the example (and does not produce UB in your real use case).
You cannot directly store values with different (static) types in a std::vector. Notably, dataStruct<int> and dataStruct<std::string> are completely unrelated types, you cannot store them in the same vector as-is.
Your problem boils down to "I have data that is given to me in a type-unsafe manner and want to eventually get type-safe access to it". The solution to this is to create a data structure that your type-unsafe data is parsed into. For example, it seems that you inteded for your example data to have structure in the sense that there are pairs of int and std::string (note that your id%2 is not doing that because the else is missing and the bool is never set to false again, but I guess you wanted it to alternate).
So let's turn that bunch of void* into structured data:
std::pair<int, std::string> readPair(int pairIndex)
{
void* ptr;
std::pair<int, std::string> ret;
// Copying data here.
readData(2 * pairIndex + 1, ptr, false);
ret.first = *reinterpret_cast<int*>(ptr);
readData(2 * pairIndex + 2, ptr, true);
ret.second = *reinterpret_cast<std::string*>(ptr);
}
void main()
{
std::vector<std::pair<int, std::string>> parsedData;
parsedData.push_back(readPair(0));
parsedData.push_back(readPair(1));
}
Demo
(I removed the references from the readData() signature for brevity - you get the same effect by storing the temporary expressions in variables.)
Generally speaking: Whatever relation between id and the expected data type is should just be turned into the data structure - otherwise you can only reason about the type of your data entries when you know both the current ID and this relation, which is exactly something you should encapsulate in a data structure.
Your readData isn't a useful function. Any attempt at using what it produces gives undefined behavior.
Yes, it's possible to do roughly what you're asking for without a template. To do it meaningfully, you have a couple of choices. The "old school" way would be to store the data in a tagged union:
struct tagged_data {
enum { T_INT, T_STR } tag;
union {
int x;
char *y;
} data;
};
This lets you store either a string or an int, and you set the tag to tell you which one a particular tagged_data item contains. Then (crucially) when you store a string into it, you dynamically allocate the data it points at, so it will remain valid until you explicitly free the data.
Unfortunately, (at least if memory serves) C++11 doesn't support storing non-POD types in a union, so if you went this route, you'd have to use a char * as above, not an actual std::string.
One way to remove (most of) those limitations is to use an inheritance-based model:
class Data {
public:
virtual ~Data() { }
};
class StringData : public Data {
std::string content;
public:
StringData(std::string const &init) : content(init) {}
};
class IntData : public Data {
int content;
public:
IntData(std::string const &init) : content(init) {}
};
This is somewhat incomplete, but I think probably enough to give the general idea--you'd have an array (or vector) of pointers to the base class. To insert data, you'd create a StringData or IntData object (allocating it dynamically) and then store its address into the collection of Data *. When you need to get one back, you use dynamic_cast (among other things) to figure out which one it started as, and get back to that type safely. All somewhat ugly, but it does work.
Even with C++11, you can use a template-based solution. For example, Boost::variant, can do this job quite nicely. This will provide an overloaded constructor and value semantics, so you could do something like:
boost::variant<int, std::string> some_object("input string");
In other words, it's pretty what you'd get if you spent the time and effort necessary to finish the inheritance-based code outlined above--except that it's dramatically cleaner, since it gets rid of the requirement to store a pointer to the base class, use dynamic_cast to retrieve an object of the correct type, and so on. In short, it's the right solution to the problem (until/unless you can upgrade to a newer compiler, and use std::variant instead).
Apart from the problem in given code described in comments/replies.
I am trying to answer your question
vec.push_back(id, &myData<?>); //how can I set the template param to be the type myData point to?
Before that you need to modify vec definition as following
vector<dataStruct<void>> vec;
Now you can simple push element in vector
vec.push_back({id, &mydata, bb});
i have tried to modify your code so that it can work
#include<iostream>
#include<vector>
using namespace std;
template<typename T>
struct dataStruct
{
int id;
T** data;
bool mybool;
};
void readData(int &ID, void*& data, bool& mybool)
{
if (mybool)
{
data = new string("bla");
}
else
{
int b = 0;
data = &b;
}
}
int main ()
{
void* mydata = nullptr;
vector<dataStruct<void>> vec;
bool bb = false;
for (int id = 0; id < 5; id++)
{
if (id%2) bb = true;
readData(id, mydata, bb);
vec.push_back({id, &mydata, bb});
}
}

join structs in c++? [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
I'm trying to create an ethernet packet plus TCP/IP payload, for that I've create three structs as follows: ethernet struct, tcp struct and ip struct all these structs are filled with valid information but I don't know what I need to do now, I need join the spared structs into a plain struct (such as an array) since I want to inject the constructed packet and all bits need to be consecutive.
Define a new class, make these three structs its instance variables, code setters and getters for the class. You may want to pay attention to const correctness when writing getters - mark getters with const keyword.
struct EthStruct1
{
// ...
};
struct EthStruct2
{
// ...
};
struct EthStruct3
{
// ...
}
class newClass
{
public :
newClass(){}
~newClass(){}
// Add functions to get and set values in A. Mark getters with const for immutability of receiver
// Add functions to get and set values in B. Mark getters with const for immutability of receiver
// Add functions to get and set values in C. Mark getters with const for immutability of receiver
private:
EthStruct1 A;
EthStruct2 B;
EthStruct3 C;
};
Declare a byte array whose size is the sum of the sizes of the three structs. Then copy the raw bytes of each struct into the array where needed. Then use the array as needed.
struct ethernet
{
...
};
struct tcp
{
...
};
struct ip
{
...
};
ethernet e;
tcp t;
ip i;
unsigned char arr[sizeof(e)+sizeof(t)+sizeof(i)];
memcpy(&arr[0], &e, sizeof(e)];
memcpy(&arr[sizeof(e)], &t, sizeof(t)];
memcpy(&arr[sizeof(e)+sizeof(t)], &i, sizeof(i)];
Alternatively:
struct ethernet
{
...
};
struct tcp
{
...
};
struct ip
{
...
};
struct pkt
{
ethernet e;
tcp t;
ip i;
};
ethernet e;
tcp t;
ip i;
unsigned char arr[sizeof(pkt)];
pkt *p = (pkt) &arr[0];
p->e = e;
p->t = t;
p->i = i;
I like to use union when converting structures to byte arrays. Be sure your compiler is using single-byte structure alignment... for the Windows compiler I know you can use #pragma pack(push,1) to start that and #pragma pack(pop) to terminate. I will use this way in my example.
#pragma pack(push,1) // start single-byte struct alignment
struct EthernetInfo
{
// data here
};
struct TCPInfo
{
// data here
};
struct IPInfo
{
// data here
};
union Packet
{
struct {
struct EthernetInfo ethernetInfo;
struct TCPInfo tcpInfo;
struct IPInfo ipInfo;
} AsPacket;
unsigned char AsBytes[sizeof(EthernetInfo) + sizeof(TCPInfo) + sizeof(IPInfo)];
};
#pragma pack(pop) // revert to whatever struct alignment was in use before

c++: fstream::seekp changes the value of a variable it doesn't control [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question appears to be off-topic because it lacks sufficient information to diagnose the problem. Describe your problem in more detail or include a minimal example in the question itself.
Closed 8 years ago.
Improve this question
In the program, the writeSector function calls seekToSector. When seekToSector calls seekp, the sec variable from writeSector is changed. Can anyone explain why or give a solution?
#include<iostream>
#include<fstream>
#include<string>
using namespace std;
class Sector
{
public:
int num;
char data[1020];
Sector()
{
num = -1;
for(int i=0;i<1020;i++)
data[i] = (char)0;
}
Sector(int n,string str)
{
num = n;
for(int i=0;i<str.length();i++)
data[i] = str[i];
}
string toData()
{
string str = to_string(num);
for(int i=0;i<1020;i++)
str += data[i];
return str;
}
};
class Disk
{
public:
fstream dskfl;
int currentPos;
void seekToSector(int index)
{
currentPos = index;
dskfl.seekp(1024*currentPos);
}
void writeSector(int index, Sector * sec)
{
seekToSector(index);
dskfl.write(sec->toData().c_str(),1024);
}
};
Sector * func()
{
Sector sec(0,"something");
return &sec;
}
void main()
{
Disk disk;
disk.dskfl.open("name",ios::binary | ios::out);
disk.writeSector(0,func());
}
func() returns the address of an object allocated on the stack. But when the function exits, that address is no longer valid. Additionally, if the object has a destructor (or if its members have destructors) that destructor is called.
I'm not clear why you want a pointer to an object instead of the object itself. Assuming you really want a pointer, you'll have to new it up so that the pointer will remain valid after func() returns (and delete it when you're done).
Alternatively, you can just return the object itself:
Sector func()
{
return Sector(0,"something");
}
Of course, you'll have to modify code that calls func() accordingly.
There are people who will complain about returning a large-ish object like Sector. However, in this case you can rely on the compiler being smart and returning the Sector efficiently ("return value optimization").

How to set data with 0 in C++? [duplicate]

This question already has answers here:
Initializing an object to all zeroes
(12 answers)
Closed 9 years ago.
In C we set data to 0 with memset() function (Not only for the initialization).
My data could be changed by another method and I want to reuse it and then I want to set it to 0 before reusing it
Are there another way to set data to 0 in C++ other than memset()?
class MYClass : public NameSpace::ParentClass {
private:
struct mystruct data
public:
void method();
};
void MYClass::method() {
memset(&data, 0, sizeof(data)); // it's the C way. Are there another way in C++
}
In C++ you would invoke the constructor of an object, or the initialiser for primitive constructor-less objects.
Re-initialisation should actually happen very rarely (don’t reuse variables, create new ones! It makes the program flow clearer) – but when you need it you can just re-assign a new object:
data = mystruct();
It is ok to use memset on POD types, otherwise initialization must be done using constructor.
The C++ way of zeroing should look like the following:
struct mystruct
{
int i;
void Reset();
}
class MYClass : public NameSpace::ParentClass
{
private:
mystruct data
public:
void method();
};
void mystruct::Reset()
{
i = 0;
}
void MYClass::method()
{
data.Reset();
}