-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);

构建CMD代码:

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;
         }
      //........
    }
}

我很确定问题是“dataBuff”,因为即使我使用 sprintf 尝试存储一个普通的常量字符串,它也会给我同样的错误。这只是......我无法弄清楚我做错了什么。提前致谢。

编辑:作为函数头解决的问题:

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

给定这个函数原型:

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

尝试取消引用具有无效值的指针时可能会发生 SIGSEV。特别是,对于大多数环境来说,0 是一个无效值。printf 必须尊重您的值数组,因此可能是您为其分配了无效值。

于 2013-06-09T13:42:30.217 回答
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 回答