ページ 1 / 1
マルチバイトの変換後出力がNULL
Posted: 2021年2月25日(木) 18:31
by ぷぷぷジューシー
コード:
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;
}
Re: マルチバイトの変換後出力がNULL
Posted: 2021年2月25日(木) 19:18
by みけCAT
ぷぷぷジューシー さんが書きました: ↑3年前
コード:
rhost = '\0', rpath = '\0';
ここでポインタに0を代入しています。
0をポインタに変換するとNULLになります。
Re: マルチバイトの変換後出力がNULL
Posted: 2021年2月28日(日) 01:35
by ぷぷぷジューシー
コード:
rhost = '\0', rpath = '\0';
のコードを消したましたが結果が変わりません
Re: マルチバイトの変換後出力がNULL
Posted: 2021年3月01日(月) 04:50
by みけCAT
最初から引数にNULLを与え、それを書き換えなければ、NULLのままになるでしょう。
例えば、第一引数を
コード:
"http://example.com/hoge"
とした場合、rpathへの代入は行われません。
どうして geturlparserfunc の呼び出し元を開示してくれなくなったのでしょうか?
指摘から逃げてもコードが勝手に改善することはないでしょう。
さらに、この部分
ぷぷぷジューシー さんが書きました: ↑3年前
コード:
rpath = malloc(bmfunc_rlen);
sprintf(rpath, "%s", temppath);
コード:
rhost = malloc(bmfunc_rlen);
sprintf(rhost, "%s", temphost);
については、
・確保している要素数が少なくともナル文字の分足りず、範囲外への書き込みが発生する
・ナル終端されていない配列を%s用に渡している
ため、未定義動作になります。
Re: マルチバイトの変換後出力がNULL
Posted: 2021年3月07日(日) 01:15
by ぷぷぷジューシー
情報がフェイクです
Re: マルチバイトの変換後出力がNULL
Posted: 2021年3月07日(日) 04:14
by ぷぷぷジューシー
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;
}
Re: マルチバイトの変換後出力がNULL
Posted: 2021年3月08日(月) 07:18
by みけCAT
ぷぷぷジューシー さんが書きました: ↑3年前
sprintf(rhost, "%s", temphost);
の部分が配列ではないかったのかっと思うci
申し訳ありません。意味がよくわかりません。
- printf("%s\n", ae);は、文字列(ナル終端された文字の配列)へのポインタを要求する%sに対してナル終端されていない領域へのポインタを渡しているため、未定義動作になります。
よくある挙動としては、tempaeの最初の要素である「a」に続いて、ゴミが出力されることがあります。
- printf("%s\n", a);は、文字列へのポインタ(char*)を要求する%sに対してchar型のデータ(可変長引数の部分なのでintに変換される)を渡しているため、未定義動作になります。
よくある挙動としては、渡された整数を無理やりポインタとして解釈したものは無効な場所を指しているので、値を読み取ることができず、アクセス違反(Segmentation Fault)になることがあります。
Re: マルチバイトの変換後出力がNULL
Posted: 2021年3月08日(月) 07:23
by みけCAT
Re: マルチバイトの変換後出力がNULL
Posted: 2021年3月09日(火) 06:20
by ぷぷぷジューシー
みけCAT さんが書きました: ↑3年前
ゴミが出力されることがあります。
[*]printf("%s\n", a);は、文字列へのポインタ(char*)を要求する%sに対してchar型のデータ(可変長引数の部分なのでintに変換される)を渡しているため、未定義動作になります。
よくある挙動としては、渡された整数を無理やりポインタとして解釈したものは無効な場所を指しているので、値を読み取ることができず、アクセス違反(Segmentation Fault)になることがあります。
[/list]
どうしてごみが出るのかね?
printfはもともとの仕様?
あとこのコードって
普通に値を入れているっと思うだけどどうだろうか
Re: マルチバイトの変換後出力がNULL
Posted: 2021年3月09日(火) 07:45
by みけCAT
有効なデータの範囲内に終端のナル文字('\0')が無いため、
続けて無効な(範囲外で何があるかわからない)領域を読み、ナル文字の前まで出力してしまうからです。
printfは少なくともC89にはあります。
The C89 Draft
ぷぷぷジューシー さんが書きました: ↑3年前
あとこのコードって
普通に値を入れているっと思うだけどどうだろうか
これはポインタaeが指している場所にポインタtempaeが指しているものを代入するコードですね。
aeは関数名としても使われており紛らわしいですが、ここでは引数(char*型)として解釈され、
この引数には有効なポインタが渡されています。
また、tempaeは配列ですが、ここでは配列の先頭要素へのポインタに変換され、
この先頭要素には不定でない値が入っています。
したがって、この行は問題ないと考えられます。
Re: マルチバイトの変換後出力がNULL
Posted: 2021年3月11日(木) 03:52
by ぷぷぷジューシー
みけCAT さんが書きました: ↑3年前
有効なデータの範囲内に終端のナル文字('\0')が無いため、
続けて無効な(範囲外で何があるかわからない)領域を読み、ナル文字の前まで出力してしまうからです。
ほうほう
Re: マルチバイトの変換後出力がNULL
Posted: 2021年3月11日(木) 05:40
by ぷぷぷジューシー
初めてしったけど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;
}
Re: マルチバイトの変換後出力がNULL
Posted: 2021年3月13日(土) 22:18
by Bull
ぷぷぷジューシー さんが書きました: ↑3年前
初めてしったけど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);
}
Re: マルチバイトの変換後出力がNULL
Posted: 2021年3月14日(日) 17:02
by ぷぷぷジューシー
Bull さんが書きました: ↑3年前
コード:
#include <stdio.h>
s = sprintf(buf += s, "%d+", i);
上のコードがどうなっているの?
Buf += sという部分がわからない
どのようになってどのような動きするの?googleで C言語 配列 略称など調べましたが出てこない...
Re: マルチバイトの変換後出力がNULL
Posted: 2021年3月14日(日) 20:26
by みけCAT
前回出力したバイト数がsに格納されているので、
bufが指す位置をその分進めて、前回書き込んだ内容の次から書き込むようにしていますね。
Re: マルチバイトの変換後出力がNULL
Posted: 2021年3月17日(水) 18:11
by ぷぷぷジューシー
みけCAT さんが書きました: ↑3年前
前回出力したバイト数がsに格納されているので、
bufが指す位置をその分進めて、前回書き込んだ内容の次から書き込むようにしていますね。
なんとなく分かった