Не удается найти причину нарушения доступа в массиве

!!!Я должен придерживаться этих функций, так как мне не разрешено использовать другие!!!

Небольшое пояснение, что мне нужно сделать: пользователь вводит каталог поиска, затем, если ничего не найдено, появляется сообщение об ошибке. Если что-то найдено, я создаю массив из одной строки, потому что хотя бы один файл был найден, и он сохраняет имя найденного файла. Затем, если FindNextFIle находит что-либо, я добавляю одну строку в существующий массив, и эта новая строка сохраняет новое найденное имя файла.

Первый вывод — это прямой вывод функции, а второй — тестовый вывод массива, чтобы убедиться, что он работает правильно. Но не получается сказать, что нарушен доступ к памяти, поэтому дальше работать не могу.

Вероятно, есть 2 причины, по которым он не работает правильно:

  1. Неверное добавление новой строки
  2. некорректная функция массива печати

Вот main():

system("chcp 1251");
    
    drtctrAr drctr;
    drctr = createDAr();

    WIN32_FIND_DATA FindFileData;
    HANDLE hf;

    hf = FindFirstFile(drctr.str, &FindFileData);
    while (hf == INVALID_HANDLE_VALUE)
    {
        printf("Error opening files or no files found!\n Try changing the search directory or correct your input!\n");
        return 1;

        break;
    }
    
    StringArray fileNames;
    int len;
    fileNames.str = (wchar_t**)malloc(sizeof(wchar_t*) * fileNames.rows);
    
    len = wcslen(FindFileData.cFileName)+1;
    fileNames.sym = (wchar_t*)malloc(sizeof(wchar_t) * len);
    wcscpy_s(fileNames.sym, len, FindFileData.cFileName);

    while (FindNextFile(hf, &FindFileData) != 0)
    {
        printf("Found file: %ls", FindFileData.cFileName);
        printf("\n");

        fileNames.rows++;

        fileNames.str = (wchar_t**)realloc(fileNames.str, sizeof(wchar_t*) * (fileNames.rows));
        int len = wcslen(FindFileData.cFileName) + 1;
        fileNames.str[fileNames.rows-1] = (wchar_t*)malloc(sizeof(wchar_t) * len);
        wcscpy_s(fileNames.str[fileNames.rows-1], len, FindFileData.cFileName);
    }
    FindClose(hf);
    freeDAr(drctr);

    printSA(fileNames);
    filterSA(fileNames);
    freeSA(fileNames);

    system("pause");
    return 0;

А это функция печати в отдельном .cpp:

void printSA(StringArray arr)
{
    printf("...........................\n");
    for (int i = 0; i < arr.rows; i++)
    {
        for(int j=0;j<arr.sym[i];j++)
            printf("Current file: %ls", arr.str[i][j]);
        printf("\n");
    }
}

И саму структуру массива забыл добавить:

struct StringArray
{
    wchar_t** str = NULL;
    wchar_t* sym = NULL;
    int rows = 1;
}; 

Я упомянул обе возможные причины, к сожалению, это не означает, что это правильное предположение, что-то в самом начале выделения массива может быть неправильным

Что такое StringArray? И почему бы не просто std::vector<std::wstring> вместо низкоуровневого кодирования в стиле C с использованием malloc?

PaulMcKenzie 23.12.2020 16:21

Куда вылетает по отладчику?

ssbssa 23.12.2020 16:24

Каким должен быть arr.sym[i]? Почему вы используете его как j < arr.sym[i]? Это не имеет никакого смысла.

Some programmer dude 23.12.2020 16:27

Кроме того, помните ли вы, что строки в стиле C в C++ должны заканчиваться нулем?

Some programmer dude 23.12.2020 16:29
std::vector<std::wstring> fileNames; while (FindNextFile(hf, &FindFileData) != 0) fileNames.push_back(FindFileData.cFileName); -- и это все, что нужно.
PaulMcKenzie 23.12.2020 16:29

Вы пытались сделать что-то сложным путем (malloc/realloc и т. д.), и у вас есть ошибка. Итак, пришло время научиться делать что-то простым способом с std::vector<std::wstring>. На данный момент ваш код написан на C, а не на C++, так что самое время немного изучить C++.

john 23.12.2020 16:30

И почему вы используете свою собственную явную обработку памяти как для массивов, так и для строк? Почему вы не используете std::vector и std::wstring? C++ — это гораздо больше, чем просто «C с классами».

Some programmer dude 23.12.2020 16:30

Я не могу использовать какие-либо объектно-ориентированные функции, так как это часть моего курсового проекта. хотел бы, но мне не разрешено. Я должен придерживаться этих функций, std::vector не является частью программы первого курса, и я делаю курсовой проект в течение первого года. Опять же, я бы хотел, но я не могу ничего использовать из второго курса

Alfredison 23.12.2020 16:32

В любом случае, здесь есть одна ошибка fileNames.sym = (wchar_t*)malloc(sizeof(wchar_t) * len); wcscpy_s(fileNames.sym, len, FindFileData.cFileName); должна быть fileNames.sym = (wchar_t*)malloc(sizeof(wchar_t) * (len + 1)); wcscpy_s(fileNames.sym, len + 1, FindFileData.cFileName);, как уже указал SomeProgrammerDude, но, возможно, вы ее пропустили.

john 23.12.2020 16:46

@john нет, это ничего не меняет, все еще ошибка нарушения прав доступа на printf("Current file: %ls", arr.str[i][j]); в printSA

Alfredison 23.12.2020 16:54

@ssbssa Вылетает на printf("Current file: %ls", arr.str[i][j]); в функции печати

Alfredison 23.12.2020 16:55

Возможно, проблема в объекте StringArray, но вы этого не опубликовали. На самом деле я думаю, что вам следует научиться пользоваться отладчиком. Кому-то еще сложно отлаживать ваш код, если они видят только его часть.

john 23.12.2020 16:57

@Alfredison Хорошо, проблема не в этом.

john 23.12.2020 16:59

Вместо этого попробуйте printf("Current file: %ls", arr.str[i]);, но удалите внутренний цикл for.

ssbssa 23.12.2020 17:00

@Alfredison Если вы не знаете, как использовать отладчик, то расставляйте операторы печати повсюду, в конце концов вы это отследите (хотя использование отладчика было бы намного быстрее).

john 23.12.2020 17:00

@ssbssa теперь даже показывает ucrtbased.pdb not loaded страницу

Alfredison 23.12.2020 17:04

@john Проблема в том, что его оператор печати дает сбой.

ssbssa 23.12.2020 17:05

@ssbssa Я только что понял, что пытался сравнить j со строкой. Я использовал тот же метод создания массива для массива int **, но эта строка содержала количество чисел в строке! Возможно, я неправильно скопировал свой собственный код!

Alfredison 23.12.2020 17:10

@ssbssa нет, он все еще вылетает именно из-за функции печати. Фу, я не такой уж и манекен

Alfredison 23.12.2020 17:13

Сбой оператора печати @ssbssa в одном месте не означает, что он будет сбой везде. На самом деле точка, в которой он начинает сбой, (вероятно) близка к точке, где произошло повреждение

john 23.12.2020 17:13
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
20
298
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий
fileNames.str = (wchar_t**)malloc(sizeof(wchar_t*) * fileNames.rows);

len = wcslen(FindFileData.cFileName)+1;
fileNames.sym = (wchar_t*)malloc(sizeof(wchar_t) * len);
wcscpy_s(fileNames.sym, len, FindFileData.cFileName);

Эта проблема существует в приведенных выше строках. Вы выделяете память для str, но не выделяете память для *str / str[0], что является типом wchar_t*. Затем вы копируете имя файла в fileNames.sym вместо fileNames.str[0], чтобы сразу не найти ошибку. Затем, если второй файл найден, вы выделяете память для fileNames.str[1] и копируете в него имя файла. Эта часть правильная.

Таким образом, исключение нарушения прав доступа происходит, когда вы пытаетесь получить доступ к содержимому fileNames.str[0], потому что это нераспределенная память. Если вы напечатаете fileNames.str[1], это будет успех.

Ниже приведена модифицированная версия, основанная на представленном вами коде. Меня устраивает. Вы можете попробовать.

#include <stdio.h>
#include <windows.h>

typedef struct StringArray
{
    wchar_t** str;
    int rows;
}StringArray;

void printSA(StringArray arr)
{
    printf("...........................\n");
    for (int i = 0; i < arr.rows; i++)
    {
        printf("Current file: %ls", arr.str[i]);
        printf("\n");
    }
}

int main()
{
    system("chcp 1251");

    WIN32_FIND_DATA FindFileData;
    HANDLE hf;

    hf = FindFirstFile(L"D:\\*.txt", &FindFileData);
    while (hf == INVALID_HANDLE_VALUE)
    {
        printf("Error opening files or no files found!\n Try changing the search directory or correct your input!\n");
        return 1;

        break;
    }

    StringArray fileNames;
    fileNames.rows = 1;
    int len;
    fileNames.str = (wchar_t**)malloc(sizeof(wchar_t*) * fileNames.rows);

    len = wcslen(FindFileData.cFileName) + 1;

    fileNames.str[fileNames.rows - 1] = (wchar_t*)malloc(sizeof(wchar_t) * len);
    wcscpy_s(fileNames.str[fileNames.rows - 1], len, FindFileData.cFileName);

    while (FindNextFile(hf, &FindFileData) != 0)
    {
        printf("Found file: %ls", FindFileData.cFileName);
        printf("\n");

        fileNames.rows++;

        fileNames.str = (wchar_t**)realloc(fileNames.str, sizeof(wchar_t*) * (fileNames.rows));
        int len = wcslen(FindFileData.cFileName) + 1;
        fileNames.str[fileNames.rows - 1] = (wchar_t*)malloc(sizeof(wchar_t) * len);
        wcscpy_s(fileNames.str[fileNames.rows - 1], len, FindFileData.cFileName);
    }
    FindClose(hf);

    printSA(fileNames);

    // TODO: Free pointers
    // ...

    system("pause");
    return 0;
}

Другие вопросы по теме