ページ 11

2つの通信プログラム間のエラー

Posted: 2014年9月01日(月) 10:16
by nana
UDP通信プログラム

コード:

char *p_pixcel;  
char **fcolor_Send;
LoopNum_Send= 1;

NUI_LOCKED_RECT colorLockedRect;
		pColorFrameTexture->LockRect( 0, &colorLockedRect, nullptr, 0 );

for(j=0;j<PIXCEL*4;j++){
			//fcolor_Send[LoopNum_Send][j] = colorLockedRect.pBits[j];//pBitsはbyte型 *pBitsです
			snprintf(&p_pixcel[j],8,"%d",colorLockedRect.pBits[j]);
			sprintf(fcolor_Send[LoopNum_Send],&p_pixcel[0]);
}
カメラから取得した画像データの byte型をc++言語で認識できる型に変換して,もう一度それをbyte型にしたいのですができなくて困っています.
おそらく型が違うため,通信できないと考えているので教えてください.

環境はvc++2010express

Re: 2つの通信プログラム間のエラー

Posted: 2014年9月01日(月) 13:03
by sleep
#define _CRT_SECURE_NO_WARNINGS を指定したくないということですよね?

snprintfは、char*を受け付けているので、キャストしてコンパイルを通そうとすると
_CRT_SECURE_NO_WARNINGSを指定する必要が出てきます。
なので、snprintfではなく、代わりにmemcpyかCopyMemoryを使用してください。
(受け付けているのがvoid*型なので)型を気にせず複数バイトをバイト単位でまとめてコピーできます。

memcpyは、string.h
CopyMemoryは、windows.h
をインクルードすれば使用できます。
オフトピック
CopyMemoryは、memcpyを#defineしただけのものです。

Re: 2つの通信プログラム間のエラー

Posted: 2014年9月01日(月) 13:31
by sleep
もしくは、
_CRT_SECURE_NO_WARNINGS自体は、非推奨の関数を指しているので
_snprintf_s なら使用可能かと思います。

Re: 2つの通信プログラム間のエラー

Posted: 2014年9月01日(月) 15:11
by sleep
何か違う意味に見えるような気がしてならないので・・・訂正を入れておきます。
sleep さんが書きました: snprintfは、char*を受け付けているので、キャストしてコンパイルを通そうとすると
_CRT_SECURE_NO_WARNINGSを指定する必要が出てきます。
正しくは、
snprintfは、char*を受け付けていますが、キャストしてコンパイルを通そうとしても通りません。
(非推奨のため)_CRT_SECURE_NO_WARNINGSを指定する必要があります。

Re: 2つの通信プログラム間のエラー

Posted: 2014年9月01日(月) 15:40
by nana
sleepさんありがとうございます.

byte型=unsigned char型とわかったので,

コード:

unsigned char **fcolor_Send;
for(j=0;j<PIXCEL*4;j++){
			fcolor_Send[LoopNum_Send][j] = colorLockedRect.pBits[j];
}
に変えてみました.すると

0x00e85291 でハンドルされていない例外が発生しました: 0xC0000005: 場所 0x031f8000 に書き込み中にアクセス違反が発生しました。
このようなエラーが出てきました.

fcolor_Send[LoopNum_Send][j] = colorLockedRect.pBits[j];

中断箇所は

コード:

fcolor_Send= (unsigned char **)malloc(seq*sizeof(unsigned char*));
	if(fcolor_Send == NULL) {
		printf("メモリが確保できません:fcolor_Send\n");
		return 0;
	}for (i=0 ; i < PIXCEL*4*8 ; i++) {
●        fcolor_Send[i] = (unsigned char*)malloc(sizeof(unsigned char)*4*PIXCEL*8);
    }
fcolor_Recv= (unsigned char **)malloc(seq*sizeof(unsigned char *));
	if(fcolor_Recv == NULL) {
		printf("メモリが確保できません:fcolor_Send\n");
		return 0;
	}for (i=0 ; i < PIXCEL*4*8 ; i++) {
 ●       fcolor_Recv[i] = (unsigned char*)malloc(sizeof(unsigned char)*4*PIXCEL*8);
    }

●の箇所で通信を始めるとエラーが発生してしまいます.

unsigned char **fcolor_Send,**fcolor_Recv

PIXCELは画面の値320*480にしてあります.

Re: 2つの通信プログラム間のエラー

Posted: 2014年9月01日(月) 15:59
by sleep
nanaさん、教えてください。

下記のコードの”seq”という変数と

コード:

fcolor_Send= (unsigned char **)malloc(seq*sizeof(unsigned char*));
下記のコードの ”PIXCEL*4*8” は同じ数になりますか?

コード:

    }for (i=0 ; i < PIXCEL*4*8 ; i++) {
確保したメモリ以上に回数を回していたりしませんか?

Re: 2つの通信プログラム間のエラー

Posted: 2014年9月01日(月) 20:21
by nana
sleepさんありがとうございます.

同じではありませんでした.

コード:

#define seq 10000		//送受信するパケット数

//    PIXCEL*4*8 = (320*480)*4*8

となっています.

コード:


#define seq (320*480)*4*8

と修正したらいいですか?

seq が PIXCEL*4*8 を超えていれば動くということでしょうか?

Re: 2つの通信プログラム間のエラー

Posted: 2014年9月01日(月) 21:09
by sleep
以下のコードがあったとします。

コード:

fcolor_Send= (unsigned char **)malloc(seq*sizeof(unsigned char*));
    if(fcolor_Send == NULL) {
        printf("メモリが確保できません:fcolor_Send\n");
        return 0;
    }for (i=0 ; i < PIXCEL*4*8 ; i++) {
●        fcolor_Send[i] = (unsigned char*)malloc(sizeof(unsigned char)*4*PIXCEL*8);
    }
ここで確保しているメモリ領域は、整理してみると
sizeof(unsigned char*) は4バイトのサイズだったとします。

コード:

fcolor_Send= (unsigned char **)malloc(seq*sizeof(unsigned char*));
上記は、4バイトの空き箱を seq 個(10000個)確保したことになります。

用意した空き箱はseq個(10000個)で、1つの箱に1つの名札(ポインタのアドレス)しか入れられません。

コード:

    }for (i=0 ; i < PIXCEL*4*8 ; i++) {
●        fcolor_Send[i] = (unsigned char*)malloc(sizeof(unsigned char)*4*PIXCEL*8);
    }
しかし、こちらでやっていることは
(unsigned char*)malloc(sizeof(unsigned char)*4*PIXCEL*8) は、4バイトの住所の書かれた名札
(ポインタのアドレス)を返すと思ってください。
その4バイトの名札を fcolor_Send に入れていく訳ですが、空き箱はseq個(10000個)しかないのですけど
PIXCEL*4*8個(4915200個)の箱があるものだと思い込んでいて、がんばって入れようとしています。

つまり、状態としては seq個(10000個)までは問題なく動作していると思われますが
seq個(10000個)を超えた後に問題が発生していると思います。

どうすれば良いのか、と言うと仕様に合わせるしかないのですけど
仕様はどうなっていますか?
送受信パケット数に制限があるのでしょうか?
nana さんが書きました:

コード:

#define seq 10000       //送受信するパケット数
 
//    PIXCEL*4*8 = (320*480)*4*8
となっています.

コード:

#define seq (320*480)*4*8
と修正したらいいですか?
普通に考えると
" PIXCEL*4*8 " は、これは画像用の領域ですよね?
なのでどちらかというと、
(unsigned char*)malloc(sizeof(unsigned char)*4*PIXCEL*8) で、1画像用の領域を確保しているようなので
forループの回数を ”PIXCEL*4*8” から ”seq” に するような気がします。

コード:

fcolor_Send= (unsigned char **)malloc(seq*sizeof(unsigned char*));
    if(fcolor_Send == NULL) {
        printf("メモリが確保できません:fcolor_Send\n");
        return 0;
    }for (i=0 ; i < seq ; i++) {
●        fcolor_Send[i] = (unsigned char*)malloc(sizeof(unsigned char)*4*PIXCEL*8);
    }
fcolor_Recv= (unsigned char **)malloc(seq*sizeof(unsigned char *));
    if(fcolor_Recv == NULL) {
        printf("メモリが確保できません:fcolor_Send\n");
        return 0;
    }for (i=0 ; i < seq ; i++) {
 ●       fcolor_Recv[i] = (unsigned char*)malloc(sizeof(unsigned char)*4*PIXCEL*8);
    }
まずは、仕様のご確認をお願いします。

Re: 2つの通信プログラム間のエラー

Posted: 2014年9月01日(月) 22:31
by nana
sleepさん,ありがとうございます.

勉強不足で仕様の意味がよく理解できませんが,c++を使って取得した映像を早く送りたいです.

送受信パケット数に制限はありませんが,できるだけ早く取得した映像を送受信したいです.

指摘のところでは直りました.エラーはなくなったのですが,値の受け渡しができないようで,

コード:

unsigned char color[PIXCEL*4*8];
unsigned char *fcolo;

                      for(i = 0; i < PIXCEL*4*8; i++){
			packet.color[i] = *(fcolor+i);
		}
	
上手く数値が入りません.

Re: 2つの通信プログラム間のエラー

Posted: 2014年9月01日(月) 22:31
by nana
sleepさん,ありがとうございます.

勉強不足で仕様の意味がよく理解できませんが,c++を使って取得した映像を早く送りたいです.

送受信パケット数に制限はありませんが,できるだけ早く取得した映像を送受信したいです.

指摘のところでは直りました.エラーはなくなったのですが,値の受け渡しができないようで,

コード:

unsigned char color[PIXCEL*4*8];
unsigned char *fcolo;

                      for(i = 0; i < PIXCEL*4*8; i++){
			packet.color[i] = *(fcolor+i);
		}
	
上手く数値が入りません.

Re: 2つの通信プログラム間のエラー

Posted: 2014年9月01日(月) 22:59
by sleep
仕様というのは、簡単にいうと作るときに決めた完成イメージのことですね。

fcolo という名前で宣言されているようですが、

コード:

unsigned char *fcolo;
fcolor という名前で使用されているようです。
掲載時の書き間違いですか?

コード:

packet.color[i] = *(fcolor+i);

Re: 2つの通信プログラム間のエラー

Posted: 2014年9月01日(月) 23:05
by nana
すみません,書き間違えました.

完成イメージは,できるだけ遅延なく取得した映像をおくるプログラムです.

Re: 2つの通信プログラム間のエラー

Posted: 2014年9月01日(月) 23:13
by sleep
教えていただいてありがとうございます。

ちょっと掲示いただいたコードだけでは判別付きませんが

コード:

packet.color[i] = *(fcolor+i);
fcolor には値は値が入っていますか?
受け渡す側なので、こちらに値が入っているかどうかですね。

もし、大丈夫であれば
受け取った側 packet.color が、そこのforループ処理のあとに
受け取った値を削除していないかどうか確認するしかないですね。

Re: 2つの通信プログラム間のエラー

Posted: 2014年9月02日(火) 17:53
by nana
ありがとうございます.

コード:

MMRESULT timerID;

timerID = timeSetEvent(1,    // 間隔[ms]
                                   1, //0,              // 分解能
                                   Send_Loop,      // 割り込み関数
                                   0,       //(DWORD)&cnt,    // ユーザーパラメータ
                                   TIME_PERIODIC | TIME_CALLBACK_FUNCTION  // 動作フラグ
                              );

if( !timerID ){
		fprintf(stderr, "タイマー登録に失敗\n");
		exit(1);
	}
timeSetEventを使用したいのですが,できず,”タイマー登録に失敗”とエ

Re: 2つの通信プログラム間のエラー

Posted: 2014年9月02日(火) 17:57
by nana
エラーをはいてしまいます.助けてください.

変えていたら,昨夜の問題よりも前にエラーを吐くようになってしまいました.
すみません.

Re: 2つの通信プログラム間のエラー

Posted: 2014年9月02日(火) 19:18
by sleep
nanaさん、落ち着いてください。大丈夫です。

今はどんなエラーが出てますかね?

Re: 2つの通信プログラム間のエラー

Posted: 2014年9月02日(火) 19:27
by sleep
試してみていただきたいんですけど、
以下のテストコードを実行しても同じエラーが出ますか?

コード:

#pragma comment(lib, "winmm.lib")
#include <windows.h>

#include <iostream>
using namespace std;

void CALLBACK Send_loop(UINT uTimerID, UINT uMsg, DWORD dwUser, DWORD dw1, DWORD dw2) {
	cout << "送信しました。" << endl;
}

int main(int argc, char* argv[])
{
	MMRESULT timerID;
	timerID = timeSetEvent(1000, 1, (LPTIMECALLBACK)Send_loop, (DWORD)NULL, TIME_PERIODIC);
	if (!timerID)
	{
		cout << "timeSetEvent" << endl;
		return -1;
	}

	// Enterキーを押下で終了
	cin.ignore();
	timeKillEvent(timerID);
	return 0;
}
それと、間隔(ms) 1ミリ秒はちょっと短すぎるかもしれないですね。
せめて100ms以上とかですね。

Re: 2つの通信プログラム間のエラー

Posted: 2014年9月02日(火) 22:46
by sleep
nanaさん、もし Windows APIを呼び出してエラーが発生したら
以下の GetErrorMessage()をコードにコピペして、GetErrorMessage(GetLastError()) を呼び出してみてください。
string型でエラーメッセージを日本語で教えてくれます。

動作確認ができるテストコードを張っておきます。

コード:

#pragma comment(lib, "ws2_32.lib")
#include <winsock2.h>

#include <iostream>
#include <string>
using namespace std;

string GetErrorMessage(DWORD dwErrorCode)
{
	HLOCAL hLocal = NULL;

	DWORD systemLocal = MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL);

	BOOL bResult = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_ALLOCATE_BUFFER, NULL, dwErrorCode, systemLocal, (PTSTR)&hLocal, 0, NULL);
	if (!bResult) {
		HMODULE hDll = LoadLibraryEx(TEXT("netmsg.dll"), NULL, DONT_RESOLVE_DLL_REFERENCES);
		if (hDll != NULL) {
			bResult = FormatMessage(FORMAT_MESSAGE_FROM_HMODULE | FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_ALLOCATE_BUFFER, hDll, dwErrorCode, systemLocal, (PTSTR)&hLocal, 0, NULL);
			FreeLibrary(hDll);
		}
	}

	string str;

	if (bResult && (hLocal != NULL)) {
		str = (PCTSTR)LocalLock(hLocal);
		LocalFree(hLocal);
	}
	else {
		str = "No text found for this error code";
	}

	return str;
}

void main() {
	//例えば、WSAEPROTOTYPE (10041) をセット (※仮にこのエラーが起きたとします)
	//http://support.microsoft.com/kb/819124/ja を参照のこと
	SetLastError(WSAEPROTOTYPE);

	//対応する以下のエラーメッセージを表示
	//ソケットの関数呼び出しでプロトコルが指定されましたが、要求したソケットの種類の形式をサポートしていません。
	cout << GetErrorMessage(GetLastError()) << endl;

	cin.ignore();  //Enterキー押下で終了
}
どんな問題が発生していて、nanaさんが何を対応してあげれば良いのか教えてくれます。
エラーが発生して、もし困ったときに使ってみてください。

Re: 2つの通信プログラム間のエラー

Posted: 2014年9月03日(水) 11:33
by nana
sleepさん,わざわざありがとう御座います.

頂いたエラーを日本語で教えてくれるコードなのですが,=の部分に赤線が出てきてしまい使えませんでした.
このGetErrorMessageはどこに入れても全体のエラーを教えてくれるのでしょうか?
プログラムの最後につければいいのでしょうか.

コード:

      
  str = (PCTSTR)LocalLock(hLocal);

Re: 2つの通信プログラム間のエラー

Posted: 2014年9月03日(水) 12:03
by nana
頂いたテストプログラムを実行したところ,timeSetEventは正常に働きtimerIDにNULLが入ることはありませんでした.

しかし,私のプログラムエラーはデバックなどで出る警告やエラーではないのでどこが悪いのかわからず行き詰っています.

Re: 2つの通信プログラム間のエラー

Posted: 2014年9月03日(水) 16:51
by sleep
少しnanaさんのコーディングスタイルに合わせました。
使用する位置は下記のとおりとなります。

一度このテストコードが動くかどうか試してみていただけますか?
(コンパイルさえ通れば GetErrorMessage(GetLastError()) の動作は確認しなくても大丈夫だと思います)

コード:

#pragma comment(lib, "winmm.lib")
#pragma comment(lib, "ws2_32.lib")
#include <winsock2.h>

#include <stdio.h>  // もしくは、#include <iostream> でもOK

void GetErrorMessage(DWORD dwErrorCode)
{
	HLOCAL hLocal = NULL;
	DWORD systemLocal = MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL);

	BOOL bResult = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_ALLOCATE_BUFFER, NULL, dwErrorCode, systemLocal, (PTSTR)&hLocal, 0, NULL);
	if (!bResult) {
		HMODULE hDll = LoadLibraryEx(TEXT("netmsg.dll"), NULL, DONT_RESOLVE_DLL_REFERENCES);
		if (hDll != NULL) {
			bResult = FormatMessage(FORMAT_MESSAGE_FROM_HMODULE | FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_ALLOCATE_BUFFER, hDll, dwErrorCode, systemLocal, (PTSTR)&hLocal, 0, NULL);
			FreeLibrary(hDll);
		}
	}

	if (bResult && (hLocal != NULL)) {
		fprintf(stderr, (PTCHAR)LocalLock(hLocal));
		LocalFree(hLocal);
	}
	else {
		fprintf(stderr, TEXT("No text found for this error code"));
	}
}

void CALLBACK Send_loop(UINT uTimerID, UINT uMsg, DWORD dwUser, DWORD dw1, DWORD dw2) {
	fprintf(stdout, "送信しました。\n");
}

int main() {
	//例えば、WSAEPROTOTYPE (10041) をセット (※仮にこのエラーが起きたとします)
	//http://support.microsoft.com/kb/819124/ja を参照のこと
	SetLastError(WSAEPROTOTYPE);

	//対応する以下のエラーメッセージを表示
	//ソケットの関数呼び出しでプロトコルが指定されましたが、要求したソケットの種類の形式をサポートしていません。
	GetErrorMessage(GetLastError());

	fprintf(stdout, "\nEnterキーを押下すると次に用意しているtimeSetEventの処理へ進みます。\n");
	getchar();  // Enterキーを押下すると次へ進む(注:押下するまでは進みません)

	MMRESULT timerID;
	timerID = timeSetEvent(1000, 1, (LPTIMECALLBACK)Send_loop, (DWORD)NULL, TIME_PERIODIC);
	if (!timerID)
	{
		//ここで使います。基本的には timeSetEventなどのWindows APIを呼び出した直後です。
		//GetLastError()というのは直前に実行されたWindows APIの終了コードを返します。
		//そのため、他のWindows APIを呼び出すと上書きされてしまうので、
		//必ずWindows APIを呼んだ直後に(エラー処理の中で)使用します。
		GetErrorMessage(GetLastError());

		fprintf(stderr, "タイマー登録に失敗\n");
		getchar();  // Enterキーを押下で終了
		exit(1);
	}

	fprintf(stdout, "もう一度Enterキーを押下するとプログラムを終了します。\n");
	getchar();  // Enterキーを押下で終了
	timeKillEvent(timerID);
	return 0;
}
もし、このテストコードがうまく動いたら
今回 GetErrorMessage のコードを新しくしたので、お手数ですが
nanaさんのコードの方へ GetErrorMessage 関数を 再度コピペし直してください。
その上で、テストコードと同じ場所に GetErrorMessage(GetLastError()) を書いてみてください。

あと、インクルードしているヘッダファイルも確認してください。
Windowsのネットワーク処理 WinSockのエラーも拾えるようにしているので、以下4行が必要となります。

コード:

#pragma comment(lib, "winmm.lib")
#pragma comment(lib, "ws2_32.lib")
#include <winsock2.h>

#include <stdio.h>  // もしくは、#include <iostream> でもOK
よろしくお願いします。

Re: 2つの通信プログラム間のエラー

Posted: 2014年9月03日(水) 17:04
by sleep
[quote=nana]
しかし,私のプログラムエラーはデバックなどで出る警告やエラーではないのでどこが悪いのかわからず行き詰っています.
[/quote]

nanaさんが fprintfで出力しているデバッグ用エラーメッセージとは別に
Windows自体が管理しているエラー情報があります。
GetErrorMessage は、そのWindowsが管理しているエラー情報を出力してくれます。

多分これがうまく動くようになれば、Windowsで発生している問題が分かると思います。

Re: 2つの通信プログラム間のエラー

Posted: 2014年9月03日(水) 17:42
by sleep
必要なヘッダファイルは4行と書いてしまいましたが、
#pragma comment(lib, "winmm.lib") は、timeSetEvent 用なので

正確には GetErrorMessage に必要なのは、3行ですね。

コード:

#pragma comment(lib, "ws2_32.lib")
#include <winsock2.h>
 
#include <stdio.h>  // もしくは、#include <iostream> でもOK
あと、以下に改行コード抜けていました。

コード:

fprintf(stderr, TEXT("No text found for this error code\r\n"));
書き忘れてましたので、ここで。
nana さんが書きました: このGetErrorMessageはどこに入れても全体のエラーを教えてくれるのでしょうか?
全体のエラーは残念ながら教えてくれません。
GetErrorMessage を入れる位置はテストコード通りとなります。
GetErrorMessage は、Windows API呼び出し1つに対し、1つのエラーメッセージを返す関数となっています。

Re: 2つの通信プログラム間のエラー

Posted: 2014年9月03日(水) 18:01
by sleep
nanaさん、何度もすみません。

エラー出力があまりにも味気なかったので、以下のように変更しました。

コード:

fprintf(stderr, "ErrorCode: %d\r\n%s\r\n", dwErrorCode, (PTCHAR)LocalLock(hLocal));
今までの修正を加えたものを再度載せておきます。
こちらで動作するようなら、こちらのテストコードをご使用ください。
こちらで動作しないようなら、前のテストコードをご使用ください。
(前のコードはコンパイル時の問題を減らせるように極力やっていることを最小限にしています)

コード:

#pragma comment(lib, "winmm.lib")
#pragma comment(lib, "ws2_32.lib")
#include <winsock2.h>

#include <stdio.h>  // もしくは、#include <iostream> でもOK

void GetErrorMessage(DWORD dwErrorCode)
{
	HLOCAL hLocal = NULL;
	DWORD systemLocal = MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL);

	BOOL bResult = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_ALLOCATE_BUFFER, NULL, dwErrorCode, systemLocal, (PTSTR)&hLocal, 0, NULL);
	if (!bResult) {
		HMODULE hDll = LoadLibraryEx(TEXT("netmsg.dll"), NULL, DONT_RESOLVE_DLL_REFERENCES);
		if (hDll != NULL) {
			bResult = FormatMessage(FORMAT_MESSAGE_FROM_HMODULE | FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_ALLOCATE_BUFFER, hDll, dwErrorCode, systemLocal, (PTSTR)&hLocal, 0, NULL);
			FreeLibrary(hDll);
		}
	}

	if (bResult && (hLocal != NULL)) {
		fprintf(stderr, "ErrorCode: %d\r\n%s\r\n", dwErrorCode, (PTCHAR)LocalLock(hLocal));
		LocalFree(hLocal);
	}
	else {
		fprintf(stderr, TEXT("No text found for this error code\r\n"));
	}
}

void CALLBACK Send_loop(UINT timerID, UINT uMsg, DWORD dwUser, DWORD dw1, DWORD dw2) {
	fprintf(stdout, "送信しました。\n");
}

int main() {
	//例えば、WSAEPROTOTYPE (10041) をセット (※仮にこのエラーが起きたとします)
	//http://support.microsoft.com/kb/819124/ja を参照のこと
	SetLastError(WSAEPROTOTYPE);

	//対応する以下のエラーメッセージを表示
	//ソケットの関数呼び出しでプロトコルが指定されましたが、要求したソケットの種類の形式をサポートしていません。
	GetErrorMessage(GetLastError());

	fprintf(stdout, "\nEnterキーを押下すると次に用意しているtimeSetEventの処理へ進みます。\n");
	getchar();  // Enterキーを押下すると次へ進む(注:押下するまでは進みません)


	//ここから上は GetErrorMessage のテストコード
	//------------------------------------------------------------------------------------
	//ここから下は GetErrorMessage の入れる位置の説明です。


	MMRESULT timerID;
	timerID = timeSetEvent(1000, 1, (LPTIMECALLBACK)Send_loop, (DWORD)NULL, TIME_PERIODIC);
	if (!timerID)
	{
		//ここで使います。基本的には timeSetEventなどのWindows APIを呼び出した直後です。
		//GetLastError()というのは直前に実行されたWindows APIの終了コードを返します。
		//そのため、他のWindows APIを呼び出すと上書きされてしまうので、
		//必ずWindows APIを呼んだ直後に(エラー処理の中で)使用します。
		GetErrorMessage(GetLastError());

		fprintf(stderr, "タイマー登録に失敗\n");
		fprintf(stdout, "\nもう一度Enterキーを押下するとプログラムを終了します。\n");
		getchar();  // Enterキーを押下で終了
		exit(1);
	}

	fprintf(stdout, "もう一度Enterキーを押下するとプログラムを終了します。\n");
	getchar();  // Enterキーを押下で終了
	timeKillEvent(timerID);
	return 0;
}

Re: 2つの通信プログラム間のエラー

Posted: 2014年9月03日(水) 20:20
by sleep
nanaさん、すいません。
ふと、とても肝心なことを思い出しました。

timeSetEvent は、成功・失敗しか返されず、GetLastError()などでどのようなエラーが発生したのか確認できませんでした。
再度MSDNで確認しました。
http://msdn.microsoft.com/en-us/library ... s.85).aspx
オフトピック
Note This function is obsolete. New applications should use CreateTimerQueueTimer to create a timer-queue timer.
と、書かれてあるように既にこの関数は廃止となっており、CreateTimerQueueTimerを使ってくださいとのことです。
(現状でも使えなくはないですが、何のエラーが起きたのかGetLastError()でエラー情報が取得できません)
オフトピック
あと、timeSetEventは、16個までしかタイマーを作成できないという上限があります。
と、いうことで CreateTimerQueueTimer の使い方を含めたテストコードを載せておくことにします。
それほど違いはありませんので、安心してください。
オフトピック
CreateTimerQueueTimer は、GetLastError()でエラー情報を取得できます。

コード:

#pragma comment(lib, "winmm.lib")
#pragma comment(lib, "ws2_32.lib")
#include <winsock2.h>

#include <stdio.h>  // もしくは、#include <iostream> でもOK

void GetErrorMessage(DWORD dwErrorCode)
{
	HLOCAL hLocal = NULL;
	DWORD systemLocal = MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL);

	BOOL bResult = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_ALLOCATE_BUFFER, NULL, dwErrorCode, systemLocal, (PTSTR)&hLocal, 0, NULL);
	if (!bResult) {
		HMODULE hDll = LoadLibraryEx(TEXT("netmsg.dll"), NULL, DONT_RESOLVE_DLL_REFERENCES);
		if (hDll != NULL) {
			bResult = FormatMessage(FORMAT_MESSAGE_FROM_HMODULE | FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_ALLOCATE_BUFFER, hDll, dwErrorCode, systemLocal, (PTSTR)&hLocal, 0, NULL);
			FreeLibrary(hDll);
		}
	}

	if (bResult && (hLocal != NULL)) {
		fprintf(stderr, TEXT("ErrorCode: %d\r\n%s\r\n"), dwErrorCode, (PTCHAR)LocalLock(hLocal));
		LocalFree(hLocal);
	}
	else {
		fprintf(stderr, TEXT("No text found for this error code\r\n"));
	}
}

//void CALLBACK Send_loop(UINT timerID, UINT uMsg, DWORD dwUser, DWORD dw1, DWORD dw2) {
//	fprintf(stdout, "送信しました。\n");
//}
void CALLBACK Send_loop(PVOID pvContext, BOOLEAN fTimeout) {
	fprintf(stdout, "送信しました。\n");
}

int main() {
	//例えば、WSAEPROTOTYPE (10041) をセット (※仮にこのエラーが起きたとします)
	//http://support.microsoft.com/kb/819124/ja を参照のこと
	SetLastError(WSAEPROTOTYPE);

	//対応する以下のエラーメッセージを表示
	//ソケットの関数呼び出しでプロトコルが指定されましたが、要求したソケットの種類の形式をサポートしていません。
	GetErrorMessage(GetLastError());

	fprintf(stdout, "\nEnterキーを押下すると次に用意しているtimeSetEventの処理へ進みます。\n");
	getchar();  // Enterキーを押下すると次へ進む(注:押下するまでは進みません)

	//ここから上は GetErrorMessage のテストコード
	//------------------------------------------------------------------------------------
	//ここから下は GetErrorMessage の入れる位置の説明です。

	//MMRESULT timerID;
	//timerID = timeSetEvent(-3, 1, (LPTIMECALLBACK)Send_loop, (DWORD)NULL, TIME_PERIODIC);
	HANDLE hTimerQTimer;                   //もしスコープを外れるようでしたら、staticを付けて static HANDLE hTimerQTimer;  としてあげてください。
	HANDLE hTimerQ = CreateTimerQueue();   //もしスコープを外れるようでしたら、staticを付けて static HANDLE hTimerQTimer;  としてあげてください。
	BOOL ret = CreateTimerQueueTimer(&hTimerQTimer, hTimerQ, Send_loop, NULL, 0, 1000, 0);
	if (!ret)
	{
		//ここで使います。基本的には timeSetEventなどのWindows APIを呼び出した直後です。
		//GetLastError()というのは直前に実行されたWindows APIの終了コードを返します。
		//そのため、他のWindows APIを呼び出すと上書きされてしまうので、
		//必ずWindows APIを呼んだ直後に(エラー処理の中で)使用します。
		GetErrorMessage(GetLastError());

		fprintf(stderr, "タイマー登録に失敗\n");
		fprintf(stdout, "\nもう一度Enterキーを押下するとプログラムを終了します。\n");
		getchar();  // Enterキーを押下で終了
		exit(1);
	}

	fprintf(stdout, "もう一度Enterキーを押下するとプログラムを終了します。\n");
	getchar();  // Enterキーを押下で終了
	//timeKillEvent(timerID);
	ret = DeleteTimerQueueTimer(hTimerQ, hTimerQTimer, NULL);
	if (!ret)
	{
		GetErrorMessage(GetLastError());
		fprintf(stdout, "\nもう一度Enterキーを押下するとプログラムを終了します。\n");
		getchar();  // Enterキーを押下で終了
		exit(1);
	}
	return 0;
}
古いAPI なので、ほんと肝心なことを忘れてしまってました。
申し訳ないです。

Re: 2つの通信プログラム間のエラー

Posted: 2014年9月04日(木) 17:31
by nana
sleepさん,本当にご親切にありがとうございます.
おかげさまでtimeSetEventの問題は解決しました.
次は,送る際のsendto関数が成功せず困っています.

コード:

struct packet{
	unsigned long seq_no;
	unsigned short state;
    double time;
unsigned char color[PIXCEL*COLOR];
	unsigned short CRC;	
};
 int main(){

int send_len ;
send_len= sizeof(packet);
SS(soc, (unsigned char *)&packet, send_len, UDPadd);
}

//関数
int SS(unsigned int soc, unsigned char *sendbuf, unsigned long DataLen,struct sockaddr_in *UDPadd)
{
int send_len;
send_len = sendto(soc,(const char *)sendbuf,DataLen,0,(LPSOCKADDR)UDPadd, sizeof(*UDPadd));
//実行できずNULLを返す
}

Re: 2つの通信プログラム間のエラー

Posted: 2014年9月04日(木) 18:05
by nana
もう一つ聞きたいのですが,
変更後のプログラムで赤線エラーが生じる.
元プログラム

コード:

HANDLE hEvents[1] = { hColorEvent };
変更後

コード:

HANDLE hColorEvent;//グローバル変数定義
HANDLE hEvent[1];//グローバル変数定義

int k;
if(k=0){
hEvent[1] = { hColorEvent };
//ここの { でエラーが生じる. {} を消してみるとコンパイルは通るが警告でメモリコピーのターゲットが小さすぎる.と出てきます.
k++;
}
お願いします.

Re: 2つの通信プログラム間のエラー

Posted: 2014年9月04日(木) 18:22
by みけCAT

コード:

HANDLE hColorEvent;//グローバル変数定義
HANDLE hEvent[1];//グローバル変数定義

int k;
if(k=0){ /* 代入になっています。この条件文は常に偽になるはずです。 */
hEvent[1] = { hColorEvent }; /* 文法的にここの{}は意味がわからないです。{}を外すと、配列の範囲外アクセスになります。 */
//ここの { でエラーが生じる. {} を消してみるとコンパイルは通るが警告でメモリコピーのターゲットが小さすぎる.と出てきます.
k++;
}

Re: 2つの通信プログラム間のエラー

Posted: 2014年9月04日(木) 18:25
by みけCAT

コード:

#include <stdio.h>

int main(void) {
	int a;
	int b[1];
	a = { 123 }; /* C言語ではブロックを値とみなせません */
	b = { 123 }; /* C言語ではこのような配列の代入のしかたはできません */
	b[1] = { 123 }; /* 範囲外アクセスの上、a = { 123 }と同じ問題があります */
	return 0;
}
int型でなくHANDLE型でも同じです。

Re: 2つの通信プログラム間のエラー

Posted: 2014年9月04日(木) 18:31
by みけCAT
sleep さんが書きました:

コード:

fprintf(stderr, (PTCHAR)LocalLock(hLocal));
このfprintfの使い方は危険だと思います。
このような使い方なら、素直にfprintfではなくfputsを使えばいいと思います。
宗教上の理由などにより、どうしてもfprintfを使いたければ、

コード:

fprintf(stderr, "%s", (PTCHAR)LocalLock(hLocal));
とするべきだと思います。

Re: 2つの通信プログラム間のエラー

Posted: 2014年9月04日(木) 18:36
by みけCAT
nana さんが書きました:sleepさん,本当にご親切にありがとうございます.
おかげさまでtimeSetEventの問題は解決しました.
次は,送る際のsendto関数が成功せず困っています.

コード:

struct packet{
	unsigned long seq_no;
	unsigned short state;
    double time;
unsigned char color[PIXCEL*COLOR];
	unsigned short CRC;	
};
 int main(){

int send_len ;
send_len= sizeof(packet);
SS(soc, (unsigned char *)&packet, send_len, UDPadd);
}

//関数
int SS(unsigned int soc, unsigned char *sendbuf, unsigned long DataLen,struct sockaddr_in *UDPadd)
{
int send_len;
send_len = sendto(soc,(const char *)sendbuf,DataLen,0,(LPSOCKADDR)UDPadd, sizeof(*UDPadd));
//実行できずNULLを返す
}
UDPの1パケットで送るには、packet構造体は大きすぎるかもしれません。
320*240の値は153600であり、UDPの1パケットで送ることができる最大サイズの65515をオーバーしています。

Re: 2つの通信プログラム間のエラー

Posted: 2014年9月04日(木) 19:25
by sleep
nanaさん
返信ありがとうございます。
また1つ問題が解決できて良かったです。

コード:

send_len = sendto(soc,(const char *)sendbuf,DataLen,0,(LPSOCKADDR)UDPadd, sizeof(*UDPadd));
//実行できずNULLを返す
}
ちょっとコードがこれだけではまださらっとしか見ていないのもあるのですけど、何とも言えません。
とりあえず、まずは int SS() に渡している struct sockaddr_in UDPadd にどのような値がセットされているか
教えていただいて良いですか?

IPアドレスがもしグローバルIPでしたらそこは伏せておいていただいて大丈夫です。

Re: 2つの通信プログラム間のエラー

Posted: 2014年9月04日(木) 19:28
by sleep
nana さんが書きました: UDPの1パケットで送るには、packet構造体は大きすぎるかもしれません。
320*240の値は153600であり、UDPの1パケットで送ることができる最大サイズの65515をオーバーしています。
あー、確かにそうですね。
4,915,200 byteですものね。

Re: 2つの通信プログラム間のエラー

Posted: 2014年9月04日(木) 19:40
by sleep
nana さんが書きました:

コード:

HANDLE hEvents[1] = { hColorEvent };
変更後

コード:

hEvents[1] = { hColorEvent };
これは2つの問題がありますね。

1つ目は、ケアレスミスのイージーミスですね。
変更後は、hEvents[0] の間違いですね。
代入の初期化リストの文法は合ってます。

2つ目は、Vusial Stadioのバージョンですね。
確か2010でしたよね?
C++11の初期化子リストはまだ対応していなかったのかもしれないですね。

コード:

if(k=0){
if文に関しては、みけCATさんのご指摘どおりですね。

Re: 2つの通信プログラム間のエラー

Posted: 2014年9月04日(木) 20:00
by sleep
みけCATさん、ご指摘ありがとうございます。
みけCAT さんが書きました:
sleep さんが書きました:

コード:

fprintf(stderr, (PTCHAR)LocalLock(hLocal));
このfprintfの使い方は危険だと思います。
このような使い方なら、素直にfprintfではなくfputsを使えばいいと思います。
宗教のことはよく分かりませんが、
nanaさんのfprintf構文のコーディングスタイルに合わせただけなのですが
終端に \0 が確定で入った文字列に fprintfで許されている文法を使用したことに
何か問題がありましたでしょうか?

私は質問者のコーディング規約などまでに修正をかけるような真似はしないので
この手の話は私的には結構どうでも良い話題でスルーさせていただこうかとも考えたのですが
みけCATさんのお考えも聞いておきたくて危険の定義を具体的に何が起きるのか教えていただけると幸いです。

コード:

	char str[] = "hello\n";
	fprintf(stderr, (PTCHAR)str);
	fputs(str, stderr);

	printf("\n\n");

	fprintf(stderr, "%s", (PTCHAR)str);
	fputs(str, stderr);

	printf("\n\n");

	str[6] = 7;
	fprintf(stderr, "%s", (PTCHAR)str);
	fputs(str, stderr);

	printf("\n\n");

	double buff[100];
	fprintf(stderr, "%s", (PTCHAR)buff);
	fputs((PTCHAR)buff, stderr);
他のプログラムでは~、
一般的に~、
と言った雲をつかむような話題でしょうか?

よろしくお願いします。

Re: 2つの通信プログラム間のエラー

Posted: 2014年9月04日(木) 20:17
by みけCAT
sleep さんが書きました:終端に \0 が確定で入った文字列に fprintfで許されている文法を使用したことに
何か問題がありましたでしょうか?

私は質問者のコーディング規約などまでに修正をかけるような真似はしないので
この手の話は私的には結構どうでも良い話題でスルーさせていただこうかとも考えたのですが
みけCATさんのお考えも聞いておきたくて危険の定義を具体的に何が起きるのか教えていただけると幸いです。
一般的に、fprintf(や、他のprintf系の関数)の書式文字列にリテラルでない文字列を渡すと、
%を含む文字列を渡された時に問題が起こる可能性があります。

No: 21のコードを少し改造してみました。

コード:

#pragma comment(lib, "winmm.lib")
#pragma comment(lib, "ws2_32.lib")
#include <winsock2.h>
 
#include <stdio.h>  // もしくは、#include <iostream> でもOK
 
void GetErrorMessage(DWORD dwErrorCode)
{
    HLOCAL hLocal = NULL;
    DWORD systemLocal = MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL);
 
    BOOL bResult = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_ALLOCATE_BUFFER, NULL, dwErrorCode, systemLocal, (PTSTR)&hLocal, 0, NULL);
    if (!bResult) {
        HMODULE hDll = LoadLibraryEx(TEXT("netmsg.dll"), NULL, DONT_RESOLVE_DLL_REFERENCES);
        if (hDll != NULL) {
            bResult = FormatMessage(FORMAT_MESSAGE_FROM_HMODULE | FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_ALLOCATE_BUFFER, hDll, dwErrorCode, systemLocal, (PTSTR)&hLocal, 0, NULL);
            FreeLibrary(hDll);
        }
    }
 
    if (bResult && (hLocal != NULL)) {
        fputs("fprintf: ", stderr);
        fprintf(stderr, (PTCHAR)LocalLock(hLocal));
        fputs("\nfputs: ", stderr);
        fputs((PTCHAR)LocalLock(hLocal), stderr);
        LocalFree(hLocal);
    }
    else {
        fprintf(stderr, TEXT("No text found for this error code"));
    }
}
 
void CALLBACK Send_loop(UINT uTimerID, UINT uMsg, DWORD dwUser, DWORD dw1, DWORD dw2) {
    fprintf(stdout, "送信しました。\n");
}
 
int main() {
    //例えば、STG_E_FILENOTFOUND をセット (※仮にこのエラーが起きたとします)
    SetLastError(STG_E_FILENOTFOUND);
 
    //対応するエラーメッセージを表示
    GetErrorMessage(GetLastError());
 
    fprintf(stdout, "\nEnterキーを押下すると次に用意しているtimeSetEventの処理へ進みます。\n");
    getchar();  // Enterキーを押下すると次へ進む(注:押下するまでは進みません)
 
    MMRESULT timerID;
    timerID = timeSetEvent(1000, 1, (LPTIMECALLBACK)Send_loop, (DWORD)NULL, TIME_PERIODIC);
    if (!timerID)
    {
        //ここで使います。基本的には timeSetEventなどのWindows APIを呼び出した直後です。
        //GetLastError()というのは直前に実行されたWindows APIの終了コードを返します。
        //そのため、他のWindows APIを呼び出すと上書きされてしまうので、
        //必ずWindows APIを呼んだ直後に(エラー処理の中で)使用します。
        GetErrorMessage(GetLastError());
 
        fprintf(stderr, "タイマー登録に失敗\n");
        getchar();  // Enterキーを押下で終了
        exit(1);
    }
 
    fprintf(stdout, "もう一度Enterキーを押下するとプログラムを終了します。\n");
    getchar();  // Enterキーを押下で終了
    timeKillEvent(timerID);
    return 0;
}

Re: 2つの通信プログラム間のエラー

Posted: 2014年9月04日(木) 20:29
by sleep
みけCATさん
返信ありがとうございます。
みけCAT さんが書きました: 一般的に、fprintf(や、他のprintf系の関数)の書式文字列にリテラルでない文字列を渡すと、
%を含む文字列を渡された時に問題が起こる可能性があります。
お考えを聞かせていただきありがとうございます。

質問させてください。
リテラルの場合でも % が含まれていると問題ありませんか?

コード:

fprintf(stdout, "abc%12e");
よろしくお願いします。

Re: 2つの通信プログラム間のエラー

Posted: 2014年9月04日(木) 21:42
by みけCAT
sleep さんが書きました:質問させてください。
リテラルの場合でも % が含まれていると問題ありませんか?

コード:

fprintf(stdout, "abc%12e");
よろしくお願いします。
不適切な%の使用は問題あります。この例では%が不適切に使用されており、ダメです。(警告も出ます)
この場合は、

コード:

fprintf(stdout, "abc%%12e");
とすれば"abc%12e"(引用符は含まない)と出力されるはずです。

Re: 2つの通信プログラム間のエラー

Posted: 2014年9月04日(木) 22:04
by sleep
この手の話題本当に苦手です。
スレッド主に迷惑ですし、本当に振らないでいただきたかった。
他のスレッドでやっていただきたかったです。本当に。

最初に掲示しているGetErrorMessageのコードが
・#include <string>
・Getmessage の戻り値は string型
・coutで data()、c_str()を使用せず直接string型の変数を渡して出力している
を見た時点で相手が理解していることを認識していただきたかったです。

コード:

fprintf(stdout, "abc%12e");
は、正直どうとでも対応できますよね。

コード:

fprintf(stdout, "%s", "abc%12e");
fputs("abc%12e", stdout);
fprintf(stdout, "abc%%12e");
「どう対応するか」は分かってます。
認識の間違いに対する指摘なのですが、それが伝わらなかったようですね。

それが認識いただけないのであれば
ここは、私のC言語教室ではなく、
nanaさんの「2つの通信プログラム間のエラー」に関する質問スレッドなので他でやっていただいて
このスレッドでは、この辺で切り上げさせていただけると幸いです。

Re: 2つの通信プログラム間のエラー

Posted: 2014年9月04日(木) 23:56
by ISLe()
printf("%s");
を実行したらどこから文字列が読み込まれるんだろう
という話ですね。

これを見逃すプログラマの作ったプログラムは安心して実行できませんね。

Re: 2つの通信プログラム間のエラー

Posted: 2014年9月05日(金) 14:16
by nana

コード:

HANDLE hEvents[0] = { hColorEvent };
上の文では定義ができるのですが,

コード:

HANDLE hEvents[0];
hEvents[0] = { hColorEvent };
グローバル変数で定義することはできないということですか?
{}になにか問題があるのでしょうか?

Re: 2つの通信プログラム間のエラー

Posted: 2014年9月05日(金) 14:16
by nana
新たなエラーです.

コード:


● _endthreadex(0);//ウインドウズエラー.ヒープが壊れていることが原因として考えられます。

seq_no_Recv = (unsigned long *)calloc(seq,sizeof(unsigned long));

● free(seq_no_Recv);//ウインドウズエラー.ヒープが壊れていることが原因として考えられます。

●のところでエラーが出てきます.

Re: 2つの通信プログラム間のエラー

Posted: 2014年9月05日(金) 14:21
by nana
sleep さんが書きました:nanaさん
返信ありがとうございます。
また1つ問題が解決できて良かったです。

コード:

send_len = sendto(soc,(const char *)sendbuf,DataLen,0,(LPSOCKADDR)UDPadd, sizeof(*UDPadd));
//実行できずNULLを返す
}
ちょっとコードがこれだけではまださらっとしか見ていないのもあるのですけど、何とも言えません。
とりあえず、まずは int SS() に渡している struct sockaddr_in UDPadd にどのような値がセットされているか
教えていただいて良いですか?

IPアドレスがもしグローバルIPでしたらそこは伏せておいていただいて大丈夫です。
struct sockaddr_in UDPadd の中は

コード:

typedef struct sockaddr_in {

#if(_WIN32_WINNT < 0x0600)
    short   sin_family;    
#else //(_WIN32_WINNT < 0x0600)
    ADDRESS_FAMILY sin_family;
#endif //(_WIN32_WINNT < 0x0600)

    USHORT sin_port;
    IN_ADDR sin_addr;
    CHAR sin_zero[8];
} SOCKADDR_IN, *PSOCKADDR_IN;
です.お願いします

Re: 2つの通信プログラム間のエラー

Posted: 2014年9月05日(金) 15:11
by sleep
nana さんが書きました: グローバル変数で定義することはできないということですか?
{}になにか問題があるのでしょうか?
グローバル変数で定義できます。
{} は特に問題ありませんが、C++11では {} による代入は特別な意味を持ちます。
それまでのC++とは異なる動きで定義されています。
C++11の{}が使用可能な環境であれば大丈夫ですが
= にエラーが出るのでしたら、nanaさんの環境(Visual Studio 2010)では
まだC++11の {}は未対応である可能性があります。

{}を特に使用しなくても、以下のコードのように
hEvent[0] = hColorEvent;
で代入できます。
むしろ、こちらが昔からのスタンダードな代入の文法となります。

コード:

#pragma comment(lib, "ws2_32.lib")
#include <winsock2.h>

HANDLE hColorEvent;
HANDLE hEvent[1];

int main() {
	hColorEvent = NULL;
	hEvent[0] = hColorEvent;
	hEvent[0] = { hColorEvent };

	return 0;
}
違いは
変更前は、配列の初期化を表す文法です。

コード:

HANDLE hEvents[1] = { hColorEvent };
変更後は、配列への値の代入を表す文法です。
配列の宣言後の = は、通常代入の処理にて値を格納することになります。

コード:

hEvent[0] = hColorEvent;
hEvent[0] = { hColorEvent };
それが 変更前と変更後での文法の違いです。

Re: 2つの通信プログラム間のエラー

Posted: 2014年9月05日(金) 15:23
by sleep
nana さんが書きました: struct sockaddr_in UDPadd の中は

コード:

typedef struct sockaddr_in {

#if(_WIN32_WINNT < 0x0600)
    short   sin_family;    
#else //(_WIN32_WINNT < 0x0600)
    ADDRESS_FAMILY sin_family;
#endif //(_WIN32_WINNT < 0x0600)

    USHORT sin_port;
    IN_ADDR sin_addr;
    CHAR sin_zero[8];
} SOCKADDR_IN, *PSOCKADDR_IN;
です.お願いします
あー・・、私がstructと付けてしまったばかりに
構造体の定義を載せてくださったのですね。ごめんなさい。

コード:

sockaddr_in UDPadd;
UDPadd.sin_family = AF_INET;
//UDPadd.sin_addr.s_addr = inet_addr("192.168.0.2");
inet_pton(AF_INET, "192.168.0.2", &UDPadd.sin_addr.s_addr);
UDPadd.sin_port = htons(8888);
お願いしたのは設定された値の方でした。
ただ、nanaさんがおっしゃるように
nana さんが書きました: UDPの1パケットで送るには、packet構造体は大きすぎるかもしれません。
320*240の値は153600であり、UDPの1パケットで送ることができる最大サイズの65515をオーバーしています。
現状はとりあえずこちらが原因のようですね。

Re: 2つの通信プログラム間のエラー

Posted: 2014年9月05日(金) 15:36
by sleep
nana さんが書きました: 新たなエラーです.

コード:


● _endthreadex(0);//ウインドウズエラー.ヒープが壊れていることが原因として考えられます。

seq_no_Recv = (unsigned long *)calloc(seq,sizeof(unsigned long));

● free(seq_no_Recv);//ウインドウズエラー.ヒープが壊れていることが原因として考えられます。

●のところでエラーが出てきます.
WindowsAPIを呼び出さなければエラーコードは上書きされないので
おそらく、callocの方は問題ないと思われます。

コード:

#pragma comment(lib, "ws2_32.lib")
#include <winsock2.h>

#define seq 10000

int main() {
	unsigned long *seq_no_Recv = (unsigned long *)calloc(seq, sizeof(unsigned long));
	free(seq_no_Recv);

	return 0;
}
しかし、それまでの間に何かが起きているということみたいですね。
そこまでの間にWindowsAPIを呼び出してエラーが発生している箇所はないですか?

Re: 2つの通信プログラム間のエラー

Posted: 2014年9月05日(金) 15:43
by sleep
free関数の中で、HeapFreeが呼ばれるので
malloc系は全て HeapAlloc系の関数でメモリ確保が行われるんですが・・・

nanaさん
Windowsが返してきたエラーって
STATUS_NO_MEMORY (0xC0000017L)

STATUS_ACCESS_VIOLATION (0xC0000005L)
のどちらを指してるか分かりますか?

STATUS_NO_MEMORYだったら、メモリ不足の可能性がありますね。

Re: 2つの通信プログラム間のエラー

Posted: 2014年9月05日(金) 16:27
by nana
sleep さんが書きました:free関数の中で、HeapFreeが呼ばれるので
malloc系は全て HeapAlloc系の関数でメモリ確保が行われるんですが・・・

nanaさん
Windowsが返してきたエラーって
STATUS_NO_MEMORY (0xC0000017L)

STATUS_ACCESS_VIOLATION (0xC0000005L)
のどちらを指してるか分かりますか?

STATUS_NO_MEMORYだったら、メモリ不足の可能性がありますね。
ヒープが壊れていることが原因として考えられます。としか出てきませんでした.

Re: 2つの通信プログラム間のエラー

Posted: 2014年9月05日(金) 16:44
by sleep
nana さんが書きました: ヒープが壊れていることが原因として考えられます。としか出てきませんでした.
あー・・、構造化例外なんて使わないですよね。ごめんなさい。
以下のコードの隙間にコピペして実行していただきたいコードがあるんですけど

コード:

● _endthreadex(0);//ウインドウズエラー.ヒープが壊れていることが原因として考えられます。
 
seq_no_Recv = (unsigned long *)calloc(seq,sizeof(unsigned long));
 
● free(seq_no_Recv);//ウインドウズエラー.ヒープが壊れていることが原因として考えられます。
下記の点線のとこのやつですね。

コード:

● _endthreadex(0);//ウインドウズエラー.ヒープが壊れていることが原因として考えられます。


//----------------------------------------------------------------------------------------------------------------
char *buff = NULL;
HANDLE hHeap = HeapCreate(HEAP_GENERATE_EXCEPTIONS, 64 * 1024, 64 * 1024);
__try
{
	__try
	{
		buff = (char*)HeapAlloc(hHeap, HEAP_ZERO_MEMORY | HEAP_GENERATE_EXCEPTIONS, sizeof(char) * 1024);
	}
	__except (EXCEPTION_EXECUTE_HANDLER)
	{
		unsigned long error_code = GetExceptionCode();
		if (error_code == STATUS_NO_MEMORY) fprintf(stderr, "Exception: STATUS_NO_MEMORY\n");
		if (error_code == STATUS_ACCESS_VIOLATION) fprintf(stderr, "Exception: STATUS_NO_MEMORY\n");
	}
}
__finally
{
	HeapFree(hHeap, NULL, buff);
	HeapDestroy(hHeap);
}
//----------------------------------------------------------------------------------------------------------------

 
seq_no_Recv = (unsigned long *)calloc(seq,sizeof(unsigned long));
 
● free(seq_no_Recv);//ウインドウズエラー.ヒープが壊れていることが原因として考えられます。
何が表示されるか見ていただけますか?
よろしくお願いします。

Re: 2つの通信プログラム間のエラー

Posted: 2014年9月05日(金) 16:46
by sleep
あー・・・、ひょっとしたら HeapCreate で既に出てしまうかもしれないですね。
とりあえず一回見てみましょう。
お手数ですが確認お願いします。

Re: 2つの通信プログラム間のエラー

Posted: 2014年9月05日(金) 16:58
by sleep
私の不手際で、両方とも STATUS_NO_MEMORY と書いてしまってました。
申し訳ないです。
下記にもう一度コピペし直して、実行をお願いします。

コード:

//----------------------------------------------------------------------------------------------------------------
char *buff = NULL;
HANDLE hHeap = HeapCreate(HEAP_GENERATE_EXCEPTIONS, 64 * 1024, 64 * 1024);
__try
{
	__try
	{
		buff = (char*)HeapAlloc(hHeap, HEAP_ZERO_MEMORY | HEAP_GENERATE_EXCEPTIONS, sizeof(char) * 1024);
	}
	__except (EXCEPTION_EXECUTE_HANDLER)
	{
		unsigned long error_code = GetExceptionCode();
		if (error_code == STATUS_NO_MEMORY) fprintf(stderr, "Exception: STATUS_NO_MEMORY\n");
		if (error_code == STATUS_ACCESS_VIOLATION) fprintf(stderr, "Exception: STATUS_ACCESS_VIOLATION\n");
	}
}
__finally
{
	HeapFree(hHeap, NULL, buff);
	HeapDestroy(hHeap);
}
//----------------------------------------------------------------------------------------------------------------


Re: 2つの通信プログラム間のエラー

Posted: 2014年9月08日(月) 08:40
by nana
sleepさん,遅くなり申し訳ありません.

頂いたプログラムを実行したところ,以下のように出力されました.


HEAP[UDP.exe]: Invalid address specified to RtlValidateHeap( 00290000, 0029F9B0 )
Windows によって UDP.exe でブレークポイントが発生しました。

ヒープが壊れていることが原因として考えられます。UDP.exe または読み込まれた DLL にバグがあります。

あるいは、UDP.exe がフォーカスを持っているときに、ユーザーが F12 キーを押したことが原因として考えられます。

可能であれば、出力ウィンドウに詳細な診断情報が表示されます。

Re: 2つの通信プログラム間のエラー

Posted: 2014年9月08日(月) 08:47
by nana
書き忘れていました.timesetevent を実行するために
seqを10に変更しました.すみません.

更に,
free(seq_no_Recv);のみでエラーする様になりました.

あと送信する際,パケットを分割して送信するやり方を教えて下さい.

画像データは640*480でした.間違えてすみません.

Re: 2つの通信プログラム間のエラー

Posted: 2014年9月08日(月) 12:47
by sleep
nana さんが書きました:sleepさん,遅くなり申し訳ありません.

頂いたプログラムを実行したところ,以下のように出力されました.


HEAP[UDP.exe]: Invalid address specified to RtlValidateHeap( 00290000, 0029F9B0 )
Windows によって UDP.exe でブレークポイントが発生しました。

ヒープが壊れていることが原因として考えられます。UDP.exe または読み込まれた DLL にバグがあります。

あるいは、UDP.exe がフォーカスを持っているときに、ユーザーが F12 キーを押したことが原因として考えられます。

可能であれば、出力ウィンドウに詳細な診断情報が表示されます。
これが出るときは、いくつか原因が考えられます。

①DLL境界を超えたポインタ、ハンドルの操作
このエラーが出るときは、DLL境界を越えてハンドルやポインタの受け渡しをして、それを操作しているときですね。
または、(こちらは私は遭遇したことがないのですが)使用されているDLLとnanaさんとで違う標準Cライブラリなどを使ってると出るようです。
http://support.microsoft.com/kb/190799/ja

②標準ライブラリ関数の使用のされ方
以下のサイトを観てみてください。
http://detail.chiebukuro.yahoo.co.jp/qa ... 1451760279
ここでは回答者が「memcpyによって問題が引き起こされる」という例を挙げています。
もう1つ、以下のサイトも観てみてください。
http://d.hatena.ne.jp/kokatsu/20120416/1334589648
mallocで確保した領域を初期化せずにstrcatしていたことが原因で同様のエラーとなっています。
「ヒープが壊れていることが原因として考えられます。」という問題は
標準ライブラリ関数を使用しただけでも発生するということです。

何でも構いません。どこかメモリを使った操作をしているところに心当たりがありませんか?
一端、追加していただいた私の構造化例外コードを除去していただいて
「ヒープが壊れていることが原因として考えられます。」という問題が
ウィンドウズのエラーがどの時点から発生しているのか確認してみてください。

Re: 2つの通信プログラム間のエラー

Posted: 2014年9月08日(月) 13:25
by sleep
nana さんが書きました: 書き忘れていました.timesetevent を実行するために
seqを10に変更しました.すみません.
それは全然大丈夫です。
むしろ逆に、いきなり全部を1度に作るのではなくて
まずは1画像送受信できるところから作っていった方が
nanaさん的にも複数の問題を1度に抱えずに済むと思われます。
nana さんが書きました: 更に,
free(seq_no_Recv);のみでエラーする様になりました.
「ヒープが壊れていることが原因として考えられます。」 というやつでしょうか?
前の返信で書いているとおり、いくつかの原因があるので情報を参考にして
コードを確認してみてください。
nana さんが書きました: あと送信する際,パケットを分割して送信するやり方を教えて下さい.

画像データは640*480でした.間違えてすみません.
送信するデータを分割するのは nanaさんが前にアップしてくださったコード断片を元にすると
データの送信開始位置をずらしながら、送信可能なサイズずつ送信することになります。

コード:

struct packet{
	unsigned long seq_no;
	unsigned short state;
	double time;
	unsigned char color[PIXCEL*COLOR];
	unsigned short CRC;
};
int main(){

	packet data = //画像データが入っているとする

	int send_len;
	send_len = sizeof(packet);

	unsigned char *p = (unsigned char *)&data;
	int split_send_len = 50000;
	for (int offset = 0; offset < send_len; offset += split_send_len)
	{
		if ((send_len - offset) < split_send_len)
		{
			//split_send_len以下のデータサイズで送信する場合
			SS(soc, p + offset, send_len - offset, UDPadd);
		}
		//split_send_lenのデータサイズで送信する場合
		SS(soc, p + offset, split_send_len, UDPadd);
	}
}

//関数
int SS(unsigned int soc, unsigned char *sendbuf, unsigned long DataLen, struct sockaddr_in *UDPadd)
{
	int send_len;
	send_len = sendto(soc, (const char *)sendbuf, DataLen, 0, (LPSOCKADDR)UDPadd, sizeof(*UDPadd));
	//実行できずNULLを返す
}
分割して送信することは可能ですが、udpでそれを行う場合いくつか問題があります。
一番やっかいなのは、データを分けて送った場合 tcpと違い順序制御なんて無いので
自分でデータを再構築しなければなりません。
あと、データが届かなくても再送信もされませんし、届かなかったことも通知されませんので
データに欠落が生まれてたかどうかも確認および対応は自分のプログラムで自力でやらなければならなくなります。

Re: 2つの通信プログラム間のエラー

Posted: 2014年9月08日(月) 13:46
by sleep
これはひどい。elseがないですね・・・・
elseが必要でした。

コード:

        if ((send_len - offset) < split_send_len)
        {
            //split_send_len以下のデータサイズで送信する場合
            SS(soc, p + offset, send_len - offset, UDPadd);
        }
        else
        {
            //split_send_lenのデータサイズで送信する場合
            SS(soc, p + offset, split_send_len, UDPadd);
        }