在什么情况下fscanf会溢出内存?
我实现了一个链表,可以很好地处理各种文件输入(逐行读取并插入它们) 鉴于这段代码,我看到了一些问题,在读取“fff”之后,当使用给定的示例输入执行fscanf时,事情似乎变得糟糕在什么情况下fscanf会溢出内存?,c,linked-list,C,Linked List,我实现了一个链表,可以很好地处理各种文件输入(逐行读取并插入它们) 鉴于这段代码,我看到了一些问题,在读取“fff”之后,当使用给定的示例输入执行fscanf时,事情似乎变得糟糕 one two three ee fff ee 在分析ee时: list = 0x009dfac0 {name=0x009dfac0 "one" next=0x00c98c08 {name=0x00c98c08 "three" next=0x00c98ba0 {name=0x00c98ba0 "two" ...}
one
two
three ee
fff
ee
在分析ee时:
list = 0x009dfac0 {name=0x009dfac0 "one" next=0x00c98c08 {name=0x00c98c08 "three" next=0x00c98ba0 {name=0x00c98ba0 "two" ...} } }
在下一个令牌之后:
list = 0x009dfac0 {name=0x009dfac0 "ee" next=0x009df068 {name=0x009df068 "È”ü\xf\x1" next=0x0ff7caa0 {msvcr110d.dll!_except_handler4(_EXCEPTION_RECORD *, _EXCEPTION_REGISTRATION_RECORD *, _CONTEXT *, void *)} {...} }
在检查我的列表时,“下一个”指针在fscanf被触发后立即损坏。潜在的原因是什么
根据请求插入排序:
void insert_sorted(node_type* list, char* value)
{
// Copy our pointer so we can move around
node_type *n = (node_type*) malloc(sizeof *n);
node_type *loc = NULL;
node_type *tmp;
node_type dat;
node_type* prev = list;
node_type* head = list;
n->next = NULL;
strcpy(n->name, value);
// First element, assign immediately
if( strcmp(list->name, "") == 0 )
{
*list = *n;
return;
}
while(head != NULL)
{
// We should do a comparison to see if one is greater than another
int cmp_result = strcmp(value, head->name);
// If the value is bigger, this means the value needs to be inserted after
if(cmp_result > 0)
{
loc = head;
}
else if (cmp_result < 0) // this needs to be ahead
{
if(prev == head)
{
dat = *head;
*head = *n;
head->next = &dat;
return;
}
prev->next = n;
n->next = head;
return;
}
else if(cmp_result == 0)
{
free(n);
return; // duplicate, die
}
// Advance to the next pointer
prev = head;
head = head->next;
}
// You've reached the end, that must mean you've succesfully reached the point to insert
tmp = loc->next; // get the value we're going to end up detaching
n->next = tmp; // link the two together
loc->next = n;
}
void insert\u排序(节点类型*列表,字符*值)
{
//复制我们的指针,以便我们可以四处移动
node_type*n=(node_type*)malloc(sizeof*n);
节点类型*loc=NULL;
节点类型*tmp;
节点类型dat;
节点类型*prev=列表;
节点类型*头=列表;
n->next=NULL;
strcpy(n->名称、值);
//第一个元素,立即赋值
如果(strcmp(列表->名称“”)==0)
{
*列表=*n;
返回;
}
while(head!=NULL)
{
//我们应该做一个比较,看一个比另一个大
int cmp_result=strcmp(值,头->名称);
//如果该值较大,则意味着需要在后面插入该值
如果(cmp_结果>0)
{
loc=水头;
}
else if(cmp_result<0)//这需要提前完成
{
如果(上一个==头部)
{
dat=*头;
*水头=*n;
head->next=&dat;
返回;
}
上一个->下一个=n;
n->next=头部;
返回;
}
else if(cmp_结果==0)
{
自由(n);
return;//复制,死亡
}
//前进到下一个指针
prev=头部;
头部=头部->下一步;
}
//您已到达终点,这一定意味着您已成功到达插入点
tmp=loc->next;//获取我们最终要分离的值
n->next=tmp;//将两者链接在一起
loc->next=n;
}
将循环修改为
while (fscanf(file, "%s", buffer) == 1) {
length = strlen(buffer);
// ...
}
因为feof(file)
在最后一次成功fscanf()之后仍然返回0
。在第一次失败的fscanf()
之后,它返回非0
关于insert\u sorted()
,请查看以下几行:
head->next = &dat;
return;
由于dat
是一个本地对象,一旦函数返回,保存其地址将导致地址无效。将循环修改为
while (fscanf(file, "%s", buffer) == 1) {
length = strlen(buffer);
// ...
}
因为feof(file)
在最后一次成功fscanf()之后仍然返回0
。在第一次失败的fscanf()
之后,它返回非0
关于insert\u sorted()
,请查看以下几行:
head->next = &dat;
return;
由于dat
是一个本地对象,一旦函数返回,保存其地址将导致地址无效。将循环修改为
while (fscanf(file, "%s", buffer) == 1) {
length = strlen(buffer);
// ...
}
因为feof(file)
在最后一次成功fscanf()之后仍然返回0
。在第一次失败的fscanf()
之后,它返回非0
关于insert\u sorted()
,请查看以下几行:
head->next = &dat;
return;
由于dat
是一个本地对象,一旦函数返回,保存其地址将导致地址无效。将循环修改为
while (fscanf(file, "%s", buffer) == 1) {
length = strlen(buffer);
// ...
}
因为feof(file)
在最后一次成功fscanf()之后仍然返回0
。在第一次失败的fscanf()
之后,它返回非0
关于insert\u sorted()
,请查看以下几行:
head->next = &dat;
return;
由于dat
是一个本地对象,一旦函数返回,保存其地址将导致地址无效。您没有正确测试文件结尾。通常,使用feof是不正确的,而是测试从文件中读取的函数的返回值
fscanf返回它能够读取的实体数。因此,在您的示例中,您将测试它是否返回1,这表示读取成功。为了避免缓冲区溢出,您可以对要读取的字符数设置一个限制,该限制的数字介于%和s之间
没有理由对缓冲区大小如此吝啬
因此:
顺便说一句,您阅读的不是“逐行”,而是“按空格分隔的字符串逐空格分隔的字符串”。要逐行读取文件,可以使用fgets
在你说“这不是问题”之前,先试试看。这些是此函数可能产生的唯一问题。您没有正确测试文件结尾。通常,使用feof是不正确的,而是测试从文件中读取的函数的返回值
fscanf返回它能够读取的实体数。因此,在您的示例中,您将测试它是否返回1,这表示读取成功。为了避免缓冲区溢出,您可以对要读取的字符数设置一个限制,该限制的数字介于%和s之间
没有理由对缓冲区大小如此吝啬
因此:
顺便说一句,您阅读的不是“逐行”,而是“按空格分隔的字符串逐空格分隔的字符串”。要逐行读取文件,可以使用fgets
在你说“这不是问题”之前,先试试看。这些是此函数可能产生的唯一问题。您没有正确测试文件结尾。通常,使用feof是不正确的,而是测试从文件中读取的函数的返回值
fscanf返回它能够读取的实体数。因此,在您的示例中,您将测试它是否返回1,这表示读取成功。为了避免缓冲区溢出,您可以对要读取的字符数设置一个限制,该限制的数字介于%和s之间
没有理由对缓冲区大小如此吝啬
因此:
顺便说一句,您读的不是“逐行”,而是“按空格分隔的字符串”