Chào mừng đến với Diễn đàn lập trình - Cộng đồng lập trình.
Kết quả 1 đến 9 của 9
  1. #1
    Ngày tham gia
    Sep 2015
    Bài viết
    0

    Lỗi hiển thị và đọc file trong MFC.

    Chào mọi, mình đang tìm hiểu về MFC thì bị gặp 1 quả như thế này.

    + mình có 1 cấu trúc như sau dùng để mô tả các thông tin của 1 rule như sau:
    Mã:
    //// rule.h
    typedef struct _RuleInfo
    {
    	ULONG sourceIp;
    	USHORT sourcePort;
    
    	ULONG destinationIp;
    	USHORT destinationPort;
    
    	UINT protocol;
    	INT action;
    	CHAR *decription;
    }RuleInfo, *PRuleInfo;
    +còn trong file ruledlg.h thì mình khai báo như sau để lấy dữ liệu từ dlg:
    Mã:
    ////////////
    CRuleDlg(CWnd* pParent = NULL);   // standard constructor
    	
    	ULONG srcIp;
    	//unsigned long srcMask;
    	USHORT srcPort;
    
    	ULONG dstIp;
    	//unsigned long dstMask;
    	USHORT dstPort;
    
    	UINT protocol;
    
    	INT cAction;
    	CHAR *dscr;
    ///////////////
    
    	CString	m_ipsource;
    	UINT	m_portsource;
    	CString	m_ipdestination;
    	UINT	m_portDestination;
    	CString	m_action;
    	CString	m_protocol;
    	CString	m_dscr;
    +trong ruledlg.cpp thì mình sẽ lấy các dữ liệu từ dlg như sau:
    Mã:
    ////
            srcPort = m_portsource;
    	dstPort = m_portDestination;
    	dscr = m_dscr.GetBuffer(m_dscr.GetLength());
    +
    Mã:
    int CFirewallAppDoc::AddRule( ULONG srcIp,
    							// unsigned long srcMask,
    							 USHORT srcPort,
    							 ULONG dstIp,
    							// unsigned long dstMask,
    							 USHORT dstPort,
    							 USHORT protocol,
    							 INT action,
    							 CHAR * dscr)
    {
    
    	if(nRules >= MAX_RULES)
    	{
    		return -1;
    	}
    
    	else
    	{
    		rules[nRules].sourceIp		  = srcIp;
    		//rules[nRules].sourceMask	  = srcMask;
    		rules[nRules].sourcePort	  = srcPort;
    		rules[nRules].destinationIp   = dstIp;
    		//rules[nRules].destinationMask = dstMask;
    		rules[nRules].destinationPort = dstPort;
    		rules[nRules].protocol		  = protocol;
    		rules[nRules].action		  = action;
    		rules[nRules].decription = dscr;// .GetBuffer(dscr.GetLength());
    		nRules++;
    	}
    
    	return 0;
    }
    +hàm

    Mã:
    void CMainFrame::OnButtonadd() 
    {
    	CFirewallAppDoc *doc = (CFirewallAppDoc *)GetActiveDocument();
    	CRuleDlg dlg;
    	if(doc->nRules < MAX_RULES )
    	{
    		if(dlg.DoModal() == IDOK)
    		{		
    			if(doc->AddRule(dlg.srcIp,dlg.srcPort, dlg.dstIp, dlg.dstPort, dlg.protocol, dlg.cAction,dlg.dscr) != 0)
    				AfxMessageBox("Error adding the rule");
    
    			else
    			{
    				
    				CFirewallAppView *view = (CFirewallAppView *)GetActiveView();
    
    				view->UpdateList();
    			}
    
    		}
    	}
    
    	else
    		AfxMessageBox("No more Rules are allowed.");
    }
    + hàm này dùng để cập nhật lại danh sách các rule trên của sổ :

    Mã:
    void CFirewallAppView::UpdateList()
    {
    	CFirewallAppDoc *doc = GetDocument();
    	// xoa tat ca cac doi tuong tu vung dieu khien
    	m_rules.DeleteAllItems();
    
    	for(int i=0;i<doc->nRules;i++)
    	{
    			
    		AddRuleToList(doc->rules[i].sourceIp,
    			// doc->rules[i].sourceMask,
    			doc->rules[i].sourcePort,
    			doc->rules[i].destinationIp,
    			//  doc->rules[i].destinationMask,
    			doc->rules[i].destinationPort,
    			doc->rules[i].protocol,
    			doc->rules[i].action,
    			doc->rules[i].decription);// .GetBuffer(doc->rules[i].decription.GetLength()));
    	}
    }
    
    void CFirewallAppView::AddRuleToList(ULONG srcIp,
    									// ULONG srcMask,
    									USHORT srcPort,
    									ULONG dstIp,
    									// ULONG dstMask,
    									USHORT dstPort,
    									UINT protocol,
    									INT action,
    									CString dscr)
    {
    	char ip[16];
    	char port[6];
    	LVITEM it;
    	int pos;
    
    	
    	it.mask		= LVIF_TEXT;
    	it.iItem	= m_rules.GetItemCount();
    	it.iSubItem	= 0;
    	it.pszText	= (srcIp == 0) ? "All" : IpToString(ip, srcIp);
    	pos			= m_rules.InsertItem(&it);
    
    	/*it.iItem	= pos;
    	it.iSubItem	= 1;
    	it.pszText	= IpToString(ip, srcMask);
    	m_rules.SetItem(&it);*/
    
    	it.iItem	= pos;
    	it.iSubItem	= 1;
    	it.pszText	= (srcPort == 0) ? "All" : itoa(srcPort, port, 10);
    	m_rules.SetItem(&it);
    	
    	it.iItem	= pos;
    	it.iSubItem	= 2;
    	it.pszText	= (dstIp == 0) ? "All" : IpToString(ip, dstIp);
    	m_rules.SetItem(&it);
    
    	/*it.iItem	= pos;
    	it.iSubItem	= 4;
    	it.pszText	= IpToString(ip, dstMask);
    	m_rules.SetItem(&it);*/
    
    	it.iItem	= pos;
    	it.iSubItem = 3;
    	it.pszText	= (dstPort == 0) ? "All" : itoa(dstPort, port, 10);
    	m_rules.SetItem(&it);
    
    
    	it.iItem	= pos;
    	it.iSubItem	= 4;
    
    	if(protocol == 1)
    		it.pszText = "ICMP";
    
    	else if(protocol == 6)
    		it.pszText = "TCP";
    
    	else if(protocol == 17)
    		it.pszText = "UDP";
    
    	else
    		it.pszText = "All";
    
    	m_rules.SetItem(&it);
    
    
    	it.iItem	= pos;
    	it.iSubItem	= 5;
    	it.pszText = action ? "Drop" : "Forward";
    	m_rules.SetItem(&it);
    
    	it.iItem = pos;
    	it.iSubItem = 6;
    	it.pszText = dscr.GetBuffer(dscr.GetLength());
    	m_rules.SetItem(&it);
    
    }
    
    mình không hiểu tại sao nếu mình khai bao tất cả các biến
    Mã:
     CString dscr; 
     CString description;
    thì sẽ không bị lỗi như trên giống như kiểu rắN không đầu nó trỏ và hiện ra các giá trị ở các trường khác hoặc như trong hình.
    nhưng nếu lưu ra file rule va load nó lại vào chương trình thì lại có lỗi kiểu như là đọc vào vùng nhớ cấm.
    còn nếu mà khai báo giống như trong chương trình thì load rule vao chuơng trình bình thường nhưng trong phần mo tả thì lại khong hiện được dữ lieu.

    Mong mọi người giúp đỡ một người mới như tôi.

    thanks!

  2. #2
    Ngày tham gia
    Sep 2015
    Bài viết
    0
    Theo ý riêng của mình, bạn nên xem lại các thành phần sau:
    _ Trong cấu trúc RuleInfo bạn đã định nghĩa trường cuối cùng là một con trỏ chuỗi CHAR *
    _ Trong phương thức AddRuleToList() bạn đã định nghĩa tham số cuối cùng có kiểu là CString.
    _ Trong vòng lặp cập nhật lại toàn bộ các Item cho ListView, bạn lại truyền cho tham số cuối của AddRuleToList() một con trỏ chuỗi chứ không phải 1 đối tượng của lớp CString.

    Cũng theo ý riêng của mình, bạn nên sửa lại theo cách đơn giản nhất như sau:
    _ Trong phương thức AddRuleToList() bạn nên định nghĩa tham số cuối cùng có kiểu là CHAR * dscr.
    _ Thay dòng mã cập nhật tại cột cuối cho ListView như sau:

    Mã:
        it.iItem = pos;    it.iSubItem = 6;    it.pszText = dscr.GetBuffer(dscr.GetLength());    m_rules.SetItem(&it);
    thành

    Mã:
        it.iItem = pos;    it.iSubItem = 6;    it.pszText = dscr;    m_rules.SetItem(&it);
    Nếu làm như trên mà vẫn không hết các rắc rối, bạn cứ đưa dự án lên, các anh em sẽ cùng xem xét.
    Thân.

  3. #3
    Ngày tham gia
    Sep 2015
    Bài viết
    0
    @victimlove : Thật xin lỗi bạn, mình chưa hề tạo nick trên Yahoo hay Facebook ( Newbye mà). Làm quen với CĐCV mấy tháng nay chỉ biết mỗi cách liên lạc qua diễn đàn thôi, bạn cứ đưa lên diễn đàn đi, mình giúp không được thì còn anh em khác mà, thân.

  4. #4
    Ngày tham gia
    Sep 2015
    Bài viết
    0
    mình thật sự không hiểu lý do tại sao mà khi mình sử dụng biến CHAR * và sử dụng biến CString thay cho cái tham số cuối cùng của mình là dscr và description. thì nó sảy ra 2 trường hợp như sau:

    1: nếu dùng CHAR thì thì loadrule tức là đọc file .rul mình đã nhập và lưu thì được nhưng cái trường description thì lại khong thể nào hiện được. giống như trường hợp trong bài của mình.
    2: nếu dùng toàn bộ bằng CString thì nó hiển thị theo đúng ý của mình nhưng khi loadrule lên thì nó lại bị lỗi truy xuất vào vùng nhớ cấm. có một kiểu xung đột nao đó giữa CString và CHAR mình khong hiểu rõ lắm.
    MHoang cau cho minh nick Yahoo or facebook minh se gui cho cậu source câu sửa hộ mình với. cùng lắm rồi cái chỗ này mình bị mấy ngày rồi giờ loạn hết cả lên. tại tớ chưa từng làm qua về cái MFC này bao giờ.

  5. #5
    Ngày tham gia
    Sep 2015
    Bài viết
    0
    xin lỗi bạn vì sự phiền hà mà tôi gây ra. đây là link mã nguồn của mình : https://www.mediafire.com/?3034ubg523gzlkh
    mình không hiểu sao lại bị dính lỗi khi sử dụng CString như vậy nữa. mong bạn và mọi người giúp mình xem chỗ nao bị sai hộ mình với. người ngoài cuộc thường minh mẫn hơn, dễ hơn vì kỹ năng của các bạn nữa. hì. THân Ái!

  6. #6
    Ngày tham gia
    Sep 2015
    Bài viết
    0
    @ victimlove :
    Mình chạy thử chức năng Save Rules thì chương trình tạo ra một tập tin mà không có đuôi "rul" cho dù hộp thoại "Save As" đang chọn kiểu để lưu là "Rule Files(*.rul)".
    Chắc là bạn đã xây dựng dự án FirewallApp từ VC++6.0 với kiểu dự án MFC AppWizard (exe).
    Bên dưới là hình ảnh từ khi tạo ra dự án trong Wizard ở bước thứ 4

    Trong hộp thoại bước 4 có nút nhấn Advanced để mở hộp thoại Advanced Options.
    Trong hộp thoại Advanced Options nhập "rul" vào nơi mình vẽ vòng tròn đỏ phía trên thì trong vòng tròn đỏ phía dưới sẽ tự động nhập vào "Firewa Files [*.rul].
    Bạn nhớ lại xem từ lúc tạo dự án, bạn có cài đặt cho các chọn lựa này không. Khi dự án đã tạo ra rồi thì hình như không có cơ hội để thay đổi đuôi mở rộng cho tập tin tài liệu mà chương trình tạo ra ( không biết mình nghĩ vậy có đúng không).
    Trong phương thức : CFirewallAppDoc::Serialize(CArchive& ar) , bạn còn để mã mặc định của Wizard mà chưa thêm mã riêng vào.
    Đây là phương thức dùng để lưu và xuất tập tin, bạn nên thay đổi để có mã phù hợp với chương trình.
    Thôi, chỉ bấy nhiêu thôi, mình sẽ xem tiếp và có gì sẽ thông tin sau, chào.

  7. #7
    Ngày tham gia
    Sep 2015
    Bài viết
    0
    Đúng là bạn nên thêm đuôi mở rộng cho cả 2 nơi lưu và nạp.

    Mình đã xem xét lại và nhận ra rằng vấn đề của bạn nằm ở chỗ : Khi lưu cấu trúc RuleInfo tham số cuối cùng là CString, một đối tượng của lớp CString chỉ nắm giữ một con trỏ tới 1 chuỗi text, trong lớp tài liệu con trỏ này đang có hiệu lực (tức là đang trỏ tới một giá trị hợp lệ). Khi bạn nạp cấu trúc từ tập tin, con trỏ vẫn sẽ giữ giá trị từ lần lưu trước đó ( nhưng bây giờ giá trị này trỏ tới vùng nhớ không còn hợp lệ nữa) , có thể nói đây là trường hợp truy xuất với con trỏ không hợp lệ.

    Để giải quyết vấn đề này, mình tạm đưa ra phương án sau và đã biên dịch , chạy thử thành công với tất cả các chức năng nạp, lưu, xóa, ...


    Mã:
    typedef struct _RuleInfo{    ULONG sourceIp;    USHORT sourcePort;     ULONG destinationIp;    USHORT destinationPort;     UINT protocol;    INT action;    char    szDes[MAX_PATH]; // thay mới với biến này    //CString description; // mã cũ của bạn}RuleInfo, *PRuleInfo;
    Trong khai báo lớp CRuleDlg thay dổi biến như sau

    Mã:
    class CRuleDlg : public CDialog{// Constructionpublic:    CRuleDlg(CWnd* pParent = NULL);          ULONG srcIp;    USHORT srcPort;    ULONG dstIp;    USHORT dstPort;    UINT protocol;    INT cAction;    char    dscr[MAX_PATH]; // Khai báo mình thay thế    //CString dscr; // Đây là khai báo của bạn    // các mã kế tiếp....................
    Trong cài đặt phương thức CRuleDlg::OnOK() thay đổi như sau

    Mã:
        //...................    srcPort = m_portsource;    dstPort = m_portDestination;    wsprintf(dscr,m_dscr.operator LPCTSTR()); // Mã mới mình thay thế    //dscr = m_dscr;// .GetBuffer(m_dscr.GetLength());  // Dòng này là mã cũ của bạn    CDialog::OnOK();    //.....................
    Thay đổi tham số cuối cùng của phương thức AddRule trong lớp CFirewallAppDoc trong khai báo như sau

    Mã:
        int AddRule(ULONG srcIp,USHORT srcPort,ULONG dstIp,USHORT dstPort,USHORT protocol,INT action,char * dscr); // Mã thay mới    //int AddRule(ULONG srcIp,USHORT srcPort,ULONG dstIp,USHORT dstPort,USHORT protocol,INT action,CString dscr); // Mã của bạn
    Và thay đổi trong cài đặt

    Mã:
    int CFirewallAppDoc::AddRule( ULONG srcIp,USHORT srcPort,ULONG dstIp,USHORT dstPort,USHORT protocol,INT action,char * dscr){     if(nRules >= MAX_RULES)    {        return -1;    }     else    {        rules[nRules].sourceIp        = srcIp;        rules[nRules].sourcePort      = srcPort;        rules[nRules].destinationIp   = dstIp;        rules[nRules].destinationPort = dstPort;        rules[nRules].protocol        = protocol;        rules[nRules].action          = action;        wsprintf(rules[nRules].szDes,dscr); // Mã mình thay mới        //rules[nRules].szDes             =  dscr;// .GetBuffer(dscr.GetLength()); // Mã cũ của bạn        nRules++;    }     return 0;}
    Sửa 1 dòng trong cài đặt DeleteRule

    Mã:
    void CFirewallAppDoc::DeleteRule(unsigned int position){     if(position >= nRules)        return;    if(position != nRules - 1)    {        unsigned int i;         for(i = position + 1;i<nRules;i++)        {            rules[i - 1].sourceIp         = rules[i].sourceIp;             rules[i - 1].sourcePort       = rules[i].sourcePort;            rules[i - 1].destinationIp    = rules[i].destinationIp;             rules[i - 1].destinationPort  = rules[i].destinationPort;            rules[i - 1].protocol         = rules[i].protocol;            rules[i - 1].action           = rules[i].action;            wsprintf(rules[i-1].szDes,rules[i].szDes); // Mã mình thay mới            //rules[i - 1].description = rules[i].description; // Mã cũ của bạn        }    }    nRules--;}
    Cuối cùng, thay đổi một số mã trong CMainFrame::OnLoadRules() như sau

    Mã:
    void CMainFrame::OnLoadRules() {    CFile file;    CFileException e;    DWORD nRead;    CFirewallAppDoc *doc = (CFirewallAppDoc *)GetActiveDocument();     CFileDialog dg(TRUE,NULL, NULL, OFN_HIDEREADONLY | OFN_CREATEPROMPT,"Rule Files(*.rul)|*.rul|all(*.*)|*.*||", NULL);    if(dg.DoModal()==IDCANCEL)        return;    CString nf=dg.GetPathName();    if(nf.GetLength() == 0)    {        AfxMessageBox("This file name isn't valid");        return;    }    if( !file.Open(nf, CFile::modeRead, &e ) )    {        AfxMessageBox("Error openning the file.");        return;    }    doc->ResetRules();//  RuleInfo rule; // Bỏ biến này    int i=0; // Thêm biến đếm        do    {        /Read = file.Read(&rule, sizeof(RuleInfo));        nRead = file.Read(&doc->rules[i],sizeof(RuleInfo));// Mã mới                if(nRead == 0)            break;        if(doc->AddRule(doc->rules[i].sourceIp,doc->rules[i].sourcePort,doc->rules[i].destinationIp,doc->rules[i].destinationPort,doc->rules[i].protocol,doc->rules[i].action,doc->rules[i].szDes) != 0) // Mã mới        //if(doc->AddRule(rule.sourceIp,                                // rule.sourceMask,                        //rule.sourcePort,                        //rule.destinationIp,                                //  rule.destinationMask,                        //rule.destinationPort,                        //rule.protocol,                                           //rule.action,                        //rule.description /*.GetBuffer(rule.decription.GetLength())*/) != 0) // Mã cũ của bạn        {             AfxMessageBox("Error adding the rule.");             break;        }        i++;// Mã mới tăng biến đếm     }while (1);     file.Close();     CFirewallAppView *view = (CFirewallAppView *)GetActiveView();     view->UpdateList();}
    Các chức năng khác mình chưa có thời gian xem tiếp, bạn xem qua nếu có thêm thắc mắc gì , anh em sẽ tiếp tục xem xét. Chào nhé.

    - - - Nội dung đã được cập nhật ngày 26-05-2014 lúc 03:13 PM - - -

    Do sửa nhiều nơi nên mình quên đưa lên đoạn sửa chữa cho CFirewallAppView
    Khai báo lại phương thức AddRuleToList

    Mã:
        void AddRuleToList(ULONG srcIp,USHORT srcPort,ULONG dstIp,USHORT dstPort, UINT protocol,INT action,char * dscr); // Mã mới    /*void AddRuleToList(ULONG srcIp,                       // ULONG srcMask,                       USHORT srcPort,                        ULONG dstIp,                       // ULONG dstMask,                       USHORT dstPort,                        UINT protocol,                        INT action,                       CString dscr);*/ // Mã cũ của bạn
    Sửa cài đặt AddRuleToList

    Mã:
    void CFirewallAppView::AddRuleToList(ULONG srcIp,USHORT srcPort,ULONG dstIp,USHORT dstPort,UINT protocol,INT action,char * dscr) // Đã thay tham số cuối{    // ..............................    it.iItem = pos;    it.iSubItem = 6;    it.pszText = dscr;// Mã mình thay đổi    //it.pszText = dscr.GetBuffer(dscr.GetLength()); // Mã cũ của bạn    m_rules.SetItem(&it);    // ..............................}
    Sửa cài đặt của UpdateList

    Mã:
    void CFirewallAppView::UpdateList(){    CFirewallAppDoc *doc = GetDocument();    // xoa tat ca cac doi tuong tu vung dieu khien    m_rules.DeleteAllItems();     for(UINT i=0;i<doc->nRules;i++)    {                    AddRuleToList(doc->rules[i].sourceIp,            // doc->rules[i].sourceMask,            doc->rules[i].sourcePort,            doc->rules[i].destinationIp,            //  doc->rules[i].destinationMask,            doc->rules[i].destinationPort,            doc->rules[i].protocol,            doc->rules[i].action,            doc->rules[i].szDes);// Mã thay đổi            //doc->rules[i].description);// .GetBuffer(doc->rules[i].decription.GetLength())); // Mã cũ    }}

  8. #8
    Ngày tham gia
    Sep 2015
    Bài viết
    0
    Cảm on MHoang!
    nếu mình sửa trong chương trình thành
    Mã:
    LPTSTR expand = ".rul"
    CFileDialog dg(FALSE,expand, NULL, OFN_HIDEREADONLY | OFN_CREATEPROMPT,"Rule Files(*.rul)|*.rul||", this);
    thi nó sẽ lưu có đuôi .rul .

    vấn đề là khi chạy nó show ra 1 cái thông báo ngoại lệ có nội dung như sau:
    Mã:
    Unhandled exception at 0x00B8F11D in FirewallApp.exe: 0xC0000005: Access violation reading location 0xBAADF00D.
    và khi break thì nó la hàm sau:
    Mã:
    static CStringData* __cdecl CloneData(_Inout_ CStringData* pData)
    	{
    		CStringData* pNewData = NULL;
    
    		IAtlStringMgr* pNewStringMgr = pData->pStringMgr->Clone();
    		if( !pData->IsLocked() && (pNewStringMgr == pData->pStringMgr) )
    		{
    			pNewData = pData;
    			pNewData->AddRef();
    		}
    		else
    		{
    			pNewData = pNewStringMgr->Allocate( pData->nDataLength, sizeof( XCHAR ) );
    			if( pNewData == NULL )
    			{
    				ThrowMemoryException();
    			}
    			pNewData->nDataLength = pData->nDataLength;
    			CopyChars( PXSTR( pNewData->data() ), pData->nDataLength+1,
    				PCXSTR( pData->data() ), pData->nDataLength+1 );  // Copy '\0'
    		}
    
    		return( pNewData );
    	}
    lỗi này là do có con trỏ trỏ vào một vùng cấm. nhưng mình sửa như thế nào cũng không được.

  9. #9
    Ngày tham gia
    Sep 2015
    Bài viết
    0
    cám ơn bạn MHoang nhiều. thanks!

 

 

Quyền viết bài

  • Bạn Không thể gửi Chủ đề mới
  • Bạn Không thể Gửi trả lời
  • Bạn Không thể Gửi file đính kèm
  • Bạn Không thể Sửa bài viết của mình
  •