I am actually working on some changes to my application and klocwork keeps complaining me about one issue:
I have a struct, say
Struct A
{
long x;
bool b;
}
I have a pointer and it is assigned a return value from another function:
A* z= (A*) function.get();
if(!z->x)
{
z->x= somevalue;
}
The klocwork keeps pointing to if(!z->x), saying that z is explicitly dereferenced.
Although my application works fine now, will it affect my application in a drastic way in future?
You need to first check whether z is non-null before deferencing z and checking for z->x.
if(z && !z->k)
...
Related
I am trying to write a D wrapper for a C library (libmpdec) that stores its data using the standard C malloc function. But the are
some nasty bugs in my programs that I don't know how to solve.
So I have written the following test example, trying to understand this. The idea is to create structure holding a pointer to a memory area allocated using malloc in the constructor and that contains a zero-terminated C string, and free the area using the destructor. Also I can print the string using printf. The problem arises when I try to implement a method toString() so that I can use the standard D function writeln. For some reason that I don't understand the destructor seems to be called twice! (one after writeln) and so a segmentation fault occurs.
import std.stdio;
import core.stdc.stdlib;
import std.string;
import core.stdc.string;
struct Prueba {
char* pointer;
string name;
this(string given_name)
{
writeln("calling the constructor");
pointer= cast (char*) malloc(char.sizeof*10);
name=given_name;
char* p= pointer;
*p= 'a';
p++;
*p= 'b';
p++;
*p= '\n';
p++;
*p= '\0';
}
~this()
{
writeln("\n calling the destructor");
free(pointer);
}
void print()
{
printf("Using printf %s \n",pointer);
}
string toString()
{
ulong len=strlen(pointer);
return cast(string) pointer[0..len];
}
}
void main()
{
writeln("version 1");
Prueba p=Prueba("a");
writeln("using writeln ",p);
p.print();
}
But if I store the result in a string varible like
string s=p.toString();
writeln("using writeln ",s);
The program just works! I cannot figure out why!
You can see both versions of my test program at
https://github.com/pdenapo/example_programs_in_D/tree/master/using_malloc
Many thanks for any help!
Update: It seems that writeln plays no role here. And I can get the
same result with something like
void probando(Prueba q)
{
q.print();
}
probando(p);
The problem seems to be that a copy of p is created when calling a function.
In cases like this, it's often a good idea to see if it's the same instance being destroyed. Adding &this to the writeln calls, I get this output:
version 1
calling the constructor at 6FBB70F960
Instance on stack: 6FBB70F960
using writeln ab
calling the destructor at 6FBB70F820
calling the destructor at 6FBB70F7F0
As we can see, the pointers are different, so there's two instances.
D structs are value types, and so are copied and moved. When you call a function taking a class parameter, a pointer is what's actually being passed, and it basically says 'the class instance you're looking for is over there'. With structs a copy is created, and suddenly you have two independent objects living their separate lives.
Of course, that's not what you want - Prueba isn't actually a copyable type, since having two copies will result in two calls to the destructor, and thus double freeing. To mark it as non-copyable, simply add #disable this(this); to disable the postblit, and the compiler will helpfully throw error messages at you when a copy would be created.
This will cause a compiler error on the writeln line, and you will have to manually call toString, e.g.: writeln("using writeln ", p.toString());
Note that a non-copyable struct may be passed to functions as ref, since that doesn't create a new copy. We can't really modify writeln to do that, but it's worth knowing for your own functions.
Following code in MSVC generates warning about assignment in conditional expression.
https://godbolt.org/z/i_rwY9
int main()
{
int a;
if ((a = 5)) {
return 1;
}
return a;
}
Note that I tried to use the double () around if since that makes the warning go away with g++, but I do not know how to make it go away in msvc without extracting the assignment from condition.
Is there a way to nudge msvc to figure out that this assignment is intentional?
I know I can use pragmas to disable this warning, but pattern is very common so I would like to get a solution without pragmas if one exists.
The MSVC compiler will give this warning unless you can convince it that you really do know what you're doing. Adding at least one 'real' logical test will achieve this:
int main()
{
int a;
if ((a = 5) != 0) {
return 1;
}
return a;
}
Note that the constant 5 can readily be replaced with any variable or valid expression: adding the explicit != 0 test does nothing to actually change the outcome of the code (and it is unlikely to change the generated assembly).
I can't figure out what's wrong with my function - it causes a breakpoint on return.
std::string generateHash(std::string source)
{
CryptoPP::SHA1 hash;
byte digest[CryptoPP::SHA1::DIGESTSIZE];
hash.CalculateDigest(digest, (const byte*)source.c_str(), source.size());
std::string output;
CryptoPP::HexEncoder encoder;
CryptoPP::StringSink test = CryptoPP::StringSink(output);
encoder.Attach((CryptoPP::BufferedTransformation*)&CryptoPP::StringSink(output));
encoder.Put(digest, sizeof(digest));
encoder.MessageEnd();
return output; // here
}
encoder.Attach((CryptoPP::BufferedTransformation*)&CryptoPP::StringSink(output));
In this line, CryptoPP::StringSink(output) is a temporary object. After this call CryptoPP::StringSink(output) no longer exists. So If you try to follow its address (encoder.Attach and encoder.Put), you will get undefined behavior. (Like you should never return the address of a local variable)
My code for reference:
std::string generateHash(std::string source)
{
CryptoPP::SHA1 hash;
byte digest[CryptoPP::SHA1::DIGESTSIZE];
hash.CalculateDigest(digest, (const byte*)source.c_str(), source.size());
std::string output;
CryptoPP::HexEncoder encoder;
CryptoPP::StringSink test = CryptoPP::StringSink(output);
encoder.Attach(new CryptoPP::StringSink(output));
encoder.Put(digest, sizeof(digest));
encoder.MessageEnd();
return output;
}
CryptoPP::HexEncoder encoder;
CryptoPP::StringSink test = CryptoPP::StringSink(output);
encoder.Attach((CryptoPP::BufferedTransformation*)&CryptoPP::StringSink(output));
Onemouth's solution is correct, but here's why you are having trouble:
The StringSink(output) is a temporary on the stack, and it will be cleaned up when the StringSink destructors run
HexEncoder 'owns' the pointer to StringSink(output), so the HexEncoder will call delete on StringSink(output)
So the StringSink is cleaned up twice.
For completeness, the StringSink does not delete the string output because it takes a reference, not a pointer.
This is documented behavior in the README.txt:
88 *** Important Usage Notes ***
89
90 1. If a constructor for A takes a pointer to an object B (except primitive
91 types such as int and char), then A owns B and will delete B at A's
92 destruction. If a constructor for A takes a reference to an object B,
93 then the caller retains ownership of B and should not destroy it until
94 A no longer needs it.
Though it would be highly unusual, you might be able to do what you are trying to do and fix it as follows (but I would not recommend doing it the way you are):
encoder.Attach(new Redirector(&CryptoPP::StringSink(output)));
The Redirector stops the ownership chain. When the Redirector is destroyed, it does not destroy its attached transformation (which is the StringSink). But again, its not the way to use the library.
Redirectors are useful in other places in the library, but not really in this case.
OK, so here's the culprit method :
class FunctionDecl
{
// More code...
override void execute()
{
//...
writeln("Before setting... " ~ name);
Glob.functions.set(name,this);
writeln("After setting." ~ name);
//...
}
}
And here's what happens :
If omit the writeln("After setting." ~ name); line, the program crashes, just at this point
If I keep it in (using the name attribute is the key, not the writeln itself), it works just fine.
So, I suppose this is automatically garbage collected? Why is that? (A pointer to some readable reference related to GC and D would be awesome)
How can I solve that?
UPDATE :
Just tried a GC.disable() at the very beginning of my code. And... automagically, everything works again! So, that was the culprit as I had suspected. The thing is : how is this solvable without totally eliminating Garbage Collection?
UPDATE II :
Here's the full code of functionDecl.d - "unnecessary" code omitted :
//================================================
// Imports
//================================================
// ...
//================================================
// C Interface for Bison
//================================================
extern (C)
{
void* FunctionDecl_new(char* n, Expressions i, Statements s) { return cast(void*)(new FunctionDecl(to!string(n),i,s)); }
void* FunctionDecl_newFromReference(char* n, Expressions i, Expression r) { return cast(void*)(new FunctionDecl(to!string(n),i,r)); }
}
//================================================
// Functions
//================================================
class FunctionDecl : Statement
{
// .. class variables ..
this(string n, Expressions i, Statements s)
{
this(n, new Identifiers(i), s);
}
this(string n, Expressions i, Expression r)
{
this(n, new Identifiers(i), r);
}
this(string n, Identifiers i, Statements s)
{
// .. implementation ..
}
this(string n, Identifiers i, Expression r)
{
// .. implementation ..
}
// .. other unrelated methods ..
override void execute()
{
if (Glob.currentModule !is null) parentModule = Glob.currentModule.name;
Glob.functions.set(name,this);
}
}
Now as for what Glob.functions.set(name,this); does :
Glob is an instance holding global definitions
function is the class instance dealing with defined functions (it comes with a FunctionDecl[] list
set simply does that : list ~= func;
P.S. I'm 99% sure it has something to do with this one : Super-weird issue triggering "Segmentation Fault", though I'm still not sure what went wrong this time...
I think the problem is that the C function is allocating the object, but D doesn't keep a reference. If FunctionDecl_new is called back-to-back in a tight memory environment, here's what would happen:
the first one calls, creating a new object. That pointer goes into the land of C, where the D GC can't see it.
The second one goes, allocating another new object. Since memory is tight (as far as the GC pool is concerned), it tries to run a collection cycle. It finds the object from (1), but cannot find any live pointers to it, so it frees it.
The C function uses that freed object, causing the segfault.
The segfault won't always run because if there's memory to spare, the GC won't free the object when you allocate the second one, it will just use its free memory instead of collecting. That's why omitting the writeln can get rid of the crash: the ~ operator allocates, which might just put you over the edge of that memory line, triggering a collection (and, of course, running the ~ gives the gc a chance to run in the first place. If you never GC allocate, you never GC collect either - the function looks kinda like gc_allocate() { if(memory_low) gc_collect(); return GC_malloc(...); })
There's three solutions:
Immediately store a reference in the FunctionDecl_new function in a D structure, before returning:
FunctionDecl[] fdReferences;
void* FunctionDecl_new(...) {
auto n = new FunctionDecl(...);
fdReferences ~= n; // keep the reference for later so the GC can see it
return cast(void*) n;
}
Call GC.addRoot on the pointer right before you return it to C. (I don't like this solution, I think the array is better, a lot simpler.)
Use malloc to create the object to give to C:
void* FunctionDecl_new(...) {
import std.conv : emplace;
import core.stdc.stdlib : malloc;
enum size = __traits(classInstanceSize, FunctionDecl);
auto memory = malloc(size)[0 .. size]; // need to slice so we know the size
auto ref = emplace!FunctionDecl(memory, /* args to ctor */); // create the object in the malloc'd block
return memory.ptr; // give the pointer to C
}
Then, of course, you ought to free the pointer when you know it is no longer going to be used, though if you don't, it isn't really wrong.
The general rule I follow btw is any memory that crosses language barriers for storage (usage is different) ought to be allocated similarly to what that language expects: So if you pass data to C or C++, allocate it in a C fashion, e.g. with malloc. This will lead to the least surprising friction as it gets stored.
If the object is just being temporarily used, it is fine to pass a plain pointer to it, since a temp usage isn't stored or freed by the receiving function so there's less danger there. Your reference will still exist too, if nothing else, on the call stack.
When I write this code and compile with /W4
long r;
__try { r = 0; }
__finally { }
return r;
I get:
warning C4701: potentially uninitialized local variable 'r' used
Why does this happen?
The compiler can't be sure the code inside of the try block will successfully run. In this case it always will, but if there's additional code in the try block r = 0 may never execute. In that case r is uninitialized hence the error.
It's no different than if you said:
long r;
if(something) {
r = 0;
}
return r;
(where 'something' is pretty much anything other than a constant true value).
Because long r; creates r but it is not initialized; it is null.
So it warns you that the variable is not initialized. In certain cases it will cause Null Pointers.
Adding this as an answer as it is of more interest than in just a comment:
The error never appeared until a labeled-statement: was inserted before the variable. Remove the goto & associated label and there is no warning.
This might have something to do with how namespace pathing is setup with a similar warning C4702 generated on a line number before the insertion of a goto block. MVCE still to be generated if anyone is interested.