|
楼主 |
发表于 2022-1-25 18:04:08
|
显示全部楼层
本帖最后由 ihavedone 于 2022-1-25 18:08 编辑
做了一些实验,发现在递归函数里调用简单的 printf("123"),或者 sprintf(buf, "123"); 等并不会死机。
但是当命令格式串越来越复杂,参数越来越多后,就会死机了。。。
采用暴力方法,加堆栈,16k 加到 32k,并且屏蔽几个 sprintf,结果可以了。。。
然后把屏蔽的几个打开,死机了。
然后继续加堆栈到 64k,可以了。。。
比较不理解的是: sprintf 中的 buf 是函数传进去的地址。
每次递归,都会从外层函数的结尾处开始写,应该不要特别大的堆栈才对。。。
个人猜测是不是 sprintf 等函数会先自己开辟一个局部缓存,把数据弄好后才复制到用户给定的缓存中去。。
如果是这样,那每嵌套一次堆栈用量都是蹭蹭地往上涨。
函数代码如下:
uint32_t ptc_pc_format_xml(XML_NOTE* root, char* buf, uint32_t size, uint16_t depth)
{
uint32_t cnt = 0;
XML_NOTE* note;
if((root==NULL) || (buf==NULL) || (size==0))
{
return 0;
}
DBG_VAR_ADDR("cnt", cnt);
note = root;
while(note)
{
cnt += snprintf(buf+cnt, size-cnt, "%*s<%s>", depth*2, "", note->name);
if(note->firstchild)
{
cnt += snprintf(buf+cnt, size-cnt, "\n");
cnt += ptc_pc_format_xml(note->firstchild, buf+cnt, size-cnt, depth+1);
cnt += snprintf(buf+cnt, size-cnt, "%*s</%s>\n", depth*2, "", note->name);
}
else if(note->pdat)
{
cnt += snprintf(buf+cnt, size-cnt, "%s", note->pdat);
cnt += snprintf(buf+cnt, size-cnt, "</%s>\n", note->name);
}
else
{
cnt += snprintf(buf+cnt, size-cnt, "</%s>\n", note->name);
}
note = note->next;
}
buf[cnt] = 0;
return cnt;
}
XML_NOTE 是节点结构体 :typedef struct _xml_node
{
char name[XML_NAME_MAX_LEN+1]; // 节点名称
char* pdat; // 节点内容。如果 child 不为空,则内容必须为空
struct _xml_node* prev; // 上一个同级节点
struct _xml_node* next; // 下一个同级节点
struct _xml_node* parent; // 父节点
struct _xml_node* firstchild; // 第一个子节点
struct _xml_node* lastchild; // 最后一个子节点
}XML_NOTE;
DBG_VAR_ADDR("cnt", cnt); 是打印变量地址的宏定义。
|
|