Как я могу обработать недопустимую процедуру обработчика исключений? - PullRequest
3 голосов
/ 13 апреля 2020

Я создаю программу, которая создает и удаляет каталоги. Я использую компилятор MSV C (Visual Studio 2017), поэтому я не могу использовать "getcwd ()" или "dirent.h" соответственно. Я пробовал несколько разных способов получить текущий рабочий каталог, но всегда была проблема. Мне удалось распечатать cwd с помощью "_wgetcwd ()". Однако я не мог найти, как я мог преобразовать его вывод, чтобы использовать его в "_rmdir ()" или "_wrmdir ()" в моем исследовании.

Моя главная цель - удалить каталог без установки нового компилятора. Если это условие выполнено, любая помощь приветствуется, потому что я уже пытался установить другой компилятор, но у меня не получилось. Я также пробовал разные способы получить cwd и преобразовать его в желаемый тип данных, но ничего не помогало в области моей IDE и моих базовых c знаний.

Я в значительной степени новичок в программировании и я учусь с этой книгой, которая, к сожалению, использует "dirent.h". Ниже приведен фрагмент моего текущего кода, где я удалил все ошибки. Однако я все еще получаю это последнее досадное исключение:

#include <iostream>
#include <stdlib.h>
#include<string>
#include <direct.h>

int main() {

    int t = 0;
    std::string str;
    char xy = ' ';
    char* _DstBuf = &xy;
    const char* uniquename;
    uniquename = _getdcwd(0, _DstBuf, _MAX_PATH);
    std::cout << "Current path is ";    
    while (*uniquename != '\0') // this pointer points to the beginning of my path
    {
        std::cout << char(*uniquename); //  prints one char of the path name for each iteration

        char var = char(*uniquename);

        str.push_back(var); //here the exception below is thrown.

        // jump to the next block of memory
        uniquename++;
    }
    std::cout << str <<'\n';

    const char* lastchance = str.c_str();

    if (_wchdir('..')) {
        std::cout << "changing directory failed.\n";
    }

    if (_rmdir(lastchance) == -1 && errno == ENOTEMPTY) { 
        std::cout << "Given path is not a directory, the directory is not empty, or the directory is either the current working directory or the root directory.\n";
    }
    else if (_rmdir(lastchance) == -1 && errno == ENOENT) 
    {
        std::cout << "Path is invalid.\n";
    }
    else if (_rmdir(lastchance) == -1 && errno == EACCES)
    {
        std::cout << "A program has an open handle to the directory.\n";
    }
    else if (_rmdir(lastchance)) {
        std::cout << "removing directory still not possible\n";
    }

}

Это исключение, которое я получаю: Необработанное исключение в 0x6E656D69 в Experimentfile.exe: 0xC00001A5: недопустимая подпрограмма обработчика исключений была обнаружено (параметры: 0x00000003).

Ответы [ 2 ]

3 голосов
/ 13 апреля 2020

Так что, если вы собираетесь программировать в стиле C (даже если у вас есть компилятор C ++), вам придется узнать, как работают массивы и указатели. Это далеко слишком большой топи c, чтобы учиться у целых rnet вам нужна хорошая книга .

Однако я укажу некоторые из ошибки

char xy = ' ';
char* _DstBuf = &xy;
const char* uniquename;
uniquename = _getdcwd(0, _DstBuf, _MAX_PATH);

Это просто безнадежно неправильно. Он компилируется, но это не значит, что он будет работать. Это то, что требуется

char DstBuf[_MAX_PATH];
_getdcwd(0, DstBuf, _MAX_PATH);

_getdcwd требует массив , который передается как указатель (смотрите, вам нужно узнать о массивах и указателях).

Тогда вы попытаться распечатать результат и присвоить результат строке. Опять же, код гораздо сложнее, чем нужно. Вот более простая версия

std::string str = DstBuf;
std::cout << str <<'\n';

Затем вы пытаетесь изменить каталоги. Я не знаю, почему вы используете широкую версию _wchdir, когда у вас узкие строки, вместо этого используйте _chdir. И снова параметр неверен, '..' является многосимвольным литералом, но для _chdir требуется строка C. Вот правильная версия, используя _chdir.

if (_chdir("..")) {
    std::cout << "changing directory failed.\n";
} 

Затем вы пытаетесь удалить каталог четыре раза, очевидно, вы не можете удалить каталог более одного раза.

И так далее, и т. д.

2 голосов
/ 13 апреля 2020

Есть несколько проблем с вашим кодом. Я думаю ваше исключение вызвано этой строкой:

uniquename = _getdcwd(0, _DstBuf, _MAX_PATH);

которая вызывает _getdcwd и передает ей указатель на один символ, а также указывает, что указатель может удерживать до _MAX_PATH. Это совершенно неопределенное поведение.

Чтобы решить эту проблему, я думаю, вам следует полностью изменить то, что вы делаете. Ваш код читается как C код, кроме разбросанных частей C ++, таких как std::string. Начиная с C ++ 17, в стандартную библиотеку встроена поддержка манипулирования файловой системой. Поэтому вы можете переписать свой код, используя std::filesystem гораздо более кратким и безопасным способом.

... // get path to delete and store it in del_path (del_path should be an std::filesystem::path object)
std::filesystem::remove_directories(del_path); // Recursive delete the directory specified by del_path
...

Примечание: std::filesystem::remove_directories будет бросить std::filesystem::filesystem_error, если это не удалось.

Вы можете получить текущий каталог, используя std::filesystem - std::filesystem::current_path.

Я также рекомендую взять лучшую книгу на C ++, так как этот, похоже, не учит вас хорошей практике

...