Code analysis warning: CA1062 is really false positive? - code-analysis

In my code, I have a reference variable LogValidacionPagosDTO
public void InsertarArchivoXmlOk(ArchivoXmlDRO archivo, ref LogValidacionPagosDTO archivoRespuesta)
{
//Some code
}
When executing "code analysis" generates this warning
Warning CA1062
In externally visible method 'ArchivoXMLOperacion.ValidacionDuplicadosArchivoXmlFosyga(List<RegistroXmlFosygaDRO>, ref LogValidacionPagosDTO)',
validate local variable ''(*archivoRespuesta)'', which was reassigned from parameter 'archivoRespuesta', before using it.
Then try to validate the object as null
public void InsertarArchivoXmlOk(ArchivoXmlDRO archivo, ref LogValidacionPagosDTO archivoRespuesta)
{
if (archivoRespuesta == null || archivoRespuesta.DetalleRegistros == null)
throw new ExcepcionOperacion(HelperMensaje.Obtener(HelperCodigoMensaje.GEN_0003),
(int)CodigosHTTP.Error, archivoRespuesta, null);
//Some code
}
But this didn't solve the warning. I found this possible solution in Microsoft forum https://social.msdn.microsoft.com/Forums/en-US/fdb00899-c7ea-4e8e-b5f6-9768c2ac0001/ca1062-false-positive-in-externally-visible-method-xxx-validate-local-variable-x-which-was?forum=vstscode
But, I really need to know if this is a false positive, thks!

Related

How to check auto_gcroot object for nullptr

I want to check if my C++/Cli managed auto_gcroot is null or not. Here's how I proceeded :
auto_gcroot<RefClassA^> m_a;
if (static_cast<RefClassA^>(m_a) != nullptr)
{
.....
}
The problem is that I get an error :
'No suitable conversion from 'auto_gcroot to object^ exists'
As I said in the comments, I'm not able to reproduce this on VS2012.
However, auto_gcroot has a get method that returns the object as a plain reference. You should be able to compare that to nullptr.
msclr::auto_gcroot<String^> m_a;
if (m_a.get() != nullptr)
{
// ...
}

A pointer-to-member is not valid for a managed class

I have a Windows Form in Visual Studio C++. (CLR)
In the header file I declare bool isRunning (to find if notepad is running):
private:
bool isRunning(LPCSTR pnotepad)
{
HWND hwnd;
hwnd = FindWindow(NULL, pnotepad);
if (hwnd != 0)
{
return true;
}
else
{
return false;
}
}
Now on a checkbox, I want it to check if the process is running.
private: System::Void checkBox2_CheckedChanged(System::Object^ sender, System::EventArgs^ e) {
if (bool application::GUI::isRunning)
label1->Text = "cat";
I get this error:
a pointer-to-member is not valid for a managed class
I tried changing it to &isRunning. This gives me the same error as above and
illegal operation on bound member function expression
How can I fix this?
everything with below seems wrong:
if (bool application::GUI::isRunning)
you don't need bool if you don't wanna save the result of function. Either define a variable that's bool and assign the result of function to that:
bool result = isRunning(...);
if(result)
...
or
if(isRunning())
...
application::gui::isRunning expression returns the pointer of isRunning function which you are trying to define as a bool variable.
Lets say you fixed first two as:
LPCSTR arg = ...;
if(application::GUI::isRunning(arg))
label1->Text = "cat";
Which implies that you are calling static function of a GUI class
or a function under the namespace of GUI (also GUI is under application namespace).
My guess is GUI is a Form class so you are trying to invoke and since the function is not static you will get error again. So you have two cases to fix:
if you are getting this error from another function of GUI
LPCSTR arg = ...;
if (isRunning(arg))
label1->Text = "cat";
otherwse you need a pointer to GUI object:
LPCSTR arg = ...;
if (gui-> isRunning(arg))
label1->Text = "cat";
I think you are making function call in incorrect manner.
Probably it should be like below,
if (application::GUI::isRunning())
{
label1->Text = "cat";
}
Above is just a hint to make proper function call - but since isRunning is a private member function, how it can be invoked directly from outside class and that too without creating any object. It is not a static member function. Please check this point.

How to tell IDEA/Studio that the null check has been done?

I'm developing with Android Studio/IntelliJ IDEA.
I have enabled the inspection check called "Constant conditions & exceptions" that shows a warning if I am risking a NPE, such as:
String foo = foo.bar(); // Foo#bar() is #nullable
if (foo.contains("bar")) { // I'm living dangerously
...
}
I have the following in my code:
String encoding = contentEncoding == null ? null : contentEncoding.getValue();
if (!TextUtils.isEmpty(encoding) && encoding.equalsIgnoreCase("gzip")) {
inputStream = new GZIPInputStream(entity.getContent());
} else {
inputStream = entity.getContent();
}
Here's the source code of TextUtils#isEmpty(String):
/**
* Returns true if the string is null or 0-length.
* #param str the string to be examined
* #return true if str is null or zero length
*/
public static boolean isEmpty(CharSequence str) {
if (str == null || str.length() == 0)
return true;
else
return false;
}
I'm not risking any NPE because TextUtils#isEmpty(String) would return true to a null pointer.
However I'm still getting the little Method invocation 'encoding.equalsIgnoreCase("gzip")' may produce 'java.lang.NullPointerException' warning, which can be annoying.
Is it possible to make this check smarter and ignore the NPE warning if there's already a null-check done?
You can look into the link that Peter Gromov mention in his answer.
Created some simple classes that resemble your setup:
A class with a method annotated with #Nullable:
The TextUtil class with it's isEmpty method:
And finally the main class calling the TextUtil#isEmpty:
Now if you enter the File -> Settings... and go to Inspections ->Constant conditions & exceptions part you can change the Configure Assert/Check Methods to cater for your isEmpty method:
Add a new IsNull check method:
Enter the TextUtil class, isEmpty method and CharSequence parameter:
This gives this Assert/Check Method Configuration window:
Press Ok and then Ok again to go back to the editor view and you'll see that the inspection disappeared:
You are actually telling IntelliJ that the isEmpty method is doing a null check on the str parameter.
You could use //noinspection ConstantConditions that will remove the NPE warning for the following line, like this:
String encoding = contentEncoding == null ? null : contentEncoding.getValue();
//noinspection ConstantConditions
if (!TextUtils.isEmpty(encoding) && encoding.equalsIgnoreCase("gzip")) {
inputStream = new GZIPInputStream(entity.getContent());
} else {
inputStream = entity.getContent();
}
You can use #SuppressWarnings("ConstantConditions") annotation.
#SuppressWarnings("ConstantConditions")
#Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int indexViewType) {
if (inflater == null) {
inflater = LayoutInflater.from(parent.getContext());
}
ItemViewProvider provider = getProviderByIndex(indexViewType);
provider.adapter = MultiTypeAdapter.this;
return provider.onCreateViewHolder(inflater, parent);
}
Select "TextUtils.isEmpty".
Right Click -> Show Context Actions -> Add Method Contract.
Enter "null -> true".
Save the configuration xml.
Please check the details here
See http://www.jetbrains.com/idea/webhelp/configuring-check-assert-methods.html for IDEA 12.
In IDEA 13 EAP, you can add method contract: http://youtrack.jetbrains.com/issue/IDEA-93372
Unfortunately marked as "right answer" solution is of date. But I found equivalent for me solution.
The new versions of IDE work correctly with static methods. So the example from the question won't throw warning anymore.
TextUtils#isEmpty(String);
public static boolean isEmpty(CharSequence str) {
// your checks
}

Managed C++, Object reference not set to an instance of an object

I've run into this problem before, but never in a situation like this. I'm completely confused. As the question states, I'm getting the runtime error "Object reference not set to an instance of an object." Using the debugger tools, I think I've pinpointed the problem to this line:
dataFileLocation = path;
The entire function is here:
void DATReader::SetPath(String^ path)
{
if(!File::Exists(path))
{
MessageBox::Show( "DATReader (missing dat file: \n"+path+"\n )", "Error", MessageBoxButtons::OK, MessageBoxIcon::Exclamation);
return;
}
dataFileLocation = path;
}
dataFileLocation is declared here, but nothing is assigned to it:
ref class DATReader
{
private:
System::String^ dataFileLocation;
// ...
}
Now I know the reason I'm getting the error is because dataFileLocation is assigned to nothing. But I'm having problems assigning it. When I add = 0; to it, it won't build because its a ref class. When I try to assigned it to = 0; in the constructor, it yells at me for trying to convert it from a System::String^ to an int. If I assign it to a = gcnew String(""); it builds, but throws the same runtime exception.
I don't get it, am I reading the debugger wrong, and this isn't the source of the problem at all? I've just started to use managed code recently, so I'm confused :\
You may want to check and make sure your DATReader object isn't null as well It may be throwing the exception at your DATReader.SetPath() call.
This is a nicety in C# that's missing in C++/CLI. C# generates code that ensures this can never be null. Easily seen in the debugger by setting a breakpoint on the method and inspecting "this". Here's an example program that reproduces the exception:
#include "stdafx.h"
using namespace System;
ref class Example {
String^ dataFileLocation;
public:
void SetPath(String^ path) {
dataFileLocation = path; // Set breakpoint here and inspect "this"
}
};
int main(array<System::String ^> ^args)
{
Example^ obj /* = gcnew Example */;
obj->SetPath("foo");
return 0;
}
Remove the /* */ comments to fix. Fix your code by looking at the call stack to find the method that forgot to instantiate the object.
Managed C++ uses nullptr for null references. So you can check:
if (path == nullptr) { ... }
or use:
if (!String::IsNullOrEmpty(path))

How do I express a void method call as the result of DynamicMetaObject.BindInvokeMember?

I'm trying to give a short example of IDynamicMetaObjectProvider for the second edition of C# in Depth, and I'm running into issues.
I want to be able to express a void call, and I'm failing. I'm sure it's possible, because if I dynamically call a void method using the reflection binder, all is fine. Here's a short but complete example:
using System;
using System.Dynamic;
using System.Linq.Expressions;
class DynamicDemo : IDynamicMetaObjectProvider
{
public DynamicMetaObject GetMetaObject(Expression expression)
{
return new MetaDemo(expression, this);
}
public void TestMethod(string name)
{
Console.WriteLine(name);
}
}
class MetaDemo : DynamicMetaObject
{
internal MetaDemo(Expression expression, DynamicDemo demo)
: base(expression, BindingRestrictions.Empty, demo)
{
}
public override DynamicMetaObject BindInvokeMember
(InvokeMemberBinder binder, DynamicMetaObject[] args)
{
Expression self = this.Expression;
Expression target = Expression.Call
(Expression.Convert(self, typeof(DynamicDemo)),
typeof(DynamicDemo).GetMethod("TestMethod"),
Expression.Constant(binder.Name));
var restrictions = BindingRestrictions.GetTypeRestriction
(self, typeof(DynamicDemo));
return new DynamicMetaObject(target, restrictions);
}
}
class Test
{
public void Foo()
{
}
static void Main()
{
dynamic x = new Test();
x.Foo(); // Works fine!
x = new DynamicDemo();
x.Foo(); // Throws
}
}
This throws an exception:
Unhandled Exception:
System.InvalidCastException: The
result type 'System.Void' of the
dynamic binding produced by the object
with type 'DynamicDemo' for the binder
'Microsoft.CSharp.RuntimeBinder.CSharpInvokeMemberBinder'
is not compatible with the result type 'System.Object' expected by the
call site.
If I change the method to return object and return null, it works fine... but I don't want the result to be null, I want it to be void. That works fine for the reflection binder (see the first call in Main) but it fails for my dynamic object. I want it to work like the reflection binder - it's fine to call the method, so long as you don't try to use the result.
Have I missed a particular kind of expression I can use as the target?
This is similar to:
DLR return type
You do need to match the return type specified by the ReturnType property. For all of the standard binaries this is fixed to object for almost everything or void (for the deletion operations). If you know you're making a void call I'd suggest wrapping it in:
Expression.Block(
call,
Expression.Default(typeof(object))
);
The DLR used to be quite lax about what it would allow and it would provide some minimal amount of coercion automatically. We got rid of that because we didn't want to provide a set of convensions which may or may not have made sense for each language.
It sounds like you want to prevent:
dynamic x = obj.SomeMember();
There's no way to do that, there'll always be a value returned that the user can attempt to continue to interact with dynamically.
I don't like this, but it seems to work; the real problem seems to be the binder.ReturnType coming in oddly (and not being dropped ("pop") automatically), but:
if (target.Type != binder.ReturnType) {
if (target.Type == typeof(void)) {
target = Expression.Block(target, Expression.Default(binder.ReturnType));
} else if (binder.ReturnType == typeof(void)) {
target = Expression.Block(target, Expression.Empty());
} else {
target = Expression.Convert(target, binder.ReturnType);
}
}
return new DynamicMetaObject(target, restrictions);
Perhaps the callsite expects null to be returned but discards the result - This enum looks interesting, particularly the "ResultDiscarded" flag...
[Flags, EditorBrowsable(EditorBrowsableState.Never)]
public enum CSharpBinderFlags
{
BinaryOperationLogical = 8,
CheckedContext = 1,
ConvertArrayIndex = 0x20,
ConvertExplicit = 0x10,
InvokeSimpleName = 2,
InvokeSpecialName = 4,
None = 0,
ResultDiscarded = 0x100,
ResultIndexed = 0x40,
ValueFromCompoundAssignment = 0x80
}
Food for thought...
UPDATE:
More hints can be gleaned from Microsoft / CSharp / RuntimeBinder / DynamicMetaObjectProviderDebugView which is used (I presume) as a visualizer for debuggers. The method TryEvalMethodVarArgs examines the delegate and creates a binder with the result discarded flag (???)
Type delegateType = Expression.GetDelegateType(list.ToArray());
if (string.IsNullOrEmpty(name))
{
binder = new CSharpInvokeBinder(CSharpCallFlags.ResultDiscarded, AccessibilityContext, list2.ToArray());
}
else
{
binder = new CSharpInvokeMemberBinder(CSharpCallFlags.ResultDiscarded, name, AccessibilityContext, types, list2.ToArray());
}
CallSite site = CallSite.Create(delegateType, binder);
... I'm at the end of my Reflector-foo here, but the framing of this code seems a bit odd since the TryEvalMethodVarArgs method itself expects an object as a return type, and the final line returns the result of the dynamic invoke. I'm probably barking up the wrong [expression] tree.
-Oisin
The C# binder (in Microsoft.CSharp.dll) knows whether or not the result is used; as x0n (+1) says, it keeps track of it in a flag. Unfortunately, the flag is buried inside a CSharpInvokeMemberBinder instance, which is a private type.
It looks like the C# binding mechanism uses ICSharpInvokeOrInvokeMemberBinder.ResultDiscarded (a property on an internal interface) to read it out; CSharpInvokeMemberBinder implements the interface (and property). The job appears to be done in Microsoft.CSharp.RuntimeBinder.BinderHelper.ConvertResult(). That method has code that throws if the aforementioned ResultDiscarded property doesn't return true if the type of the expression is void.
So it doesn't look to me like there's an easy way to tease out the fact that the result of the expression is dropped from the C# binder, in Beta 2 at least.