简体   繁体   English

为什么 malloc/calloc 无法将 memory 分配给结构数组中的某些成员?

[英]Why does malloc/calloc fail to allocate memory to certain members in an array of structures?

I want some function ( save() ) to get a pointer to array of structures dbEntry and fill it with data.我想要一些 function ( save() ) 来获取指向结构数组dbEntry的指针并用数据填充它。 This is where memory management issues come in.这就是 memory 管理问题出现的地方。

This is my code:这是我的代码:

Structure itself:结构本身:

typedef struct dbEntry {
          unsigned int id;
          char* type;
          char* name;
          unsigned int parent_id;
          unsigned char* md5;
} dbEntry;

Memory allocation and calling save() : Memory 分配和调用save()

int main(int argc, char const* argv[]){
          if (argc != 5) arg_error();

          if (strcmp(argv[1], "-s") == 0){
              FILE* database = fopen(argv[2], "wb");
              if (database == NULL) file_error();
              dbEntry* entries = malloc(150*sizeof(dbEntry*));
              for (int i=0; i<150; i++){
                  entries[i].id = 0;
                  entries[i].parent_id = 0;
                  entries[i].name = malloc(50*sizeof(char));
                  entries[i].type = malloc(10*sizeof(char));
                  entries[i].md5 = malloc(MD5_DIGEST_LENGTH*sizeof(unsigned char));
              }
              int entry_num = save(argv[4], 0, &entries);

save()

int save(char* dir_path, unsigned int parent, dbEntry** entries) {
          size_t path_len = strlen(dir_path);
          if (dir_path[path_len - 1] != '/') strcat(dir_path, "/");
          char dp_copy[path_len];
          strcpy(dp_copy, dir_path);
          DIR* dir = opendir(dir_path);
          struct dirent* dirent = readdir(dir);
          dirent = readdir(dir);
          dirent = readdir(dir);
          unsigned int id = 0;
          char* fpath;

          if (dirent == NULL) {
                  fprintf(stderr,
                          "Directory %s doesn't exist or can't be "
                          "opened. Check permissions\n",
                          dir_path);
                  exit(-1);
          }

          while (dirent != NULL) {
                  entries[id]->id = id;
                  strcpy(entries[id]->name, dirent->d_name);
                  entries[id]->parent_id = parent;

                  if (dirent->d_type == 8) {
                          strcpy(entries[id]->type, "file");
                          size_t len = strlen(dir_path)+strlen(dirent->d_name);
                          fpath = malloc(len);
                          strcpy(fpath, dir_path);
                          strcat(fpath, dirent->d_name);
                          FILE* file = fopen(fpath, "rb");
                          if (file == NULL){
                                  printf("Could not open file %s for reading\n", fpath);
                                  exit(-1);
                          }
                          md5digest(file, entries[id]->md5);
                          fclose(file);
                          printf("Saved %s\n", strcat(dir_path, dirent->d_name));

GDB output: GDB output:

57              while (dirent != NULL) {
(gdb) n
58                      entries[id]->id = id;
(gdb) n
59                      strcpy(entries[id]->name, dirent->d_name);
(gdb) n
60                      entries[id]->parent_id = parent;
(gdb) n
62                      if (dirent->d_type == 8) {
(gdb) n
63                              strcpy(entries[id]->type, "file");
(gdb) n
64                              size_t len = strlen(dir_path)+strlen(dirent->d_name);
(gdb) n
65                              fpath = malloc(len);
(gdb) n
66                              strcpy(fpath, dir_path);
(gdb) n
67                              strcat(fpath, dirent->d_name);
(gdb) p entries
$1 = (dbEntry **) 0x7ffffffee110
(gdb) p entries[0]
$2 = (dbEntry *) 0x8403490
(gdb) p entries[1]
$3 = (dbEntry *) 0x0
(gdb) p entries[2]
$4 = (dbEntry *) 0x8403260
(gdb) p entries[3]
$5 = (dbEntry *) 0xf625f4cc70b40b00
(gdb) p entries[4]
$6 = (dbEntry *) 0x7ffffffee220
(gdb) p entries[5]
$7 = (dbEntry *) 0x0
(gdb) p entries[6]
$8 = (dbEntry *) 0x8001890 <__libc_csu_init>
(gdb) p entries[7]
$9 = (dbEntry *) 0x7ffffeb51b97 <__libc_start_main+231>
(gdb) p entries[8]
$10 = (dbEntry *) 0x2000000000
(gdb) p entries[0]->name
$11 = 0x8403950 ".bash_history"
(gdb)

For some reason, it failed to allocate memory for entries[1] , entries[5] and some more, so the program returns Address boundary error when trying to reference entries[1] .由于某种原因,它未能为entries[1]entries[5]等分配 memory ,因此程序在尝试引用entries[1]时返回Address boundary error

Tried almost everything, but the issue persists.几乎尝试了所有方法,但问题仍然存在。 Looking for your help.寻求您的帮助。

You have two problems:你有两个问题:

  1. With

    malloc(150*sizeof(dbEntry*))

    you allocate memory for 150 pointers to dbEntry structures, not the dbEntry structures themselves.您将 memory 分配给 150个指向dbEntry结构的指针,而不是dbEntry结构本身。

    I recommend that you get the size of the data to allocate from the variable itself, as in:我建议您从变量本身获取要分配的数据大小,如下所示:

     dbEntry *entries = malloc(150 * sizeof *entries);
  2. In the save function the variable entries is essentially a pointer to an array of dbEntry structures .save function 中,变量entries本质上是一个指向dbEntry结构数组的指针。 You treat it as an array of pointers to structures (a pointer to an array is not the same as an array of pointers).您将其视为指向结构的指针数组(指向数组的指针与指针数组不同)。 You need to dereference the pointer to get the original pointer, which can then be dereferenced like an array of structures:您需要取消引用指针以获取原始指针,然后可以像结构数组一样取消引用:

     (*entries)[id].id = id;

    Or simply not pass it as a pointer to a pointer:或者干脆不将它作为指向指针的指针传递:

     // Note only one asterisk // v int save(char* dir_path, unsigned int parent, dbEntry* entries) {... entries[id].id = id; // Entries can be treated like a normal array of structures... }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM