Приложение сервера C ++ MFC с сокетами падает, и я не могу найти ошибку, помогите! - PullRequest
0 голосов
/ 01 апреля 2010

Моя программа имеет один диалог и два сокета. Оба сокета получены из CAsyncSocket, один для прослушивания, другой для получения данных от клиента. Моя программа аварийно завершает работу, когда клиент пытается подключиться к серверному приложению, и серверу необходимо инициализировать приемный сокет.

Это мой диалоговый класс MFC.

class CFileTransferServerDlg : public CDialog
{
   ...
   ListeningSocket ListenSock;
   ReceivingSocket* RecvSock;
   void OnAccept(); // called when ListenSock gets connection attempt
   ...
};

Это мой производный класс сокета для получения данных, который вызывает метод родительских диалогов, когда событие сигнализируется.

class ReceivingSocket : public CAsyncSocket
{
   ...
   CFileTransferServerDlg* m_pDlg; // for accessing parent dialogs controls
   virtual void OnReceive(int nErrorCode);
   ...
}

ReceivingSocket::ReceivingSocket()
{
}

Это диалоговая функция, которая обрабатывает попытку входящего соединения, когда прослушивающий сокет получает уведомление о событии. Вот где происходит сбой.

void CFileTransferServerDlg::OnAccept()
{   
   RecvSock = new ReceivingSocket;   /* CRASH */
}

OR

void CFileTransferServerDlg::OnAccept()
{   
   ReceivingSocket* tmpSock = new ReceivingSocket;
   tmpSock->SetParentDlg(this);

   CString message;
   if( ListenSock.Accept(*tmpSock) )  /* CRASH */
   {
      message.LoadStringW(IDS_CLIENT_CONNECTED);
      m_txtStatus.SetWindowTextW(message);
      RecvSock = tmpSock;
   }
}

Моя программа падает, когда я пытаюсь создать сокет для приема файла, отправленного из клиентского приложения. OnAccept запускается, когда прослушивающий сокет сигнализирует о попытке входящего соединения, но мое приложение вылетает. Что может быть не так? Ошибка в режиме отладки:

Unhandled exception at 0x009c30e1 in FileTransferServer.exe: 0xC0000005: Access violation reading location 0xccccce58.

UPDATE:

Я немного отредактировал код и обнаружил, что внутри sockcore.cpp, где определен Accept, программа завершается сбоем в этой строке кода:

ASSERT(rConnectedSocket.m_hSocket == INVALID_SOCKET);

Я не понимаю, как это может произойти. Класс ReceivingSocket почему-то не сконструирован правильно. Я извлекаю его из CAsyncSock, оставляю конструктор пустым, и независимо от того, где я его создаю, в стеке или в куче, он всегда падает.

Вот полный проект, как клиентский, так и серверный, если кто-нибудь сможет взглянуть на него, я был бы очень благодарен. Прошу прощения за комментарии, они на хорватском.

Проект Visual Studio

Ответы [ 2 ]

0 голосов
/ 01 апреля 2010

Я посмотрел ваш код. Кажется, проблема в том, что вы никогда не звоните ListeningSocket::SetParentDlg(CFileTransferServerDlg* parent). Поскольку вы также не инициализируете указатель m_pDlg в конструкторе ListeningSocket, он имеет случайные значения, и программа может аварийно завершить работу здесь и там при доступе к этому указателю. (У меня тоже был сбой, но немного в другом месте, чем вы указали.)

Я изменил это так:

В ListeningSocket.h изменен конструктор:

ListeningSocket(CFileTransferServerDlg* parent);

Также в ListeningSocket.cpp:

ListeningSocket::ListeningSocket(CFileTransferServerDlg* parent)
   : m_pDlg(parent)
{
}

Конструктор CFileTransferServerDlg изменился следующим образом:

CFileTransferServerDlg::CFileTransferServerDlg(CWnd* pParent /*=NULL*/)
   : CDialog(CFileTransferServerDlg::IDD, pParent),
     ListenSock(this)
{
    m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}

Авария исчезла. Конечно, возможны и другие способы.

Кстати, очень хорошие маленькие программы :) Я, конечно, сейчас их удалю, так как не могу себе позволить лицензионные сборы:)

0 голосов
/ 01 апреля 2010

Может быть, проверьте, правильно ли вы унаследовали ReceivingSocket?

Проверьте это.

...