【问题标题】:truncating files with windows.h, C用 windows.h、C 截断文件
【发布时间】:2013-05-25 06:28:45
【问题描述】:

我的任务是创建一个随机访问/二进制列表,并允许程序使用 windows.h 库及其 HANDLE 函数从中删除目标记录(结构)。 我编写了以下代码以尝试截断文件,虽然在文件末尾删除某些内容似乎可行,但中间处理文件的部分似乎很麻烦,我很难过。

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;
        }
    }
}

}

谁能分享一下出了什么问题?

【问题讨论】:

  • 很小的一点不能回答你的问题,但我注意到你投了malloc()的回报。请参阅stackoverflow.com/questions/605845/…,了解为什么应该避免这样做:)
  • 谢谢,其实信息量很大
  • 再次,不回答您的问题,但不是遍历所有记录来查找最后一条记录,您可以使用fseek(file, sizeof(buffer), SEEK_END) 然后ftell() 来为您节省一个while 循环吗?所有读取/写入/搜索是否成功...如果您检查ferror(),您是否检测到任何错误?从检查来看,它似乎很好......我不知道为什么它不起作用。如果您能说出您看到的哪些错误或症状可能会更清楚地了解现场情况?
  • 这实际上是一个很好的建议。我可能对我尝试了各种不同的东西而忘记简化它的代码感到太沮丧。它似乎没有发出任何怪癖,所以我真的很困惑
  • 失败的症状是什么?

标签: c struct replace binaryfiles truncate


【解决方案1】:

我认为该问题与以下内容有关。当您说以下内容时,便士掉了:

好吧,我检查了 ferror() 但它返回 0。程序只是 在我尝试运行我提到的部分和运行后崩溃 通过调试工具,我得到“0x577514cf 处的未处理异常 项目 5.exe 中的 (msvcr100d.dll):0xC0000005:读取访问冲突 位置 0xcdcdcdcd。”

0xcdcdcdcd 的值为

"...来自 C 运行时内部的调试值 图书馆。当您在调试版本中分配一块内存时,它是 初始化为这个虚假值,以期捕获错误。 0xCDCDCDCD 是非 NULL 并且永远不是有效的内存指针......” (http://www.microsoft.com/msj/1198/c/c1198.aspx)。

因此这意味着某些东西未能分配内存。

我要做的第一件事是检查malloc() 语句不返回NULL

接下来,检查fopen()的返回值不是NULL

接下来是以下几行......

s.artist = buffer.artist;
s.name = buffer.name;

他们正在引入内存泄漏。您不是在此处复制字符串,而是在复制指针。因此,您之前malloc()artistname 编辑的内存现在丢失了,您将永远无法free() 它。例如,我认为您可能打算使用strcpy() 将字符串从buffer 复制到s.name

另外,你是在写指向文件的指针吗?如果您回读 buffer.name 并且它是一个指针(我认为这一定是因为您将其视为这样),那么您正在回读任何在创建文件时有效的旧地址,但在 这个实例您的程序可能完全无效!然后尝试取消引用该指针会导致您头疼!

我建议当您将结构写入文件时,不要写入指针s.names.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.names.label,因为strdup()已经创建了一个你有责任处理的副本。

【讨论】:

  • 我会调查这个,但到目前为止,似乎只需 fclose()'ing 文件就可以了。感谢您的帮助
  • 虽然fclose()ing 你的文件可能有助于解决这个问题,但我认为你有内存泄漏,除非你在做s.name/label = buffer.name/label 之前释放s.name/label 而我没有发现它?存储指向文件的指针也是一个坏主意。你不能保证这些在程序的另一个实例中意味着什么:)
  • 感谢 cmets。正如我们所说,我正在改进代码,尽管我没有提到我的程序最初使用“wb”处理程序重新打开文件(因此所有旧数据都被删除)
【解决方案2】:

我已经解决了。显然,我忘记了一些非常重要的事情。那是关闭(如fclose())文件。总是说这个会引起问题,这是一个例子。

【讨论】:

    猜你喜欢
    • 2011-08-15
    • 2016-06-14
    • 1970-01-01
    • 2010-10-26
    • 2011-09-26
    • 2010-12-27
    • 1970-01-01
    • 2016-10-17
    • 1970-01-01
    相关资源
    最近更新 更多