int x = 0;
int *px = &x;
int *py;
假設x所在的記憶體位址是0x1000,又假設int類型的大小為4bytes
當我們執行py = px + 1; 後,py指標中的值會等於 0x1000 + 4 = 0x1004
而執行py = px - 1; 後,py指標中的值會等於 0x1000 - 4 = 0x0FFC
由此可知當一個指標加減一個整數後,其結果還是一個指標,而不是一個整數值
而指標與整數的運算是以該指標的資料型態大小乘上整數後的值做為運算
所以
結果指標 = 運算指標 +/- 運算值;
求結果指標的值的公式就是
結果指標的值 = 運算指標的值 +/- (運算值 * 運算指標的資料型態大小)
再來說說指標之間的相減
就剛剛上面公式,利用簡單的數學將運算值移到=號的左邊,將結果指標移到=號的右邊
就可以得到
運算值 = 運算指標 - 結果指標;
就剛剛求結果指標的值的公式,又可以推導出
(運算值 * 運算指標的資料型態大小) = 運算指標的值 - 結果指標的值
舉個例子來看
假設有兩個int型態的指標pa與pb,pa指向0x2000而pb指向0x2008
r = pb - pa; 則r會是多少? 答案是2。為什麼不是8呢?
就上面的公式看來
(r * 4bytes) = 0x2008 - 0x2000
所以 r = (0x2008 - 0x2000) / 4 = 8 / 4 = 2
這裡又可以推導出另一個問題,那就是不同型態的指標之間不可以相減。
例如:
char* pc; int* pi;
int r = pi - pc; // 編譯器會出錯
因為,就上面的公式而言,運算指標與結果指標的資料型態都是相同的,
依照求值的過程中會需要用到指標的資料型態大小,若是資料型態不同,
則編譯器不知道要以哪個為準。(其時把它當作編譯器規定的就好)
最後說明為什麼兩個指標之間不可以相加。
因為,由上面的公式推導不出來兩個指標要如何相加,
也就是說兩個指標中的位址相加是無意義的。
以上屬個人觀點,若有錯誤的地方請不吝指教。
2012年11月8日 星期四
將sub-thread(子執行緒)的Method(方法)丟到main-thread(主執行緒)執行
執行MainForm中的_a.Start()會產生一個子執行緒
當執行緒發生例外時會去觸發ErrorEvent事件
若再catch中直接呼叫 this.ErrorEvent(this, new EventArgs()); 則會發生(InvalidOperationException)例外
(呼叫執行緒無法存取此物件,因為此物件屬於另一個執行緒)
因為Label1在主執行緒中被建立,所以不能被子執行緒直接呼叫。
因此我們可以透過Dispatcher物件來處理這個問題
class MainForm : Form
{
private A _a = new A();
void Main()
{
_a.ErrorEvent += new EventHandler(Alert);
A.Start();
}
privaet void Alert(object sender, EventArgs e)
{
Label1.Text = "發生例外了!!";
}
}
class A
{
private Thread _thread = null;
private Dispatcher dispatcher = Dispatcher.CurrentDispatcher;
public void Start()
{
if (_thread == null)
{
_thread = new Thread(new ThreadStart(ThreadMethod));
_thread.Start();
}
}
private void ThreadMethod()
{
try
{
// do something;
}
catch (Exception ex)
{
//if (this.ErrorEvent != null) this.ErrorEvent(this, new EventArgs()); <= 錯誤
if (this.ErrorEvent != null) dispatcher.BeginInvoke(this.ErrorEvent, this, new EventArgs()); <= 正確
}
}
}
當執行緒發生例外時會去觸發ErrorEvent事件
若再catch中直接呼叫 this.ErrorEvent(this, new EventArgs()); 則會發生(InvalidOperationException)例外
(呼叫執行緒無法存取此物件,因為此物件屬於另一個執行緒)
因為Label1在主執行緒中被建立,所以不能被子執行緒直接呼叫。
因此我們可以透過Dispatcher物件來處理這個問題
class MainForm : Form
{
private A _a = new A();
void Main()
{
_a.ErrorEvent += new EventHandler(Alert);
A.Start();
}
privaet void Alert(object sender, EventArgs e)
{
Label1.Text = "發生例外了!!";
}
}
class A
{
private Thread _thread = null;
private Dispatcher dispatcher = Dispatcher.CurrentDispatcher;
public event EventHandler ErrorEvent;
public void Start()
{
if (_thread == null)
{
_thread = new Thread(new ThreadStart(ThreadMethod));
_thread.Start();
}
}
private void ThreadMethod()
{
try
{
// do something;
}
catch (Exception ex)
{
//if (this.ErrorEvent != null) this.ErrorEvent(this, new EventArgs()); <= 錯誤
if (this.ErrorEvent != null) dispatcher.BeginInvoke(this.ErrorEvent, this, new EventArgs()); <= 正確
}
}
}
2012年10月6日 星期六
Data Channel Port Range(資料通道連接埠範圍) 設定無效
奇怪~~ 明明將Data Channel Port Range的port設定在5000-5100 相對應的防火牆port也開了
怎麼用filezilla被動連線又出現 '無法取得目錄列表',當把防火牆關閉之後就可以正常取得了
我想問題還是在ftp server上,試著在IIS中將ftp server重新啟動,用netstat檢查一下
發現資料傳輸的port竟然在49319 =口=
怎麼會這樣~~~~ 我不是設定好了嗎? ftp也重開了啊~~ 怎麼會設定無效咧~~
弄了好久終於找到解決的方法了...
原來在IIS中將ftp重新啟動是沒有用的
要到 '服務' 中找到 'Microsoft FTP Service' 然後將此服務重新啟動就完成了
可惡 花了我這麼久的時間 T_T
怎麼用filezilla被動連線又出現 '無法取得目錄列表',當把防火牆關閉之後就可以正常取得了
我想問題還是在ftp server上,試著在IIS中將ftp server重新啟動,用netstat檢查一下
發現資料傳輸的port竟然在49319 =口=
怎麼會這樣~~~~ 我不是設定好了嗎? ftp也重開了啊~~ 怎麼會設定無效咧~~
弄了好久終於找到解決的方法了...
原來在IIS中將ftp重新啟動是沒有用的
要到 '服務' 中找到 'Microsoft FTP Service' 然後將此服務重新啟動就完成了
可惡 花了我這麼久的時間 T_T
2012年9月27日 星期四
jQuery ajax post 在IIS中無法存取 WebService (*.asmx)
有某段程式碼如下,在本機測試時沒問題,一放到IIS上就失敗
$.ajax({
type: "POST",
url: "/Services/CommonService.asmx/QueryNation",
data: '',
async: false,
success: function (result) {
var msg = $(result.lastChild).text();
alert(msg);
}
});
有兩種方式解決:
1. 在IIS上設定虛擬目錄,指向存放webservice的資料夾
2. 在web.config上設定webService區段,如下:
<!-- 設定允許Service存取 -->
<configuration>
<system.web>
<webServices>
<protocols>
<add name="HttpPost" />
</protocols>
</webServices>
</system.web>
</configuration>
2012年9月14日 星期五
替IIS設定網站限制存取IP
先到微軟下載Web Platform後安裝執行
在安裝的項目當中仔細的找一下,會有一個叫IP 及網域限制的項目,找到後並安裝它。
接下來回到IIS設定,在左側點選要限制的站台,然後在右側的檢視功能畫面中找到IP位址及網域限制這個項目並點選開啟它,之後在右側的動作點選新增允許項目,在特定IP位址輸入您要允許的IP後按確定(當然也可以使用IP位址範圍來限制)。
當設定完成之後,必須還要限制除了剛剛設定好的IP之外,其他的任何IP都不得存取此站台,那就在右側的動作點選編輯功能設定,將未指定的用戶端的存取,設定為拒絕後確定。
完成!
注: IIS為7.5
在安裝的項目當中仔細的找一下,會有一個叫IP 及網域限制的項目,找到後並安裝它。
接下來回到IIS設定,在左側點選要限制的站台,然後在右側的檢視功能畫面中找到IP位址及網域限制這個項目並點選開啟它,之後在右側的動作點選新增允許項目,在特定IP位址輸入您要允許的IP後按確定(當然也可以使用IP位址範圍來限制)。
當設定完成之後,必須還要限制除了剛剛設定好的IP之外,其他的任何IP都不得存取此站台,那就在右側的動作點選編輯功能設定,將未指定的用戶端的存取,設定為拒絕後確定。
完成!
注: IIS為7.5
解決:使用者'IIS APPPOOL\ASPNET v4.0'的登入失敗
發生的原因主要是因為網站所使用的'應用程式集區',預設使用'ApplicationPoolIdentity'做為識別,因此當網站使用integrated security=SSPI字串登入SQL Server時就會發生此錯誤。
解決的方法有兩種:
1. 不要使用 integrated security=SSPI 做為驗證的方法,改用 User Id=”xxx”; Password=”ooo” 來登入資料庫。
2. 到IIS的應用程式集區,選擇您的網站所使用的集區,按右鍵 -> 進階設定 -> 識別,選擇NetworkService後按確定。接下來使用Microsoft SQL Server Management Studio,登入到您的SQL Server,找到安全性 -> 登入 -> 按右鍵點選’新增登入’-> 點選'搜尋'-> 輸入net ->點選’檢查名稱’ -> 在相符名稱當中選擇’NETWORK SERVICE’ -> 確定 -> 確定 -> 確定。接下來到伺服器角色把'sysadmin'打勾,按確定後完成。(當然伺服器角色的權限可依安全需求變更。)
解決的方法有兩種:
1. 不要使用 integrated security=SSPI 做為驗證的方法,改用 User Id=”xxx”; Password=”ooo” 來登入資料庫。
2. 到IIS的應用程式集區,選擇您的網站所使用的集區,按右鍵 -> 進階設定 -> 識別,選擇NetworkService後按確定。接下來使用Microsoft SQL Server Management Studio,登入到您的SQL Server,找到安全性 -> 登入 -> 按右鍵點選’新增登入’-> 點選'搜尋'-> 輸入net ->點選’檢查名稱’ -> 在相符名稱當中選擇’NETWORK SERVICE’ -> 確定 -> 確定 -> 確定。接下來到伺服器角色把'sysadmin'打勾,按確定後完成。(當然伺服器角色的權限可依安全需求變更。)
2011年11月29日 星期二
[asp.net] 永久登入,延長(自訂)表單驗證(Forms Authentication)保存時間
有些網站會提供記錄使用者登入密碼二週或永久
如pchome的 '記住我的密碼' 、 yahoo的 '保持我的登入狀態'
如pchome的 '記住我的密碼' 、 yahoo的 '保持我的登入狀態'
若使用Login控制項時,可以在Login控制項的LoggedIn事件裡面加入下面的程式碼:
// 使用Login控制項,在成功登入之後會自動幫我們建立驗證的cookie
// 所以我們必須拿出來重新修改,改成我們希望延長的時間
HttpCookie cookie = HttpContext.Current.Request.Cookies[FormsAuthentication.FormsCookieName];
// 從cookie解碼還原票證
FormsAuthenticationTicket oldTicket = FormsAuthentication.Decrypt(cookie.Value);
// 建立新的票證 註:DateTime.Now.AddYears(1)為票證到期日,也就是希望延長的期限
FormsAuthenticationTicket newTicket = new FormsAuthenticationTicket(oldTicket.Version,
oldTicket.Name, DateTime.Now, DateTime.Now.AddYears(1), oldTicket.IsPersistent, oldTicket.UserData, FormsAuthentication.FormsCookiePath);
// 使用新的票證來建立新的驗證cookie
string cookiestr = FormsAuthentication.Encrypt(newTicket);
HttpCookie newCookie = new HttpCookie(FormsAuthentication.FormsCookieName, cookiestr);
newCookie.Expires = newTicket.Expiration;
newCookie.Path = FormsAuthentication.FormsCookiePath;
// 最後將新的驗證cookie重新寫回給user
Response.Cookies.Add(newCookie);
-----完成-----
訂閱:
文章 (Atom)