我正在编写一个打印到标准输出的函数,就像普通的printf函数一样,但是需要使用{i}或{s}来获取%d或%s等指标。我的问题是,当格式参数的字符串太长约23个字符时,我在调用vfprintf函数的行处得到分段错误。
int mr_asprintf(const char *format, ...)
{
int i;
char *newFormat = calloc(1,sizeof(char));
char integer[3] = "%d";
char str[3] = "%s";
char tmpStr[2];
va_list args;
newFormat[0] ='\0';
tmpStr[1] = '\0';
for(i=0;format[i]!='\0';i++) // convert to printf syntaxe
{
if(format[i]=='{' && format[i+2]=='}') //check if it's {x}
{
switch(format[i+1])
{
case 'i':
strcat(newFormat,integer);
i += 2;
break;
case 's':
strcat(newFormat,str);
i += 2;
break;
}
}
else
{
tmpStr[0] = format[i];
strcat(newFormat,tmpStr);
}
}
va_start(args,format);
int s = vfprintf(stdout,newFormat,args);
va_end(args);
free(newFormat);
return s;
}
测试示例:
int main()
{
char *result = mr_asprintf("bce }edadacba{i}}aa}da{s}fe aeaee d{i}cefaa",55,"XXX",66);
printf("%s\n",result);
return 0;
}
答案 0 :(得分:1)
您的字符串newFormat
被分配为大小1,并且您使用strcat附加它 - 但是strcat不会进行任何数组大小调整,因此newFormat
将很快开始踩踏未分配的内存。输出字符串的长度始终为< =输入字符串的长度,因此您应该分配该大小的字符串。
最后,虽然这不应该导致vprintf中的段错误,但以后可能会导致意外行为 -
for(i=0;format[i]!='\0';i++) // convert to printf syntaxe
{
if(format[i]=='{' && format[i+2]=='}') //check if it's {x}
检查当前位置是否为字符串的结尾,然后检查结束括号的当前位置后面的两个字符,而不检查字符串是否在下一个空格上结束。这可能导致在阵列的已分配内存之外进行读取。用if(format[i]=='{' && (format[i+1]=='i' || format[i+1]=='s') && format[i+2]=='}')
替换if语句可以避免这个问题。