C sprintf缓冲区sigsegv错误

时间:2013-06-09 13:35:04

标签: c arrays printf sigsegv fault

我的程序有问题:我一直在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;
         }
      //........
    }
}

我很确定问题是“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 个答案:

答案 0 :(得分:2)

对于BuildCMD(),参数dataBuff是一个指针。但是你已经将dataBuff声明为指针数组! 如果你有 char dataBuff [100]; 然后你可以使用 BuildCMD(CALC,tmpdata伪,0.f,dataBuff);

答案 1 :(得分:0)

鉴于此功能原型:

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

这个电话没有意义:

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

你看到dataBuff的类型是如何错误的?您没有启用编译器诊断吗?你应该,因为编译器会立即捕获到这个错误,而不需要运行它来发现它是错误的。

答案 2 :(得分:0)

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

答案 3 :(得分:0)

你正在分配一个char指针数组而不是一个chars数组,我很确定编译器抱怨在调用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将指向新字符串)。