Less memory methods - c#

If i have the following methods:
void addfive(int num)
{
num = num + 5;
}
and when i use it in the main routine like this:
int a = 15;
addfive(a);
What will happen is that 5 will be added to a copy of the (a) variable.
but if the method parameter is a pointer int* num instead of the int num
5 will be added to the (a) variable and no copy is created.
If I used the pointer in my method, will this use less memory that the first method, and will this work in non_void methods?

If you use a pointer it will still use memory and it will usually be less than the memory used by a type, but in your specific case and depending on your system (your os and application) an int * might use more memory than an int, use sizeof to see the size of a type and a pointer, example use this line in a 64 bit build of an application:
std::cout << "Size of int is: " << sizeof(int) << ", size of int* is: " << sizeof(int*) << "\n";
But another usage for pass by pointer or by reference is to be able to code your function to leave side-effects on the object (or build in type) that you pass as parameter.

It's implementation defined whether passing a pointer takes more or less memory than passing an integer. For example, in MS Visual Studio int takes 4 bytes, and a pointer takes 4 bytes for 32-bit platform and 8 bytes for x64 system.
Usually sizeof(int) <= sizeof(int*) .

Firsly +5 is applied to copy of "a" and
int a = 15;
addfive(a);
and your variable a will not change because "a" is passed by value not reference if you want a funciton that will change a you must use pointer or "ref" keyword
if you are using c or c++
your code should be likse this
addfilve(*a)
{
*a = *a + 5;
}
int main()
{
int a = 15;
int *aptr ;
aptr = &a;
return 0;
}
but if you use c#
addfive(ref a)
{
a += 5;
}
and when you want to use that function
double a = 5;
addfive(ref a); // a = 10 now
note that it is a normal funciton not extesion method
For example if you are writing form appilication it must be declared in the Form1 class

Related

Why does it appear that this string is stored inline by value in an explicit layout class or struct?

I have been doing some extremely unsafe and slightly useless messing with the System.Runtime.CompilerServices.Unsafe MSIL package that allows you to do a lot of things with pointers you can't in C#. I created an extension method that returns a ref byte, with that byte being the start of the Method Table pointer at the start of the object, which allows you to use any object in a fixed statement, taking a byte pointer to the start of the object:
public static unsafe ref byte GetPinnableReference(this object obj)
{
return ref *(byte*)*(void**)Unsafe.AsPointer(ref obj);
}
I then decided to test it, using this code:
[StructLayout(LayoutKind.Explicit, Pack = 0)]
public class Foo
{
[FieldOffset(0)]
public string Name = "THIS IS A STRING";
}
[StructLayout(LayoutKind.Explicit, Pack = 0)]
public struct Bar
{
[FieldOffset(0)]
public string Name;
}
And then in the method
var foo = new Foo();
//var foo = new Bar { Name = "THIS IS A STRING" };
fixed (byte* objPtr = foo)
{
char* stringPtr = (char*)(objPtr + (foo is Foo ? : 12));
for (var i = 0; i < foo.Name.Length; i++)
{
Console.Write(*(stringPtr + i /* Char offset */));
}
Console.WriteLine();
}
Console.ReadKey();
The really weird thing about this is that this successfully prints "THIS IS A STRING"? The code works like this:
Get a byte pointer, objPtr, to the very start of the object
Add 16 to get to the actual data
Add another 16 to get past the string header to the string's actual data
Add 4 to skip the first 4 bytes of the string, which are the int _stringLength (exposed to us as Length property)
Interpret the result as a char pointer
EDIT: Important point - when switching foo to type Bar, I only add 12 rather than 36 bytes on (36 = 16 + 16 + 4). Why does it only have 8 bytes of header in the struct rather than 32 in the class? It would make sense that the struct has a smaller header (no syncblk i believe), but then why doesn't the string still have a 16 byte head? I would expect the offset to be 8 + 16 + 4 (28) rather than just 8 + 4 (12)
However, this assumption makes a big flaw. It assumes the string is stored inline inside the class/struct. However, strings are reference types and only a reference to them is stored inside the object from my knowledge. Particularly, I thought reference types can only be put on the heap - and as this struct is a local variable I thought it was on the stack. If it wasn't, the code would surely look something more like this to get the stringPtr
byte** stringRefptr = objPtr + 16;
char* stringPtr = (char*)(*stringRefPtr + 20);
where you take the string reference as a byte** and then use it to get to the chars. And this still wouldn't make sense if the string internally was a char[] (I'm not sure if it is)
So why does this work, and print the string, even though it mistakenly assumes string is stored inline, when string is a reference type?
NOTE: Requires .NET Core 2.0+ with System.Runtime.CompilerServices.Unsafe nuGet package, and C# 7.3+.
Because strings are indeed stored inline. The problem with your assumption is that strings are not normal objects but handled as a special case by the CLR (probably for performance reasons).
And as for the objects, since the string is the only member this would naturally be the most efficient way to allocate the memory. Try adding more members after your string member and your code would break.
Here’s a few references in how strings are stored in the CLR
https://mattwarren.org/2016/05/31/Strings-and-the-CLR-a-Special-Relationship/
https://codeblog.jonskeet.uk/2011/04/05/of-memory-and-strings/
Edit: I didn’t check, but I believe your reasoning behind the offsets is off. 36 = 24 (size of object) + 8 (string header?) + 4 (size of int) while for the struct the24 bytes becomes 0 as it has no header.

Constructors and Destructors in C++ compared to C#

I want the following code to create 5 objects of the class "test" which call the constructor each time one is created,store them in a vector, print "lalalala" once, and then run the destructors and destroy the created objects. I want the destructor to run once for each object i created not more than once.
I think C++ in the following example is creating multiple extra copies of objects i do not want or else it calls the destructor way more times that it should. I am not sure. Tried gcc and clang no difference. Tried both with stack and heap allocation, as well as std::move. All produce the same results, way more destructor calls than i asked for.
Also i noticed some but not all C++ destructors are called before i print "lalala".
Why does this C++ code runs the destructor 17 times :
#include <iostream>
#include <vector>
using namespace std;
class test
{
public:
int t;
test(int i)
{
t = i;
cout << "Created instance " << t << ". \n";
}
~test()
{
cout << "(*)Deleted instance " << t << ".\n";
}
};
int main()
{
vector <test> V;
for(int i = 1; i <= 5; i++)
{
test D(i);
V.push_back(D);
}
cout << "LALALLALA \n";
return 0;
}
While this C# code does exactly what i want, 5 constructors and 5 destructors.
using System.IO;
using System;
using System.Collections.Generic;
class Program
{
class test
{
public int t;
public test(int i)
{
t = i;
Console.Write ("Created instance ");
Console.Write (t.ToString());
Console.WriteLine(".");
}
~test()
{
Console.Write( "(*)Deleted instance ");
Console.Write(t.ToString());
Console.WriteLine(".");
}
}
static void Main()
{
List<test> lst = new List<test>();
for(int i = 0; i < 5; i++)
{
test temp = new test(i);
lst.Add(temp);
}
Console.WriteLine("LALALLALA \n");
}
}
In C#, your List is storing references to objects. In C++, you are actually storing objects in the vector. Which means they need to be copied when they're put into the vector, and also when the vector needs to reallocate. Each one of those copies is a separate object (created with the copy constructor, which you're not tracking), and will have the destructor called on it.
A close approximation in C++ to what you are doing in C# would be to store pointers (or smart pointers) to heap allocated test objects, instead of test objects themselves
#include <memory> // for shared_ptr
int main()
{
std::vector<std::shared_ptr<test>> V;
for(int i = 1; i <= 5; i++)
{
auto D = std::make_shared<test>(i);
V.push_back(D);
}
std::cout << "LALALLALA \n";
return 0;
}
A preferred idiomatic C++ approach, if you want to be sure you just create 5 objects, but not have to allocate each one individually on the heap would be the following:
int main()
{
std::vector<test> V;
// ensure we can store 5 objects without reallocating
V.reserve(5);
for(int i = 1; i <= 5; i++)
{
// construct the object in place in the vector
V.emplace_back(i);
}
std::cout << "LALALLALA \n";
return 0;
}
Missing copy-constructor in C++ adds mismatch between reported number of constructor calls and destructor calls. There are a lot of copies created (number depends on optimizations performed/allowed by compiler).
Note that you are comparing apples to oranges (twice):
C++ objects are by default value types, while C# classes are reference types (and C# value types - struct can't have destructors). So if you C++ code would use pointers wrapped into some sort of smart-pointer (thus also avoiding problem with missing copy constructor) you'll get the same behavior.
C++ destructors are synchronous while C# "destructors" are asynchronous and may not ever run (definitely not when object is "out of scope" compared to C++).

How to pass a long array from VB6 to C# thru COM

I need to pass an array of int or long (doesn't matter) from a VB6 application to a C# COM Visible class. I've tried declaring the interface in C# like this:
void Subscribe([MarshalAs(UnmanagedType.SafeArray, SafeArraySubType = VarEnum.VT_I4)]int[] notificationTypes)
void Subscribe(int[] notificationTypes)
But both of them raised a Function or interface markes as restricted, or the function uses an Automation type not supported in Visual Basic.
How should I declare the C# method?
If you get desperate, code the signature in a dummy VB6 ActiveX dll project. Then generate the .NET Interop version of the vb6 component via Visual studio or the command line tool. Then use Reflector or dotPeek to pull the code out of the interop assembly. It is the long way around, but it works.
I ran into this problem 9 years later. The solution I came up with is to pass a pointer to the first element of the array, along with the upper bound (UBound in VB6). Then iterate the pointer to the upper bound and put each element into a list.
on the vb6 side use
Dim myarray(3) As float
Dim ptr As integer
Dim upperbound as integer
myarray(0) = 0.1
myarray(1) = 0.2
myarray(2) = 0.3
myarray(3) = 0.4
ptr = VarPtr(myarray(0))
upperbound = UBound(myarray)
SetMyFloat(ptr, upperbound)
C# code
public float MyFloat {get; set;}
public unsafe void SetMyFloat(float* ptr, int ubound)
{
MyFloat = PointerToFloatArray(ptr, ubound);
}
public unsafe float[] PointerToFloatArray(float* ptr, int ubound)
//this is to deal with not being able to pass an array from vb6 to .NET
//ptr is a pointer to the first element of the array
//ubound is the index of the last element of the array
{
List<float> li = new List<float>();
float element;
for (int i = 0; i <= ubound; i++)
{
element = *(ptr + i);
li.Add(element);
}
return li.ToArray();
}

Return list of points (x,y,z) from C to C# using PInvoke

I need to return a list of points i have from a C dll to a C# application using PInvoke. These are points in 3 dimensions [x,y,z]. The number of points varies by what kind of model it is. In C i handle this a linked list of structs. But I don't see how i can pass this on to C#.
The way I see it, I have to return a flexible two dimensional array, probably in a struct.
Any suggestions to how this can be done? Both ideas on how to return it in C and how to access it in C# are highly appreciated.
A linked list of structs could be passed back, but it would be quite a hassle to deal with, as you would have to write code to loop through the pointers, reading and copying the data from native memory into managed memory space. I would recommend a simple array of structs instead.
If you have a C struct like the following (assuming 32-bit ints)...
struct Point
{
int x;
int y;
int z;
}
... then you'd represent it nearly the same way in C#:
[StructLayout(LayoutKind.Sequential]
struct Point
{
public int x;
public int y;
public int z;
}
Now to pass an array back, it would be easiest to have your native code allocate the array and pass it back as a pointer, along with another pointer specifying the size in elements.
Your C prototype might look like this:
// Return value would represent an error code
// (in case something goes wrong or the caller
// passes some invalid pointer, e.g. a NULL).
// Caller must pass in a valid pointer-to-pointer to
// capture the array and a pointer to capture the size
// in elements.
int GetPoints(Point ** array, int * arraySizeInElements);
The P/Invoke declaration would then be this:
[DllImport("YourLib.dll")]
static extern int GetPoints(
[MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] out Point[] array,
out int arraySizeInElements);
The MarshalAs attribute specifies that the array should be marshaled using the size specified in the second parameter (you can read more about this at MSDN, "Default Marshaling for Arrays").
If you use this approach, note that you must use CoTaskMemAlloc to allocate the native buffer as this is what the .NET marshaler expects. Otherwise, you will get memory leaks and/or other errors in your application.
Here is a snippet from the simple example I compiled while verifying my answer:
struct Point
{
int x;
int y;
int z;
};
extern "C"
int GetPoints(Point ** array, int * arraySizeInElements)
{
// Always return 3 items for this simple example.
*arraySizeInElements = 3;
// MUST use CoTaskMemAlloc to allocate (from ole32.dll)
int bytesToAlloc = sizeof(Point) * (*arraySizeInElements);
Point * a = static_cast<Point *>(CoTaskMemAlloc(bytesToAlloc));
*array = a;
Point p1 = { 1, 2, 3 };
a[0] = p1;
Point p2 = { 4, 5, 6 };
a[1] = p2;
Point p3 = { 7, 8, 9 };
a[2] = p3;
return 0;
}
The managed caller can then deal with the data very simply (in this example, I put all the interop code inside a static class called NativeMethods):
NativeMethods.Point[] points;
int size;
int result = NativeMethods.GetPoints(out points, out size);
if (result == 0)
{
Console.WriteLine("{0} points returned.", size);
foreach (NativeMethods.Point point in points)
{
Console.WriteLine("({0}, {1}, {2})", point.x, point.y, point.z);
}
}

Calling FORTRAN dll from C# and assigning values to array of structures

I can pass a C# struct into FORTRAN just fine. I can even pass an array of a C# struct as an array of TYPE() in FORTRAN. Where I run into trouble is when I tried to return values back into C#. Here is an example:
The fortran dll is:
MODULE TESTING
TYPE VALUEREF
INTEGER*4 :: A
ENDTYPE VALUEREF
CONTAINS
SUBROUTINE TEST_REF(T,N)
!DEC$ ATTRIBUTES DLLEXPORT :: TEST_REF
!DEC$ ATTRIBUTES ALIAS:'TEST_REF' :: TEST_REF
!DEC$ ATTRIBUTES VALUE :: N
IMPLICIT NONE
INTEGER*4 :: A,I,N
TYPE(VALUEREF) :: T(N)
A = 100
DO I=1,N
T(I)%A = A + I
END DO
END SUBROUTINE
END MODULE
and the C# calling function that expects results is:
[StructLayout(LayoutKind.Sequential)]
public struct ValueRef
{
public int a;
}
[DllImport("mathlib.dll")]
static extern void TEST_REF(ValueRef[] t, int n);
void Main()
{
ValueRef[] T = new ValueRef[4];
for (int i = 0; i < T.Length; i++)
{
T[i].a = i;
}
Console.WriteLine("Initialize");
for (int i = 0; i < T.Length; i++)
{
Console.WriteLine(" A={0}", T[i].a);
}
Console.WriteLine("Call Fortran");
TEST_REF(T, T.Length);
for (int i = 0; i < T.Length; i++)
{
Console.WriteLine(" A={0}", T[i].a);
}
}
With results:
Initialize
A=0
A=1
A=2
A=3
Call Fortran
A=0
A=1
A=2
A=3
Debugging through the FORTRAN code, I see the initial values pass from C# to FORTRAN just fine. The the values get overridden with new values and control is passed back into C# where the old values are still contained within the ValueRef instances.
Why is it that I can pass and return an array of float, or int in a similar fashion, just fine. and I can pass and return singular structures with ref keyword, and I can pass but not return and array of struct?
PS. I am using Compaq Visual Fortran 6.5 & .NET 3.5
PS2. I appreciate any comments/ideas on this. I am 95% done with my project, and now I run into this issue. The whole point of this project is to use structures as much as possible to reduce the #of arguments passed to functions and retain certain aspects of OOP design.
I have done this in the past using a pointer, not an array. I think that your structures are being copied for the P/Invoke call:
[DllImport("mathlib.dll")]
static extern void TEST_REF(ValueRef* t, int n);
You will need to pin your array before calling the method.
fixed (ValueRef* pointer = t)
{
TEST_REF(pointer, n);
}
Edit:
Based on the comments the solution is to declare the external as
[DllImport("mathlib.dll")]
static extern void TEST_REF([Out] ValueRef[] t, int n);
Here is a MSDN reference on Marshaling of arrays, and how they default to [In].

Categories