使用 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
}
使用正确的数组大小,您仍然可以使用 memcpy
或 strcpy
库函数之一或其变体之一:
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()
会帮你查明是什么问题。
我正在按照 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
}
使用正确的数组大小,您仍然可以使用 memcpy
或 strcpy
库函数之一或其变体之一:
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()
会帮你查明是什么问题。