2014-12-03 4 views
3

Я столкнулся с этой странной проблемой. Для удаления файла unlink() API вызывается в моем коде. Этот вызов удаляет файл и преуспеть на платформах, отличных от Windows. В окнах это удается (возвращает 0), но не удаляет файл.DeleteFile() или unlink() вызывает успешное выполнение, но не удаляет файл

Чтобы поэкспериментировать, я добавил цикл, чтобы повторно называть тот же API. На второй итерации я получил ошибку отказа от разрешения, код ошибки = 13. Хотя атрибуты чтения/записи задаются в файле, и программа имеет полное разрешение на доступ к файлу.

Я тогда позвонил DeleteFile() вместо unlink() API. К моему удивлению, я вижу тот же результат, вызов преуспел, то есть вернулся 1, но файл не удаляется физически.

Я проверил утилиту разблокировки, никакая другая программа не обращается к файлу, кроме программы, которая пытается удалить этот файл.

Есть ли у кого-нибудь идеи, что еще может быть неправильно?

Редактировать 1: Просто чтобы файл не был открыт во время его удаления. Я сохранил дескриптор, когда был создан файл, и попытался закрыть его перед удалением, но я получил ошибку «UNOPENED» (Errcode: 9 - Bad file descriptor) ». Таким образом, я делаю вывод, что файл не был открыт во время его удаления.

Редакция 2 В соответствии с просьбой, приведена упрощенная версия кода, используемого для создания и удаления файла.

// Code to create the file 
int create_file(const char* path) 
{ 
    HANDLE osfh;       /* OS handle of opened file */ 
    DWORD fileaccess;      /* OS file access (requested) */ 
    DWORD fileshare;      /* OS file sharing mode */ 
    DWORD filecreate;      /* OS method of opening/creating */ 
    DWORD fileattrib;      /* OS file attribute flags */ 
    SECURITY_ATTRIBUTES SecurityAttributes; 


    SecurityAttributes.nLength= sizeof(SecurityAttributes); 
    SecurityAttributes.lpSecurityDescriptor= NULL; 
    SecurityAttributes.bInheritHandle= !(oflag & _O_NOINHERIT); 



fileaccess= GENERIC_WRITE; 
fileshare= FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE; 
filecreate= CREATE_NEW; 


if ((osfh= CreateFile(path, fileaccess, fileshare, &SecurityAttributes, 
filecreate, fileattrib, NULL)) == INVALID_HANDLE_VALUE) 
{ 
    // error handling 
} 

} 

//Code to delete the file - 
int remove_file (const char* name) 
{ 
    if ((err = unlink(name)) == -1) 
    { //Error handling } 
} 

Edit3 Как указано на Joachim Pileborg и icabod, что DeleteFile() не удаляет файл, если он все еще открыт. Как было предложено Remy Lebeau, чтобы использовать проводник процесса. Я обнаружил, что один дескриптор файла был действительно открыт, когда я закрыл его из файла explorer процесса, удаленного как шарм :)

Я также упомянул в документе Edit1, когда пытался закрыть файл. Я получил ошибку. Это произошло потому, что дескриптор файла, который я получаю от createfile(), не является фактическим дескриптором, возвращаемым API CreateFile(), а не логическим отображаемым дескриптором из-за сложности кода, поддерживающего другие не-windows-платформы. В любом случае, теперь я понял основную причину проблемы, но я ожидал, если файл с открытым дескриптором будет передан в DeleteFile() API, тогда он должен потерпеть неудачу в первой попытке, а не преуспеть и дождаться закрытия открытых дескрипторов.

+4

Вы говорите: «никакая другая программа не выполняет доступ к файлу, кроме программы, которая пытается удалить этот файл». Означает ли это, что файл открыт в вашей программе (например, 'open',' fopen' или 'CreateFile')? Тогда нет, он не будет удален с диска, так как ваша программа все еще открыта. Если вы сначала закроете файл и * затем * удалите его, он должен работать. –

+1

Я нахожу это странным, если люди считают, что вопрос не стоит спрашивать, что вместе с голосом. Что случилось с вопросом? – Rahul

+0

@JoachimPileborg, если файл все еще открыт, не должен 'DeleteFile' возвращать false? –

ответ

5

Предполагая, что вы вызываете функцию Createfile, а затем вызовите функцию remove_file ... у вас все еще есть дескриптор, открытый для файла. Функция WinAPI CreateFile, если она преуспевает, держит ручку открытой в файле. В вашем предоставленном коде вы не закрываете этот дескриптор.

Из документации на DeleteFile:

Функция DeleteFile помечает файл для удаления при закрытии. Поэтому удаление файла не происходит до тех пор, пока последний дескриптор файла не будет закрыт. Последующие вызовы CreateFile для открытия файла не выполняются с помощью ERROR_ACCESS_DENIED.

Я предполагаю, что у вас все еще есть ручка, и когда вы закрываете этот дескриптор, файл будет удален.

Однако ваш образец кода является неполным, поэтому его сложно рассказать.

+1

Вы можете использовать такой инструмент, как SysInternals Process Explorer, чтобы узнать, кто имеет открытый дескриптор удаляемого файла. –

+0

Да, PE очень полезен для этого. Я хотел бы отметить, что вы не должны использовать его, чтобы заставить дескриптор закрыт - как указывает Раймонд Чен (http://technet.microsoft.com/en-us/magazine/2009.04.windowsconfidential.aspx), он может быть очень плохим. Лучше убедиться, что вы закрываете все свои ручки, и если вы беспокоитесь о том, что другие пользователи обращаются к файлу, не открывайте его с помощью доступа SHARED. – icabod