何処が悪いのか見ていただけますか?

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
史上最悪のデスペナ
記事: 521
登録日時: 14年前

何処が悪いのか見ていただけますか?

#1

投稿記事 by 史上最悪のデスペナ » 13年前

以下のコードを実行するとエラーになるようです。何処が問題なのかエラーメッセージを見ても分かりませんし、
デバッグして追跡しても分かりませんでした。

Crient側

コード:

#include "DxLib.h"
#include "string"

using namespace std;
string flag="OK";

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
	SetDoubleStartValidFlag(TRUE);
	ChangeWindowMode(TRUE);
	DxLib_Init();
	SetDrawScreen(DX_SCREEN_BACK);

	IPDATA IP;
	IP.d1 = 127;
	IP.d2 = 0;
	IP.d3 = 0;
	IP.d4 = 1;

	int n_count = 0;
	int NetHandle; 
	while(ProcessMessage() == 0)
	{
		n_count++;

		//通信を確立
		NetHandle = ConnectNetWork( IP, 9850 );

		//count_sが5になったら強制終了
		if(n_count == 5){
			DrawString( 0, 0, "接続失敗", GetColor( 255 , 255 , 255 ) );
			ScreenFlip();
			DxLib_End();
			return -1;
		}

		string Ver = "0.0";
		// 確立が成功した場合のみ中の処理をする
		if( NetHandle != -1 )
		{ 
			int StrLength = sizeof( Ver ) + 1;
			//データ送信
			NetWorkSend( NetHandle, &Ver, StrLength);
			break;
		} else {
			DrawString( 0, 0, "接続失敗", GetColor( 255 , 255 , 255 ) );
			ScreenFlip();
			DxLib_End();
			return -1;
		}
	}

		string StrBuf;
		int DataLength;
		//データがくるのを待つ
		while( !ProcessMessage() )
		{
			//取得していない受信データ量を得る
			DataLength = GetNetWorkDataLength( NetHandle ) ;
			//取得してない受信データ量が0じゃない場合はループを抜ける
			if( DataLength != 0 ) break ;
		}

		//データ受信
		NetWorkRecv( NetHandle , &StrBuf, DataLength );

		DrawString( 0, 0, StrBuf.c_str(), GetColor(0,0,0) );
		if(strcmp( StrBuf.c_str(), flag.c_str() ) == 0 )
		{
			//接続を断つ
			CloseNetWork( NetHandle );
			goto Login;
		} else {
			//接続を断つ
			CloseNetWork( NetHandle );
			goto UpDate;
		}

//////////////////////////////////////////////////////////////////////////////////////////////////////////

UpDate:;

	//アップデートサーバーに接続
	   {
		   DxLib_End();
		   return -1;
	   }

////////////////////////////////////////////////////////////////////////////////////////////////////////////

Login:;

    DxLib_End();

    return 0;
}
Server側

コード:

#include "コモン.h"
#include "変数.h"

//バージョン
string ver = "0.0";
string Message;
///////////////////////////////////////////

//ネットワークハンドル
int NetHandle = -1, LostHandle;
//接続先IPアドレスデータ
IPDATA Ip;
//受信データ量保存用変数
int DataLength;
//受信データバッファ
string StrBuf;

int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,
			LPSTR lpCmdLine, int nCmdShow )
{
	SetDoubleStartValidFlag(TRUE);
	// ウインドウモード
	ChangeWindowMode( TRUE );

	//DXライブラリ初期化
	if( DxLib_Init() == -1 ) return -1;

	//接続してくるのを待つ状態にする
	PreparationListenNetWork( 9850 );

	//接続してくるかESCキーが押されるまでループ
	while( !ProcessMessage() && CheckHitKey( KEY_INPUT_ESCAPE ) == 0 )
	{
		//新しい接続があったらそのネットワークハンドルを得る
		NetHandle = GetNewAcceptNetWork();
		if( NetHandle != -1 ) break;
	}

	//接続されていたら次に進む
	if( NetHandle != -1 )
	{
		//接続の受付を終了
		StopListenNetWork();

		//接続してきたマシンのIPアドレスを得る
		GetNetWorkIP( NetHandle , &Ip );

		//データが送られて来るまで待つ
		while( !ProcessMessage() )
		{
			//取得していない受信データ量が0以外のときはループから抜ける
			if( GetNetWorkDataLength( NetHandle ) != 0 ) break;
		}

		//データ受信
		DataLength = GetNetWorkDataLength( NetHandle );//データの量を取得
		NetWorkRecv( NetHandle , &StrBuf, DataLength );	//データをバッファに取得

		//受信したデータを描画
		DrawString( 0 , 0 , StrBuf.c_str(), GetColor( 255 , 255 , 255 ) );

		if(strcmp( StrBuf.c_str(), ver.c_str() ) == 0)
		{
			Message = "OK" ;
			//受信成功のデータを送信
			NetWorkSend( NetHandle , &Message, 3);
		} else {
			Message = "NO";
			//受信失敗のデータを送信
			NetWorkSend( NetHandle , &Message , 3);

		}
		DrawString( 0 , 20 , Message.c_str(), GetColor( 255 , 255 , 255 ) );
		//相手が通信を切断するまで待つ
		while( !ProcessMessage() )
		{
			//新たに切断されたネットワークハンドルを得る
			LostHandle = GetLostNetWork();

			//切断された接続が今まで通信してた相手だった場合ループを抜ける
			if( LostHandle == NetHandle ) break;
		}

		//切断確認表示
		DrawString( 0, 16, "切断しました", GetColor( 255 , 255 , 255 ) );

		// キー入力待ち
		WaitKey();
	}

	DxLib_End();	// DXライブラリ使用の終了処理

	return 0;	// ソフトの終了
}
エラーメッセージの内容
SAO-Client.exe の 0x0136e312 でハンドルされていない例外が発生しました: 0xC0000005: 場所 0x3573665b を読み込み中にアクセス違反が発生しました。

エラーの出る場所
DxLib_End();
の後のreturnが終了した後

VC++2010EEを使用しています

YuO
記事: 947
登録日時: 14年前
住所: 東京都世田谷区

Re: 何処が悪いのか見ていただけますか?

#2

投稿記事 by YuO » 13年前

std::stringをネットワークに流したりしてはいけません。
基本的に,ネットワーク上に流すデータは,octet列にシリアライズして流し,受け取った側でデシリアライズして元に戻す必要があります。
大抵の環境で1octetを表すのに利用するのはchar型になるでしょうから,char型の配列という形にシリアライズすることになると思います。

beatle
記事: 1281
登録日時: 13年前
住所: 埼玉
連絡を取る:

Re: 何処が悪いのか見ていただけますか?

#3

投稿記事 by beatle » 13年前

エラーの原因は、stringが内部でヒープ領域へのポインタを持っているからだと思われます。
Clientはポインタをそのままサーバーから受け取り、mainからreturnするときにそのポインタをdeleteしようとします。
しかし、もちろんそのポインタ値はServer側のヒープ領域上でのポインタ値ですから、Clientでそのポインタをdeleteしようとするのは誤りです。

史上最悪のデスペナ
記事: 521
登録日時: 14年前

Re: 何処が悪いのか見ていただけますか?

#4

投稿記事 by 史上最悪のデスペナ » 13年前

ふむふむ。(←よく分かってない)
どうも、どんなデータ型(のアドレスでも可)でも保存できる変数ってありますか?と内容がかぶっているようなのでこちらは解決にしておきます。

結論:データ送信にstringを使ってはいけない

beatle
記事: 1281
登録日時: 13年前
住所: 埼玉
連絡を取る:

Re: 何処が悪いのか見ていただけますか?

#5

投稿記事 by beatle » 13年前

一度、stringを自分で実装してみると僕の言ったことが分かるんじゃないかと思います。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 14年前
住所: 東海地方
連絡を取る:

Re: 何処が悪いのか見ていただけますか?

#6

投稿記事 by softya(ソフト屋) » 13年前

あっちのトピックで
とりあえず構造体を引数にしてしまってポインタやクラスさえ含んでいなければちゃんと受け取れます。
と含んじゃいけないと書いたつもりなんですけどね。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

閉鎖

“C言語何でも質問掲示板” へ戻る