使用windows.h和C截断文件
我的任务是创建一个随机访问/二进制列表,并允许程序使用windows.h库及其句柄函数从中删除目标记录(struct)。 我写了下面的代码试图截断文件,而在文件的末尾擦除某些东西似乎是有效的,中间处理文件的部分似乎是在制造麻烦,而我却被难住了。使用windows.h和C截断文件,c,struct,replace,binaryfiles,truncate,C,Struct,Replace,Binaryfiles,Truncate,我的任务是创建一个随机访问/二进制列表,并允许程序使用windows.h库及其句柄函数从中删除目标记录(struct)。 我写了下面的代码试图截断文件,而在文件的末尾擦除某些东西似乎是有效的,中间处理文件的部分似乎是在制造麻烦,而我却被难住了。 void erase_record(FILE *file, stct buffer, char *target) { HANDLE h; int jump=0; int mark; stct s; file = fopen("list.txt","rb+
void erase_record(FILE *file, stct buffer, char *target)
{
HANDLE h;
int jump=0;
int mark;
stct s;
file = fopen("list.txt","rb+");
s.artist = (char*)malloc(20*(sizeof(char)));
s.name = (char*)malloc(20*(sizeof(char)));
while(1)
{
jump++;
fread(&buffer,sizeof(buffer),1,file);
if(!strcmp(target,buffer.name)) // did we find a match?
{
jump--;
fread(&buffer,sizeof(buffer),1,file); // then check one more time.
if(feof(file)) // is the match right before the eof?
{
fclose(file);
h=CreateFile(L"list.txt",GENERIC_WRITE | GENERIC_READ,0,0,OPEN_ALWAYS,FILE_ATTRIBUTE_NORMAL,0);
SetFilePointer(h,(jump)*sizeof(buffer),NULL,FILE_BEGIN); // truncate from last
SetEndOfFile(h);
CloseHandle(h);
break;
}
else // is it in middle of the file?
{
mark = jump; // we mark the struct we wanted to delete
while(1)
{
s.shelf = buffer.shelf;
s.artist = buffer.artist;
s.name = buffer.name;
jump++;
fread(&buffer,sizeof(buffer),1,file); // find the end of the file first
if(feof(file))// when we DO find the end..
{
break;
}
}
fclose(file);
h=CreateFile(L"list.txt",GENERIC_WRITE | GENERIC_READ,0,0,OPEN_ALWAYS,FILE_ATTRIBUTE_NORMAL,0);
SetFilePointer(h,(jump)*sizeof(buffer),NULL,FILE_BEGIN); //deleting it!
SetEndOfFile(h);
CloseHandle(h);
file = fopen("list.txt","rb+");
fseek(file,mark*sizeof(buffer),SEEK_SET); // we erase the marked struct
fwrite(&s,sizeof(s),1,file);
break;
}
}
}
}
有谁能分享一些关于哪里出了问题的见解吗?。显然,我忘了一些非常重要的事情。这就是关闭文件(如
fclose()
)。人们总是说这个问题会导致问题,这就是一个例子。我认为问题与下面的问题有关。当你说下列话时,硬币掉了下来:
我用ferror()检查了一下,但它返回了0。节目刚刚结束
在我尝试运行我提到的部分和运行之后崩溃
通过调试工具,我得到“0x577514cf处未处理的异常”
(msvcr100d.dll)在Project 5.exe中:0xC0000005:访问冲突读取
位置0xCDCD。“
值0xcdcdcd
为
“…来自C运行时内部的调试值
当您在调试构建中分配内存块时,它是
初始化为这个伪值,希望捕获bug。
0xCDCD为非NULL,并且永远不是有效的内存指针
().
因此,这意味着某些东西无法分配内存
我要做的第一件事是检查malloc()
语句不返回NULL
接下来,检查fopen()
的返回值不是NULL
接下来是以下几行
s.artist = buffer.artist;
s.name = buffer.name;
他们正在引入内存泄漏。您不是在这里复制字符串,而是在复制指针。因此,您以前为artist
和name
使用的malloc()
内存现在已丢失,您将永远无法释放它。例如,我想您可能打算使用strcpy()
将字符串从缓冲区
复制到s.name
另外,您是否正在编写指向文件的指针?如果读回buffer.name
,并且它是一个指针(我认为这一定是因为您将其视为指针),那么您正在读回创建文件时有效的任何旧地址,,但在本例中,您的程序可能完全无效然后尝试取消引用该指针将导致您头痛
我建议在将结构写入文件时,不要写入指针s.name
和s.artist
,而是将实际字符串写入文件。然后从文件中读回字符串,然后为它们创建指针
fwrite(&s,sizeof(s),1,file); // OOPS! You wrote pointer values to a file.
// These pointers will be invalid addresses in the next program instance!
相反,你可以做一些像
fwrite(all non pointer members of struct)
fwrite(&s.label, LABEL_LEN, 1, file); // Note, include the string null-terminator
fwrite(&s.name, NAME_LEN, 1, file); // Note, include the string null-terminator
然后在阅读时,将标签和名称作为实际字符串读回
fread(all non pointer members of struct)
fread(&stringBuffer, LABEL_LEN, 1, file);
s.label = strdup(stringBuffer);
fread(&stringBuffer, NAME_LEN, 1, file);
s.name= strdup(stringBuffer);
后来记得free()
s.name
和s.label
,因为strdup()
已经创建了一个副本,你有责任处理它。非常小的一点没有回答你的问题,但我注意到你投下了malloc()
的回归。请参阅避免这样做的原因:)谢谢,它实际上非常具有信息性。它不回答您的问题,但您可以使用fseek(文件,大小(缓冲区),SEEK__END)
然后ftell()
来为您节省一个while循环,而不是遍历所有记录来查找最后一条记录吗?所有读/写/寻道是否成功确定。。。如果选中ferror()
,是否检测到任何错误?从检查来看,似乎不错。。。我看不出它为什么不起作用。如果你能说出你所看到的错误或症状,可能会对原位有更多的了解?这实际上是一个很好的建议。我可能对代码太失望了,因为我尝试了各种不同的方法,但后来忘记了简化它。它似乎没有表现出任何怪癖,所以我真的很困惑失败的症状是什么?我将对此进行研究,但到目前为止,通过简单的fclose()操作文件似乎有效。感谢您的帮助虽然fclose()
ing您的文件可能有助于解决这一问题,但我认为您可能存在内存泄漏,除非您在执行s.name/label=buffer.name/label
之前释放s.name/label
,而我没有发现它?同时存储指向文件的指针也是一个坏主意。你不能保证这些在程序的另一个实例中有任何意义:)谢谢你的评论。正如我们所说,我正在改进代码,尽管我没有提到我的程序最初使用“wb”处理程序重新打开文件(因此所有旧数据都会被删除)