【问题标题】:Dynamic array of structs memory storage结构内存存储的动态数组
【发布时间】:2021-06-10 14:39:07
【问题描述】:

我正在尝试创建一个客户的动态数组,但我没有成功。这是我的代码。当我运行这段代码时,输​​出是


3
� H
3
4332
3
8939

我认为它正在打印内存的东西,但我不知道为什么。我把我的代码放在这里

int client_counter = 0;

typedef struct client
{
   char *pid;
   char *message;
}Client;


void store (Client * client_array, char *buf)
{  

   Client c;

   c.pid = strdup (strtok (buf, ":"));

   c.message = strdup (strtok (NULL, "\0"));

   client_array[client_counter++] = c;
}

int main () {
       
  Client* client_array = malloc (sizeof (struct client));

  char buf1[50] = { "1245:message" };
  store (client_array, buf1);
      
  char buf2[50] = { "4332:message" };
      
  store (client_array, buf2);
  char buf3[50] = { "8939:message" };
  store (client_array, buf3);


  for (int i = 0; i < client_counter; i++)
  {
     printf ("%d\n", client_counter);
     printf ("%s\n", client_array[i].pid);
  }

  return 0;
}

我已经尝试过使用这个:

    client_array = realloc(client_array, sizeof(struct client) * (client_counter + 1));

在此行之后的存储功能。

client_array[client_counter++] = c;

但它也不起作用。

【问题讨论】:

  • Re "就在这一行之后。",你应该分配内存before你需要它。另外,我怀疑您没有将realloc 返回的指针返回给main
  • 您有Client * client_arraychar *bufClient* client_array。我不在乎您是否在左侧、右侧或两者都放置空格,但选择一个并坚持下去!

标签: arrays c pointers


【解决方案1】:

如果空间不足,您需要分配额外的内存。现在,您为一个分配了足够的空间,但您尝试访问三个。

不要忘记将新内存块的指针返回给 main!在下文中,这是通过将指针传递给调用者的指针来完成的。 store通过传递的指针修改调用者的指针。

// Sets errno and returns 0 on error.
int store(Client ** client_array_ptr, char *buf) {  
   Client* new_client_array = realloc(*client_array_ptr, sizeof(Client) * (client_counter + 1));
   if (!new_client_array)
      return 0;

   *client_array_ptr = new_client_array;
   
   // ...

   new_client_array[client_counter++] = c;
   return 1;
}


int main() {
   Client* client_array = NULL;

   // ...

   if (!store(&client_array, buf1)) {
      perror("malloc");
      exit(1);
   }

   // ...

   if (!store(&client_array, buf2)) {
      perror("malloc");
      exit(1);
   }

   // ...

   free(client_array);
   return 0;
}

【讨论】:

  • 想象一下我添加了一个客户端并且知道我不再需要它,我怎样才能在不丢失其他客户端的情况下从阵列中释放它?
  • 您可以重新分配到较小的数字。但是,如果在要删除的元素之后有任何元素,则必须将它们复制下来。例如,如果有 4 个客户端并想删除第二个,则需要在缩小缓冲区之前将 2 复制到 1 并将 3 复制到 2。 (从技术上讲,您不必缩小缓冲区;最后有额外的空间不是问题。)
【解决方案2】:

原始代码会进行超出范围的访问,因为它试图将多个数据存储在仅分配给一个元素的缓冲区中。

要使用realloc(),您必须注意C 中函数的参数是所传递内容的副本。修改被调用函数内部的参数不会影响调用者传递的内容。您应该将指针传递给应该修改的内容,以使函数修改调用者的本地内容。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int client_counter = 0;

typedef struct client
{
   char *pid;
   char *message;
}Client;


void store (Client ** client_array, char *buf)
{  

   Client c;

   c.pid = strdup (strtok (buf, ":"));

   c.message = strdup (strtok (NULL, "\0"));

   *client_array = realloc(*client_array, sizeof(struct client) * (client_counter + 1));
   (*client_array)[client_counter++] = c;
}

int main () {
       
  Client* client_array = malloc (sizeof (struct client));

  char buf1[50] = { "1245:message" };
  store (&client_array, buf1);
      
  char buf2[50] = { "4332:message" };
      
  store (&client_array, buf2);
  char buf3[50] = { "8939:message" };
  store (&client_array, buf3);


  for (int i = 0; i < client_counter; i++)
  {
     printf ("%d\n", client_counter);
     printf ("%s\n", client_array[i].pid);
  }

  return 0;
}

【讨论】:

  • 你能解释一下这个“Client ** client_array”吗?
  • 它是一个指向Client*的指针。它用于将指向ClientClient*)数组的指针更新为新值。
  • Client* client_array = malloc (sizeof (struct client)); 可以简化为Client* client_array = NULL;。如果您只是要问realloc 以确保稍后分配它,那么在那里分配是没有意义的。
  • @MikeCAT 1. 任何重新分配错误都会导致内存泄漏。 2. 使用对象而不是sizeof 中的类型。 3 你从不检查分配结果。这是一个不应该做的例子。
【解决方案3】:

我会做一些不同的方式。

typedef struct
{
   char *pid;
   char *message;
}client_TypeDef;

typedef struct
{
    size_t size;
    client_TypeDef clients[];
}clients_TypeDef;

clients_TypeDef *add(clients_TypeDef *clients, const char *pid, const char *message)
{
    size_t newsize = clients ? clients -> size + 1 : 1;
    client_TypeDef client = {.pid = strdup(pid), .message = strdup(message)};

    if(client.pid && client.message)
    {
        clients = realloc(clients, sizeof(*clients) + newsize * sizeof(clients -> clients[0]));

        if(clients)
        {
            clients -> size = newsize;
            clients -> clients[newsize - 1] = client;
        }
    }
    else
    {
        free(client.pid);
        free(client.message);
        clients = NULL;
    }
    return clients;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-06-04
    • 2020-04-18
    • 2013-12-25
    • 2011-01-30
    • 1970-01-01
    • 1970-01-01
    • 2021-10-15
    相关资源
    最近更新 更多