LPBYTE 配列が空かどうか確認する方法 – プログラミング – Home

LPBYTE 配列が空かどうか確認する...
 
通知
すべてクリア

[解決済] LPBYTE 配列が空かどうか確認する方法

固定ページ 1 / 2

なおぞう
 なおぞう
(@なおぞう)
ゲスト
結合: 9年前
投稿: 143
Topic starter  

お世話になります。
VS2013 標準Windowsライブラリを使用、Unicode文字セットを使用、共通言語ランタイム
サポートをしない の環境で開発しております。

出力データ(バイナリコード)として、LPBYTE 型の配列が引数として渡されてくるのです
が、その配列が引数として不正で無いかチェックする必要があります。

配列の1文字目がNULL(空?)だったら不正引数としようと考えましたが、(引数チェッ
クとしてこの考えも良くないというようでしたらご指摘いただけると嬉しいです)コード
を書いても期待する結果(空だよ)が返ってきません。

以下のテストコードを書いてみました。

BYTE ch[] = 0232421312;
LPBYTE x = ch;
memset(ch, '\0', sizeof(ch));

//xが空かどうかの判定
if ((!x)) printf(ERROR \n);

if (&x[0] == NULL) printf(ERROR \n);

if (&x[0] == '\0') printf(ERROR \n);

if (x == '\0') printf(ERROR \n);
if (x == NULL) printf(ERROR \n);

記述したものはすべてスルーしてしまいました…。

根本的に間違えているのかもしれませんが、それ自体が分かりません。
すみませんが、教えていただけますようお願いします。


引用未解決
トピックタグ
tetrapod
 tetrapod
(@tetrapod)
ゲスト
結合: 21年前
投稿: 830
 

「空」という用語に何を期待しているのかがわからないのでアドバイスしようが無い。
そもそも BYTE は「文字」でない。

0文字の char 相当のチェックであるなら
if (ch[0]=='\0') とか
if (x[0]=='\0') とか。
これが期待した「空」であるかどうかは要件次第。


返信引用
瀬戸っぷ
 瀬戸っぷ
(@瀬戸っぷ)
ゲスト
結合: 18年前
投稿: 178
 

>if ((!x)) printf(ERROR \n);

xがNULLだった場合に真になる。
>LPBYTE x = ch;
なので、xにはchのアドレスが入っているのでNULLにはならない。

>if (&x[0] == NULL) printf(ERROR \n);

変数xのアドレスがNULLだった場合に真になる。
変数割り当てがあった時点でアドレスNULLはあり得ない。

>if (&x[0] == '\0') printf(ERROR \n);

変数xのアドレスが'\0'だった場合に真になる。
1つ上と同上。

>if (x == '\0') printf(ERROR \n);

xが'\0'だった場合に真になる。
最初の同じ。

>if (x == NULL) printf(ERROR \n);

xがNULLだった場合に真になる。
最初の同じ。

>配列の1文字目がNULL

配列の1文字目が'\0'だったら…ですよね?
一応、'\0'とNULLは区別した方がいいと思いますが。
# というかNULLポインタと言うべき?

if (*(x[0]) == '\0') printf(ERROR \n);
でいいんじゃないですかね?


返信引用
瀬戸っぷ
 瀬戸っぷ
(@瀬戸っぷ)
ゲスト
結合: 18年前
投稿: 178
 

あれ?間違ったか?
微妙に理解が怪しいかも知れん。
# あんまし考えないで回答はいかんな。


返信引用
なおぞう
 なおぞう
(@なおぞう)
ゲスト
結合: 9年前
投稿: 143
Topic starter  

回答ありがとうございます。

>tetrapod様
データの入っているはずのLPBYEに、ちゃんとデータが入っているか確認したいというこ
となので、1バイト目にデータが無ければエラーという考えに至りました。

>瀬戸っぷ様
丁寧な説明ありがとうございます。

if (x[0]== '\0') printf(ERROR \n);
で、エラーが出力されました。
なぜ、このパターンを自分で書かなかったのか…。

ポインタって難しいですね。

ありがとうございました。


返信引用
AR2
 AR2
(@ar2)
Estimable Member
結合: 5年前
投稿: 110
 

 解決しちゃったようですが、せっかく書いたので

 文字とBYTEを混同しちゃってるのは、この辺りから推測できるわけでして
BYTE ch[] = 0232421312;
 また、この質問のボタンの掛け違いの本質もここだと思います。

 この部分を、こんな風に書き換えれば、多少なりとも理解が進むと思います。
char *szbuff = new char[20];
StrCpyA(szbuff, 0232421312);
LPBYTE lpch = (LPBYTE)szbuff;

 なんとなくVARIANT型の戻り値を展開しようとしてるんじゃないかと予想しています
が・・・その場合だとVariantInit()を調べると良いでしょう。


返信引用
aetos
(@aetos)
Noble Member
結合: 5年前
投稿: 1480
 

そもそもデータが文字列なのかバイナリデータなのかをはっきりすべきですね。
文字列なら char なり wchar_t なり(もしくはそのポインター)で扱うべきだし、LPBYT
E ならバイナリデータとして扱うべきです。

C/C++ では一般に文字列の終端を '\0' で表しますから、「有効な文字列がなくても '\0
' だけは必ずある」ことが保証されているならば、
ch[0] == '\0'
でよいでしょう。

同様に、バイナリデータの場合であっても、アプリケーションの仕様によって、「有効な
データがない場合でも、必ず 1 バイトの 0 は保証される」という約束があるならば、
ch[0] == 0
でよいでしょう。

ただし、文字列と違ってバイナリデータの場合、「データがない」というのは「データの
長さがゼロ」というのを指す方が一般的だと思います。
その場合、
ch[0]
は不正なアクセスになり得ます。

データの長さがゼロという事態が想定できるのであれば、LPBYTE というポインターだけ
から、その長さを知ることはできませんから、別途長さを表すパラメーターを受け取る必
要があります。


返信引用
仲澤@失業者
(@uncle_kei)
Prominent Member
結合: 5年前
投稿: 828
 

もう結論が出ているようなので、別の注意点。

まぁ渡されるのが LPBYTE( = unsgined char *) であると明記されているので
間違いはしないと思いますが、「Unicode」でコンパイルしているとも
書いてあったのでで少し気になりました。

あたりまえですが、もしUnicodeテキストのやりとりについて、検討しているのなら、
そもそも LPBYTE や、chr * などでやり取りしてはいけません。
wchar_t や WCHAR を使用します。

wchar_t ch[] = L0232421312;
WCHAR * x = ch;

てな感じ。


返信引用
なおぞう
 なおぞう
(@なおぞう)
ゲスト
結合: 9年前
投稿: 143
Topic starter  

>皆様
解決後の書き込みありがとうございます。勉強になります。(とはいえ、理解が追い付か
ない現状ですが)

引数で受け取るLPBYTEはImageのデータのポインタなので、バイナリデータです。

>ただし、文字列と違ってバイナリデータの場合、「データがない」というのは「データの
>長さがゼロ」というのを指す方が一般的だと思います。

最初、データの長さで確認しようとしたのですが、
LPBYTE …unsigned char の長さをとる方法がみつけられなかったのです。


返信引用
tetrapod
 tetrapod
(@tetrapod)
ゲスト
結合: 21年前
投稿: 830
 

例えばバイナリファイルを読むことを考える。

#define BUFSIZE 1024
BYTE buf[BUFSIZE];
size_t len=fread(buf, 1, BUFSIZE, f);

としたのであれば「空である」とは len==0 のことだ。バイナリファイルの中身として
0x00 ('\0') は普通にありうる話だから buf を見ても判別不能。

> Image のデータのポインタ
の他にサイズを得るための引数、ないしは返却値があったりしないかい?


返信引用
なおぞう
 なおぞう
(@なおぞう)
ゲスト
結合: 9年前
投稿: 143
Topic starter  

>tetrapod様

引数として渡されるのは、コールバック関数のポインタと、 LPBYTE (imageデータ) だ
けとなっています。戻り値は、関数内で発生したエラーIDになります。

この二つの引数が不正で無いことを確認しなくてはならないのです。
コールバック関数の不正チェックも、 if(PFUNC == NULL) return err; って考えてし
まっています…。


返信引用
tetrapod
 tetrapod
(@tetrapod)
ゲスト
結合: 21年前
投稿: 830
 

今作ろうとしているのは image を作る側なんだよね。
ということは呼び出し側が渡してくる BYTE* には何も入っていないのが普通だろう。
「空」であることが当たり前なのではないかい?

呼び出し側の典型的コード
BYTE* buf=malloc(BUFSIZE); // 中身は無い
imagebuilderfunc(buf, callback); // 無いまま渡してくる

真にやりたいことは「空チェック」などではないに1票。
では真にやりたいことが何なのかは読者にはわからないことなので、
自分でもう一度整理してもらいたい。

> LPBYTE (imageデータ) だけ
それはダメ設計だ。

char buf[1];
strcpy(buf, abc);
はメモリ破壊(バッファオーバーラン脆弱性)を起こしているわけだ。
今の設計(サイズ指定なし)だと、これと同じことが起こる。しかも回避策がない。
strncpy() のようにサイズ指定があれば回避できるので、
今のうちに仕様変更を提案しておくといい。

> コールバック関数の不正チェックも、 if(PFUNC == NULL) return err; って
これは正しいだろう。でもオイラなら assert() で実装するよ。

C/C++ にはポインタの妥当性を調べる方法は提供されていないので、
呼び出される側でチェックできるとしたら nullptr くらいしかないよ。
呼ぶ側の責任で正しく呼ぶ以外に方法はない。

BYTE* p=malloc(100); // メモリ確保
free(p); // メモリ処分するが、ごみになったポインタ値は p に残ったまま
fread(p, 1, 100, f); // ダングリングポインタ使用バグ
fread 側にてチェックできる内容は実際問題として無い。


返信引用
なおぞう
 なおぞう
(@なおぞう)
ゲスト
結合: 9年前
投稿: 143
Topic starter  

>tetrapod様

>今作ろうとしているのは image を作る側なんだよね。

いえ。
LPBYTE型のImageを引数でもらって、それをさらに次のDLLの関数に他の引数と一緒に渡す
だけという橋渡しの関数を作っています。なので、受け取ったImageが空だったらエラー
という判断をしたいのです。

LPBYTEのデータが不正かどうかなんてどうやって判断したら良いのか分からないので、質
問させていただきました。

>これは正しいだろう。でもオイラなら assert() で実装するよ。

間違いでないようで良かったです。
assertですか。…使った事ないです。今後利用したいと思います。
提案ありがとうございます。


返信引用
tetrapod
 tetrapod
(@tetrapod)
ゲスト
結合: 21年前
投稿: 830
 

うーんさっぱりわからん。
とりあえず既に書いた通り、呼ばれる側でできることはほとんど無い。

1.ポインタの値の妥当性を調査するすべはない (nullptr かどうかくらい)
2.ポインタの指す先に使用可能なメモリがあるかを調査するすべはない
3.バッファサイズを渡さない設計はただのバグ。

直すべきところは仕様のレベルで直そう。
できないことはきっぱりできないと言って断ろう。


返信引用
ITO
 ITO
(@ITO)
ゲスト
結合: 22年前
投稿: 1235
 

>LPBYTE型のImageを引数でもらって、それをさらに次のDLLの関数に他の引数と一緒に
>渡すだけという橋渡しの関数を作っています。なので、受け取ったImageが空だったら
>エラーという判断をしたいのです。

ただ、データをもらって判断する。= 無理です。

正しいデータかどうかの識別の型が必要ですね。
まず、
  1. imageデータの種類は?
jepg? BMP? png? gif? ......

2. imageデータの固有情報(タイトル等)を入れてもらう。
  3. 1,2をもとにデータのヘッダー情報からタイトル、ファイル容量を調べる。
  4. タイトルが正しくなければそのデータは捨てる。
5. 得られたファイル情報をもとに、データを取得する。
6. データを渡す。

ですね。


返信引用
固定ページ 1 / 2

返信する

投稿者名

投稿者メールアドレス

タイトル *

プレビュー 0リビジョン 保存しました
共有:
タイトルとURLをコピーしました