My struct seems to be broken, I can't figure why:
struct FilterBoundary {
private uint start;
private uint end;
public static immutable uint MIN = 0;
public static immutable uint MAX = uint.max;
public this(uint start=0, uint end=0){
checkRange(start,end);
this.start=start;
this.end=end;
}
public uint getStart(){
return this.start;
}
public uint getEnd(){
return this.end;
}
private void checkRange(uint start, uint end){
if(start>end){
throw new Exception("Invalid range.");
}
}
public FilterBoundary setStart(uint start){
checkRange(start,this.end);
this.start=start;
return this;
}
public FilterBoundary setEnd(uint end){
checkRange(this.start,end);
this.end=end;
return this;
}
}
This code
auto r1 = FilterBoundary(6, 7);
//Correct
writeln(r1);
r1.setStart(5);
//Correct
writeln(r1);
//Wrong end set to 9 but start stays to 5
r1.setEnd(9).setStart(2);
writeln(r1);
Produces this output:
FilterBoundary(6, 7)
FilterBoundary(5, 7)
FilterBoundary(5, 9)
Structs are value types: when setStart and setEnd return this, they are actually returning a copy of the struct. Thus, the second setStart call operates on a temporary copy, which is discarded.
You can get around this by returning &this (and changing the return value to FilterBoundary* appropriately). Just be careful, this may be unsafe: because structs can live on the stack, saving a pointer to it may cause it to become a dangling pointer, and accessing it can corrupt memory.
Related
C# code:
class Hello{
public void helloWorld(char[] chars){
//do something
}
}
C++ code to call C#:
MyCSDLL::Hello* hello;
//init hello, some calls are ok.
char* myCharPtr;
//init with message
HRESULT result = hello->helloWorld(safeArray, (MyCSDLL::_MyRetVal) _retValPtr);
Adapting from How to create and initialize SAFEARRAY of doubles in C++ to pass to C#
void createSafeArray(SAFEARRAY** saData, char* charPtr)
{
char* iterator = charPtr;
SAFEARRAYBOUND Bound;
Bound.lLbound = 0;
Bound.cElements = 10;
*saData = SafeArrayCreate(VT_R8, 1, &Bound);
char HUGEP *pdFreq;
HRESULT hr = SafeArrayAccessData(*saData, (void HUGEP* FAR*)&pdFreq);
if (SUCCEEDED(hr))
{
do {
*pdFreq++ = *iterator;
} while (*iterator++);
}
}
How to call hello->helloWorld()? it is expecting SAFEARRAY*. The current code gives 80131538 error. How to fix it?
C++ Project is not CLR.
Let's suppose the C# code is this:
namespace ClassLibrary1
{
[ComVisible(true)]
[ClassInterface(ClassInterfaceType.AutoDual)]
public class Hello
{
public void helloWorld(char[] chars)
{
...
}
}
}
Then, you can call it with this C/C++ code, for example:
#import "C:\mycode\ClassLibrary1\bin\Debug\classlibrary1.tlb" raw_interfaces_only
using namespace ClassLibrary1;
HRESULT CallHello(wchar_t* charPtr, int count)
{
CComPtr<_Hello> p;
HRESULT hr = p.CoCreateInstance(__uuidof(Hello));
if (FAILED(hr))
return hr;
SAFEARRAY* psa = SafeArrayCreateVector(VT_UI2, 0, count);
if (!psa)
return E_OUTOFMEMORY;
LPVOID pdata;
hr = SafeArrayAccessData(psa, &pdata);
if (SUCCEEDED(hr))
{
CopyMemory(pdata, charPtr, count * 2); // count is the number of chars
SafeArrayUnaccessData(psa);
hr = p->helloWorld(psa);
}
SafeArrayDestroy(psa);
return hr;
}
.NET's char type is unicode, so the binary size is two bytes, the C equivalent is wchar_t (or unsigned short, etc...). So the safearray element type must match that, that's why I used VT_UI2 (VT_R8 that you used is Real of size 8 bytes, so it's equivalent to .NET's double type).
If you really want to use C's char, then you must do some kind of conversion to a 2-byte character.
Also, you can use the SafeArrayCreateVector function which directly allocates a 1-dimension safe array. Don't forget to call cleanup methods.
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.
I need to call a function that returns a unique id,
int getid()
{
static id=0;
id++;
return id;
}
Multiple threads need to call this function, my problem is I'm not sure where I need to lock the mutex,
Do I need to lock before and after calling the function like below
pthread_mutex_lock( &id );
int id = getid()
pthread_mutex_unlock( &id );
can someone help me with that please?
It doesn't really matter where it was locked as long as it was before the access to the shared state. It would be less prone to errors if the mutex locking was inside the function. Something minimal like this would work:
int getid()
{
static int id=0;
pthread_mutex_lock( &mutex );
int newId = ++id;
pthread_mutex_unlock( &mutex );
return newId;
}
There are some issues around the initialization of the static variable being thread safe that you may want to look into.
For a single integer you don't need a full mutex, atomic increment would be enough:
int getid() {
static int id = 0;
return __sync_fetch_and_add( &id, 1 );
}
I have the following in my WinRT component:
public value struct WinRTStruct
{
int x;
int y;
};
public ref class WinRTComponent sealed
{
public:
WinRTComponent();
int TestPointerParam(WinRTStruct * wintRTStruct);
};
int WinRTComponent::TestPointerParam(WinRTStruct * wintRTStruct)
{
wintRTStruct->y = wintRTStruct->y + 100;
return wintRTStruct->x;
}
But, it seems that the value of winRTStruct->y and x are always 0 inside the method, when called from C#:
WinRTComponent comp = new WinRTComponent();
WinRTStruct winRTStruct;
winRTStruct.x = 100;
winRTStruct.y = 200;
comp.TestPointerParam(out winRTStruct);
textBlock8.Text = winRTStruct.y.ToString();
What is the correct way to pass a struct by reference so it an be updated inside the method of a WinRTComponent written in C++/CX?
You cannot pass a struct by reference. All value types (including structs) in winrt are passed by value. Winrt structs are expected to be relatively small - they're intended to be used for holding things like Point and Rect.
In your case, you've indicated that the struct is an "out" parameter - an "out" parameter is write-only, its contents are ignored on input and are copied out on return. If you want a structure to be in and out, split it into two parameters - one "in" parameter and another "out" parameter (in/out parameters are not allowed in WinRT because they don't project to JS the way you expect them to project).
My co-worker helped me solve this.
In WinRT components, it seems that the best way to do this is to define a ref struct instead of a value struct:
public ref struct WinRTStruct2 sealed
{
private: int _x;
public:
property int X
{
int get(){ return _x; }
void set(int value){ _x = value; }
}
private: int _y;
public:
property int Y
{
int get(){ return _y; }
void set(int value){ _y = value; }
}
};
But this creates other problems. Now the VS11 compiler gives INTERNAL COMPILER ERROR when I try to add a method to the ref struct that returns an instance of the struct.
I'm confused about when I need to use KeepAlive in my C++/CLI wrapper code and how lifetimes are handled in it. Consider the following code and note the places where I ask whether KeepAlive is needed.
// convert from managed to native string
inline std::string ToStdString(String^ source)
{
if (String::IsNullOrEmpty(source))
return std::string();
int len = ((source->Length+1) * 2);
/*** Do I need GC::KeepAlive(source) here? ***/
char *ch = new char[ len ];
bool result ;
{
pin_ptr<const wchar_t> wch = PtrToStringChars( source );
result = wcstombs( ch, wch, len ) != -1;
}
std::string target = ch;
delete ch;
if(!result)
throw gcnew Exception("error converting System::String to std::string");
return target;
}
// convert from native to managed string
inline String^ ToSystemString(const std::string& source)
{
return gcnew String(source.c_str());
}
// unmanaged C++ class
struct NativeDog
{
std::string name;
std::string bark() const {return "woof";}
void eat(std::string& food) const {food.clear();}
};
typedef shared_ptr<NativeDog> NativeDogPtr;
// C++/CLI wrapper class
ref class ManagedDog
{
NativeDogPtr* base_;
NativeDog& base() {return **base_;}
ManagedDog() {base_ = new NativeDogPtr(new NativeDog);}
~ManagedDog() {if (base_) delete base_;}
!ManagedDog() {delete this;}
property String^ name
{
String^ get() {return ToSystemString(base().name);}
void set(String^ name)
{
base().name = ToStdString(name);
/*** Do I need GC::KeepAlive(name) here? ***/
}
}
String^ bark() {return ToSystemString(base().bark());}
void eat(String^ food)
{
std::string nativeFood = ToStdString(food);
base().eat(nativeFood);
food = ToSystemString(nativeFood);
/*** Do I need GC::KeepAlive(food) here? ***/
}
};
// unmanaged C++ class
struct NativeKennel
{
vector<NativeDogPtr> dogs;
};
// C++/CLI wrapper class
ref class ManagedKennel
{
NativeKennel* base_;
NativeKennel& base() {return *base_;}
IList<ManagedDog^>^ dogs;
void addDog(ManagedDog^ dog)
{
base().dogs.push_back(*dog->base_);
dogs->Add(dog);
/*** Do I need GC::KeepAlive(dog) here? Will the IList manage the ManagedDog lifetimes? ***/
}
};
Right before calling a managed delegate's function pointer.
This is a common failure mode, the garbage collector cannot see any reference held by native code. The managed code must store a reference to the delegate itself to prevent it from getting garbage collected. There's a debugger assistant for this, not sure why you didn't see it. More details in this MSDN Library article.
None of the above!
If you access managed classes in C++/CLI, KeepAlive won't help. You need to pin the data in memory to stop it from relocating afer a garbage collect. In all of these examples, this is done implicitly by the functions you call.
KeepAlive has a different goal. References stored on the stack are subject to garbage collection immediately after the last time the object is dereferenced. KeepAlive prevents this from happening, by extending the lifetime of your object until after the KeepAlive call.