Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
372 views
in Technique[技术] by (71.8m points)

c# - Cannot take the address of, get the size of, or declare a pointer to a managed type

I've done a fair bit of research, but am stuck now as to why I'm still getting this error. I have a struct with the following attributes:

struct Account
{
    //private attributes
    private double mBalance;
    private int mAccountNumber;
    private string mName;
    private string mDateCreated;
}

and am trying to do the following:

class BankManager
{
    //private attributes
    private unsafe Account *mAccounts;
    private unsafe bool *mAccountsAvailable;
    private int mNumberAccounts;
}

Even after turning my class Account to a struct, using "unsafe" for the attributes in class BankManager, and telling the compiler it can use unsafe code (in properties -> Build), I'm still getting this error at

*mAccounts

Any ideas as to why? I'm pretty sure all the types I'm using in the struct are legal to have pointers to in c#. Thanks in advance!

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

The strings in the Account class cause this problem. To understand why, you need to understand how the garbage collector works. It discovers garbage by tracking references to objects. The mName and mDateCreated are such references. The mBalance and mAccountNumber are not, those fields are value types. And, most importantly, the BankManager.mAccounts field is not, it is a pointer.

So the compiler can tell up front that the garbage collector will never be able to see the string references. Because the only way to do so is to go through the mAccount field and its not a reference.

The only cure for this is to limit yourself strictly to value types. The only way to do that for strings is to allocate them in unmanaged memory with, say, Marshal.StringToCoTaskMemUni() and store the IntPtr in the field. It is now out of reach from the garbage collector and cannot get moved by it. You'll now also have the burden of releasing that string.

Clearly that's not practical and prone to cause leaks, the kind of problem that's so common in C programs. Not sure why you are pursuing this at all but do keep in mind that a reference to an object is already a simple pointer so you are not gaining anything by using pointers yourself.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...