マルチバイトの変換後出力がNULL

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
ぷぷぷジューシー
記事: 22
登録日時: 3ヶ月前
住所: アンドロメダ銀河系のどこかに住んでいる

マルチバイトの変換後出力がNULL

#1

投稿記事 by ぷぷぷジューシー » 2ヶ月前

コード:

int geturlparserfunc(const char* name,   char* rhost, char* rpath)
{
  int bmfunc_rlen = 0;
  int  inputlen = strlen(name)+1;
  char32_t inp32b[50];
  int arraycount1 = 0, arraycount2 = 0;
  mbstate_t mbstate = 0;
  char temphost[MB_LEN_MAX+1];
  char temppath[MB_LEN_MAX+1];

  int  while_n = 0;
  int slashconunt = 0, colon = 0;
  int rpathpp = 0, rhostpp = 0;

  rhost = '\0', rpath = '\0';

  while (1){
    bmfunc_rlen = mbrtoc32(&inp32b[arraycount1], &name[arraycount2], MB_LEN_MAX, &mbstate);
    if ( -1== bmfunc_rlen ){
      printf("エラーが発生しました\n");
      printf("エンコードエラー又はバイト数が足りませんの可能性があります。");
      printf("エラー size_t サイズ : %zu\n", bmfunc_rlen);
      break;
    } else if ( -2 == bmfunc_rlen ){
      printf("エラーが発生しました\n");
      printf("マルチバイト文字の可能性があります。");
      printf("エラー size_t サイズ : %zu\n", bmfunc_rlen);
      break;
    } else if ( -3 == bmfunc_rlen ){
      arraycount1 += 1;
      continue;
    }  else if (0 == bmfunc_rlen ){
      break;
    } else if ( 0 < bmfunc_rlen ){
    	arraycount1 += 1;
      arraycount2 += bmfunc_rlen;
    } 
  }

  while (arraycount1 > while_n){
    while_n += 1;
    if (':' == inp32b[while_n] || '/' == inp32b[while_n]){
      if ( ':' == inp32b[while_n]){
        colon = 1;
      }
      if ('/' == inp32b[while_n]){
        slashconunt+=1;
      }
    }

    // rpath
    if ( 3 < slashconunt && 1 == colon) {
      bmfunc_rlen = c32rtomb(temppath ,inp32b[while_n], &mbstate);
      if (-1 == bmfunc_rlen){
        printf("エラーが発生しました\n");
        printf("有効なワイド文字ではありません\n");
        printf("エラー size_t サイズ : %zu\n", bmfunc_rlen);
        break;
      }
      rpath = malloc(bmfunc_rlen);
      sprintf(rpath, "%s", temppath);
      
    }
    // rhost
    if ( 2 == slashconunt && 1 == colon){
      bmfunc_rlen = c32rtomb(temphost ,inp32b[while_n], &mbstate);
      if ((size_t)(-1) == bmfunc_rlen){
        printf("エラーが発生しました\n");
        printf("有効なワイド文字ではありません\n");
        printf("エラー size_t サイズ : %zu\n", bmfunc_rlen);
        break;
      }
      rhost = malloc(bmfunc_rlen);
      sprintf(rhost, "%s", temphost);
    }
  }
  printf("%s\n", rpath);

  arraycount1 = 0, arraycount2 = 0, slashconunt = 0, colon = 0 , bmfunc_rlen = 0;

}


面倒なことはCGo使おう!

アバター
みけCAT
記事: 6432
登録日時: 10年前
住所: 千葉県
連絡を取る:

Re: マルチバイトの変換後出力がNULL

#2

投稿記事 by みけCAT » 2ヶ月前

ぷぷぷジューシー さんが書きました:
2ヶ月前

コード:

  rhost = '\0', rpath = '\0';
ここでポインタに0を代入しています。
0をポインタに変換するとNULLになります。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

ぷぷぷジューシー
記事: 22
登録日時: 3ヶ月前
住所: アンドロメダ銀河系のどこかに住んでいる

Re: マルチバイトの変換後出力がNULL

#3

投稿記事 by ぷぷぷジューシー » 2ヶ月前

コード:

  rhost = '\0', rpath = '\0';
のコードを消したましたが結果が変わりません
面倒なことはCGo使おう!

アバター
みけCAT
記事: 6432
登録日時: 10年前
住所: 千葉県
連絡を取る:

Re: マルチバイトの変換後出力がNULL

#4

投稿記事 by みけCAT » 2ヶ月前

最初から引数にNULLを与え、それを書き換えなければ、NULLのままになるでしょう。
例えば、第一引数を

コード:

"http://example.com/hoge"
とした場合、rpathへの代入は行われません。
どうして geturlparserfunc の呼び出し元を開示してくれなくなったのでしょうか?
指摘から逃げてもコードが勝手に改善することはないでしょう。

さらに、この部分
ぷぷぷジューシー さんが書きました:
2ヶ月前

コード:

      rpath = malloc(bmfunc_rlen);
      sprintf(rpath, "%s", temppath);

コード:

      rhost = malloc(bmfunc_rlen);
      sprintf(rhost, "%s", temphost);
については、
・確保している要素数が少なくともナル文字の分足りず、範囲外への書き込みが発生する
・ナル終端されていない配列を%s用に渡している
ため、未定義動作になります。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

ぷぷぷジューシー
記事: 22
登録日時: 3ヶ月前
住所: アンドロメダ銀河系のどこかに住んでいる

Re: マルチバイトの変換後出力がNULL

#5

投稿記事 by ぷぷぷジューシー » 2ヶ月前

情報がフェイクです
面倒なことはCGo使おう!

ぷぷぷジューシー
記事: 22
登録日時: 3ヶ月前
住所: アンドロメダ銀河系のどこかに住んでいる

Re: マルチバイトの変換後出力がNULL

#6

投稿記事 by ぷぷぷジューシー » 2ヶ月前

sprintf(rhost, "%s", temphost);
の部分が配列ではないかったのかっと思うci
問題の部分を取り出し写したコード

コード:

#include <stdio.h>
#include <string.h>

void ae(char* ae){
  char tempae[432] = {'\0'};
  sprintf(tempae, "%s", "afe)");
  printf("%s\n", tempae);
  *ae = *tempae;
  printf("%s\n", ae);
  return;
}


int main(void)
{
    char a;
    ae(&a);
    printf("%s\n", a);

    return 0;
}
面倒なことはCGo使おう!

アバター
みけCAT
記事: 6432
登録日時: 10年前
住所: 千葉県
連絡を取る:

Re: マルチバイトの変換後出力がNULL

#7

投稿記事 by みけCAT » 2ヶ月前

ぷぷぷジューシー さんが書きました:
2ヶ月前
sprintf(rhost, "%s", temphost);
の部分が配列ではないかったのかっと思うci
申し訳ありません。意味がよくわかりません。
ぷぷぷジューシー さんが書きました:
2ヶ月前
問題の部分を取り出し写したコード
  • printf("%s\n", ae);は、文字列(ナル終端された文字の配列)へのポインタを要求する%sに対してナル終端されていない領域へのポインタを渡しているため、未定義動作になります。
    よくある挙動としては、tempaeの最初の要素である「a」に続いて、ゴミが出力されることがあります。
  • printf("%s\n", a);は、文字列へのポインタ(char*)を要求する%sに対してchar型のデータ(可変長引数の部分なのでintに変換される)を渡しているため、未定義動作になります。
    よくある挙動としては、渡された整数を無理やりポインタとして解釈したものは無効な場所を指しているので、値を読み取ることができず、アクセス違反(Segmentation Fault)になることがあります。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

アバター
みけCAT
記事: 6432
登録日時: 10年前
住所: 千葉県
連絡を取る:

Re: マルチバイトの変換後出力がNULL

#8

投稿記事 by みけCAT » 2ヶ月前

ぷぷぷジューシー さんが書きました:
2ヶ月前
情報がフェイクです
何のことでしょうか?
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

ぷぷぷジューシー
記事: 22
登録日時: 3ヶ月前
住所: アンドロメダ銀河系のどこかに住んでいる

Re: マルチバイトの変換後出力がNULL

#9

投稿記事 by ぷぷぷジューシー » 2ヶ月前

みけCAT さんが書きました:
2ヶ月前
ゴミが出力されることがあります。
[*]printf("%s\n", a);は、文字列へのポインタ(char*)を要求する%sに対してchar型のデータ(可変長引数の部分なのでintに変換される)を渡しているため、未定義動作になります。
よくある挙動としては、渡された整数を無理やりポインタとして解釈したものは無効な場所を指しているので、値を読み取ることができず、アクセス違反(Segmentation Fault)になることがあります。
[/list]
どうしてごみが出るのかね?
printfはもともとの仕様?
あとこのコードって

コード:

 *ae = *tempae;
普通に値を入れているっと思うだけどどうだろうか
面倒なことはCGo使おう!

アバター
みけCAT
記事: 6432
登録日時: 10年前
住所: 千葉県
連絡を取る:

Re: マルチバイトの変換後出力がNULL

#10

投稿記事 by みけCAT » 2ヶ月前

ぷぷぷジューシー さんが書きました:
2ヶ月前
どうしてごみが出るのかね?
有効なデータの範囲内に終端のナル文字('\0')が無いため、
続けて無効な(範囲外で何があるかわからない)領域を読み、ナル文字の前まで出力してしまうからです。
ぷぷぷジューシー さんが書きました:
2ヶ月前
printfはもともとの仕様?
printfは少なくともC89にはあります。
The C89 Draft
ぷぷぷジューシー さんが書きました:
2ヶ月前
あとこのコードって

コード:

 *ae = *tempae;
普通に値を入れているっと思うだけどどうだろうか
これはポインタaeが指している場所にポインタtempaeが指しているものを代入するコードですね。
aeは関数名としても使われており紛らわしいですが、ここでは引数(char*型)として解釈され、
この引数には有効なポインタが渡されています。
また、tempaeは配列ですが、ここでは配列の先頭要素へのポインタに変換され、
この先頭要素には不定でない値が入っています。
したがって、この行は問題ないと考えられます。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

ぷぷぷジューシー
記事: 22
登録日時: 3ヶ月前
住所: アンドロメダ銀河系のどこかに住んでいる

Re: マルチバイトの変換後出力がNULL

#11

投稿記事 by ぷぷぷジューシー » 2ヶ月前

みけCAT さんが書きました:
2ヶ月前
有効なデータの範囲内に終端のナル文字('\0')が無いため、
続けて無効な(範囲外で何があるかわからない)領域を読み、ナル文字の前まで出力してしまうからです。
ほうほう
みけCAT さんが書きました:
2ヶ月前
printfは少なくともC89にはあります。
The C89 Draft
初めて知りました
面倒なことはCGo使おう!

ぷぷぷジューシー
記事: 22
登録日時: 3ヶ月前
住所: アンドロメダ銀河系のどこかに住んでいる

Re: マルチバイトの変換後出力がNULL

#12

投稿記事 by ぷぷぷジューシー » 2ヶ月前

初めてしったけどsprintfは継続して扱うのでははく一回、一回値を扱う関数なのかな?

コード:

#include <stdio.h>

int main(void)
{
    char str[20];

    sprintf( str, "%s\n", "hello" );
    printf("%d\n", *(int*)str);
    sprintf( str, "%s\n", "Clang" );
    printf("%d\n", *(int*)str);

    return 0;
}
面倒なことはCGo使おう!

Bull
記事: 145
登録日時: 6年前

Re: マルチバイトの変換後出力がNULL

#13

投稿記事 by Bull » 2ヶ月前

ぷぷぷジューシー さんが書きました:
2ヶ月前
初めてしったけどsprintfは継続して扱うのでははく一回、一回値を扱う関数なのかな?
継続して扱うと言えるのかどうか分かりませんが、続けて使うことはできます。

コード:

#include <stdio.h>

void sum(int n, char *buf)
{
	int s = 0;
	int t = 0;
	int i;
	for (i = 1; i < n; ++i) {
		t += i;
		s = sprintf(buf += s, "%d+", i);
	}
	t += i;
	sprintf(buf + s, "%d=%d", i, t);
}

int main(void)
{
	char buff[1000];
	sum(10, buff);

	printf("%s\n", buff);
}

ぷぷぷジューシー
記事: 22
登録日時: 3ヶ月前
住所: アンドロメダ銀河系のどこかに住んでいる

Re: マルチバイトの変換後出力がNULL

#14

投稿記事 by ぷぷぷジューシー » 2ヶ月前

Bull さんが書きました:
2ヶ月前

コード:

#include <stdio.h>
		s = sprintf(buf += s, "%d+", i);
上のコードがどうなっているの?
Buf += sという部分がわからない
どのようになってどのような動きするの?googleで C言語 配列 略称など調べましたが出てこない...
面倒なことはCGo使おう!

アバター
みけCAT
記事: 6432
登録日時: 10年前
住所: 千葉県
連絡を取る:

Re: マルチバイトの変換後出力がNULL

#15

投稿記事 by みけCAT » 2ヶ月前

前回出力したバイト数がsに格納されているので、
bufが指す位置をその分進めて、前回書き込んだ内容の次から書き込むようにしていますね。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

ぷぷぷジューシー
記事: 22
登録日時: 3ヶ月前
住所: アンドロメダ銀河系のどこかに住んでいる

Re: マルチバイトの変換後出力がNULL

#16

投稿記事 by ぷぷぷジューシー » 1ヶ月前

みけCAT さんが書きました:
2ヶ月前
前回出力したバイト数がsに格納されているので、
bufが指す位置をその分進めて、前回書き込んだ内容の次から書き込むようにしていますね。
なんとなく分かった
面倒なことはCGo使おう!

返信

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