使用 malloced char 数组时无法创建文件

Cannot create a file when using malloced char arrays

我正在按照 this 文章使用标准 C 编写 PE 文件查看器。它非常简洁,但我对第一行有疑问:

#include "stdafx.h"
#include "Windows.h"
#include <iostream>

int main(int argc, char* argv[]) {
    const int MAX_FILEPATH = 255;
    char fileName[MAX_FILEPATH] = {0};
    memcpy_s(&fileName, MAX_FILEPATH, argv[1], MAX_FILEPATH);
    ...
}

如您所见,作者将 MAX_FILEPATH 定义为 255,但我不能这样做,因为我将给出的输入参数可能比它大。

我决定使用 malloc 进行动态内存分配,这样我就可以拥有一个自动调整大小的数组(确切的参数长度),并且还省去了 'memcpy_s' 函数:

#include <stdio.h>

#include "Windows.h"

#pragma warning (disable: 6011 6386 6387) // MSVC is giving me a headache.

int main(int argc, char *argv[]) {
    int length = strlen(argv[1]); // Yes, I only care for 1 input argument.
    char* path = malloc(length * sizeof(char));

    int i = 0;
    for (; i <= length; i++) {
        if (i < length) {
            path[i] = argv[1][i];
        }
        else {
            path[i] = '[=11=]';
        }
    }
    ...
}

我知道 'for cicle' 可能不是速度方面的最佳选择,但我还不担心。相反,我很担心,因为一切似乎都很好,但是当我到达代码的第二部分(即 HANDLE 的创建)时,它总是返回错误。

HANDLE file = CreateFileA(path, GENERIC_ALL, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);

if (file == INVALID_HANDLE_VALUE) {
    printf_s("Nope."); // Always throwing nopes.
}

你知道我做错了什么吗?也许我试图混合不同的数据类型或函数的方式...?

非常感谢您。

顺便说一下,如果您对我的 C 编码风格有任何建议,或者如果有什么不是真的 'C standard',请告诉我。

如果有人遇到同样的问题...

尝试运行你的程序作为管理员...这都是关于文件权限的。

除非有其他原因,否则不需要复制argv[1]你可以直接使用它:

#include <stdio.h>
#include <stdlib.h>
#include <Windows.h> // use normal include guards

int main(int argc, char *argv[])
{
    if (argc < 2){ // if the argument is not there the program would have undefined behavior
        fprintf(stderr, "Usage: <prog> <filename>\n");
        return EXIT_FAILURE;
    }
    
    HANDLE file = CreateFileA(argv[1], GENERIC_ALL, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
    //                        ^^^^^^^
    if (file == INVALID_HANDLE_VALUE) {
        printf_s("Nope."); // Always throwing nopes.
    }
    //...
}

无论如何你应该检查 argv[1] 是否真的存在,否则你的程序将有未定义的行为。

无论如何,如果你真的想复制,有更好的选择,这里是其中之一:

#include <stdio.h>
#include <stdlib.h>
#include<string.h> // maybe needed for strdup
#include <Windows.h> // use normal include guards


int main(int argc, char *argv[]) {

    if(argc < 2){ // if the argument is not there the program would have undefined behavior
        fprintf(stderr, "Usage: <prog> <filename>\n");
        return EXIT_FAILURE;
    }
    // allocates memory for the new string and duplicates it
    char* path = _strdup(argv[1]); // MSVC can complain about POSIX strdup()
    //...
    // you'll need to free path
}

使用正确的数组大小,您仍然可以使用 memcpystrcpy 库函数之一或其变体之一:

int length = strlen(argv[1]) + 1; // account for null byte
char *path = malloc(length); // sizeof char is always 1 byte
memcpy_s(path, length, argv[1], length); // path is already pointer, removing &

请注意,在您的代码中,filename 作为参数传递时会衰减为指向其第一个元素的指针,因此您还应该删除 &.

或者简单地使用一个指针:

char *path = argv[1];

尽管指针选项与直接使用 argv[1] 基本相同,如第一个代码所示。

如果还有其他与字符串无关的问题,GetLastError()会帮你查明是什么问题。