【问题标题】:Can't find what's causing access violation in array在数组中找不到导致访问冲突的原因
【发布时间】:2021-04-02 05:12:08
【问题描述】:

!!!我必须坚持使用这些功能,因为我不允许使用任何不同的功能!!!

我需要做的一点解释:用户输入一个搜索目录,然后如果没有找到,则会弹出错误消息。如果找到某些东西,我会创建一个包含一行的数组,因为至少找到了一个文件,并且它会保存找到的文件的名称。然后,如果 FindNextFIle 找到任何东西,我将一行添加到现有数组中,并且这一新行保存新找到的文件名。

第一个输出是函数的直接输出,第二个是数组的测试输出,以确保它正常工作。然而,说内存访问被违反是行不通的,所以我不能进一步工作。

它不能正常工作的原因可能有两个:

  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&lt;std::wstring&gt; 而不是使用malloc 的低级C 样式编码?
  • 根据调试器在哪里崩溃?
  • arr.sym[i] 应该是什么?你为什么用它作为j &lt; arr.sym[i]?这没有任何意义。
  • 另外,你还记得 C++ 中的 C 风格字符串应该是null-terminated吗?
  • std::vector&lt;std::wstring&gt; fileNames; while (FindNextFile(hf, &amp;FindFileData) != 0) fileNames.push_back(FindFileData.cFileName); -- 这就是我们所需要的。

标签: c++ arrays c winapi jagged-arrays


【解决方案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;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2010-11-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-05-22
    • 2018-08-04
    • 1970-01-01
    相关资源
    最近更新 更多