-1

プログラムに問題があります: sprintf 関数でセグメンテーション違反が発生し続けますが、その理由がわかりません。バッファーは十分に大きく、ポインターを正しく渡していると思いますが、理由がわかりませんうまくいきません。

コードは次のとおりです。

呼び出し:

char dataBuff[100];
//same error with char *dataBuff=malloc(sizeof(char)*100);
//those vars were declared before
int tmpData[5]={TID,i,JobList[i].Num1,JobList[i].Op,JobList[i].Num2};
//here's the function that return the sigsegv error
BuildCMD(CALC,tmpData,0.f,dataBuff);

BuildCMD コード:

int BuildCMD(enum CMD cmd,int *values,float Res,char *dataBuff)
{
     switch(cmd)
     {//........
         case CALC:
         {
              //this line cause the error,it's just a formatted parameters list
              //note:same error with just 
              //sprintf(dataBuff,"abc");
              spritf(dataBuff,"0*;%d;%d;%d;%d;%d;%d;%.5f|\n",cmd,values[0],values[1],values[2],values[3],values[4],Res);
              break;
         }
      //........
    }
}

sprintf を使用して通常の定数文字列を保存しようとしても、同じエラーが発生するため、問題は「dataBuff」であると確信しています。それはただ...私が間違っていることを理解できません。前もって感謝します。

編集:関数ヘッダーとして解決された問題:

int BuildCMD(enum CMD cmd,int *values,float Res,char dataBuff[100])

sprintf 呼び出しとして:

sprintf(&dataBuff,"0*;%d;%d;%d;%d;%d;%d;%.5f|\n",cmd,values[0],values[1],values[2],values[3],values[4],Res);
4

4 に答える 4

2

BuildCMD() の場合、パラメーター dataBuff はポインターです。しかし、dataBuff をポインターの配列として宣言しています。char dataBuff[100]; がある場合 その後、BuildCMD(CALC,tmpData,0.f,dataBuff); を使用できます。

于 2013-06-09T14:22:16.590 に答える
0

無効な値を持つポインターを逆参照しようとすると、SIGSEV が発生する可能性があります。特に、0 はほとんどの環境で無効な値です。printf は値の配列を参照する必要があるため、無効な値を割り当てている可能性があります。

于 2013-06-09T13:42:30.217 に答える
0

この関数プロトタイプが与えられた場合:

int BuildCMD(enum CMD cmd,int *values,float Res,char *dataBuff)

この呼び出しは意味がありません:

char *dataBuff[100];
BuildCMD(CALC,tmpData,0.f,dataBuff);

dataBuff の型が間違っていることがわかりますか? コンパイラ診断を有効にしていませんか? コンパイラはこのエラーをすぐにキャッチするため、エラーを検出するために実行する必要はありません。

于 2013-06-09T13:39:37.947 に答える
0

char の配列ではなく、char ポインターの配列を割り当てています。BuildCMD の呼び出しで、char ** を char * として渡すことについてコンパイラが文句を言うと確信しています。

とにかく、とにかく asprintf を使用する必要があります (C11 標準にあると思います)。この呪文のような固定バッファー サイズは、将来のプログラムの正確性に影響を与えるためです (必要は大きくなり、バッファーはそうではありません。遠い将来のどこかで、プログラム爆発します…)。

編集:正しいバージョンは

//Don't do this!
char dataBuff[100];
int tmpData[5]={TID,i,JobList[i].Num1,JobList[i].Op,JobList[i].Num2};
BuildCMD(CALC, tmpData, 0.f, dataBuff);

int BuildCMD(enum CMD cmd, int* values, float Res, char* dataBuff) {
    sprintf(dataBuff, "whatever...");
}

これが機能するのは、配列識別子が最初の要素へのポインターに暗黙的に変換されるため、BuildCMD に渡されると dataBuff が char* になるためです (これは、sprintf が最初の引数として期待している型でもあります)。----- これは正しいですが、あなたがすべきことではありません! -----

あなたがすべきことはこれです:

char *data = NULL;
int tmpData[5]={TID,i,JobList[i].Num1,JobList[i].Op,JobList[i].Num2};
BuildCMD(CALC, tmpData, 0.f, &dataBuff);
//do whatever you need to do with the string
free(dataBuff);

//mallocs a buffer in dataBuff, the caller is responsible to free it.
int BuildCMD(enum CMD cmd, int* values, float Res, char** pointerAdress) {
    asprintf(pointerAdress, "whatever...");
}

これにより、ポインターへのポインターが BuildCMD (dataBuff に格納されているポインターのアドレス) に渡されるため、BuildCMD/asprintf は、ポインター ポインターが指すメモリ位置に新しく割り当てられたポインターを返すことができることに注意してください (呼び出しの後、dataBuff は新しい文字列を指します)。

于 2013-06-09T13:46:00.607 に答える