【问题标题】:Garbage value even after initializing members of dynamically allocated struct array即使在初始化动态分配的结构数组的成员之后也是垃圾值
【发布时间】:2018-02-09 01:34:28
【问题描述】:

我有一个动态分配的结构数组“buff”。每个元素都是一个结构,它有几个整数变量和一个指针“buffer_ptr”,它指向另一个动态分配的结构数组。两个数组的大小作为命令行输入给出。

int buffer_size;
int user_num;
struct tuple
{
  char userID[5];
  char topic[16];
  int weight;
};
struct buff_ctrl    
{
  struct tuple* buffer_ptr;
  int in;
  int out;
  int numItems;
  int done;
};

数组在 main() 中创建和初始化如下:

int main(int argc, char* argv[])
{
  void *status;
  pthread_t mapThd;
  if(argc != 4)
  {
    printf("Input format: ./combiner <buffer_size> <number_of_users> <input_file>\n");
    return -1;
  }
  buffer_size = atoi(argv[1]);
  user_num = atoi(argv[2]);
  struct buff_ctrl *buff = (struct buff_ctrl*)malloc(user_num * sizeof(struct buff_ctrl)); 
  for(int i=0; i<user_num; i++)
  {
    struct buff_ctrl* curr_buff = (buff + (i*sizeof(struct buff_ctrl)));
    struct tuple *ptr = (struct tuple*)malloc(buffer_size * sizeof(struct tuple));
    curr_buff->buffer_ptr = ptr;//points to another array
    curr_buff->in = 8;
    curr_buff->out = 4;
    curr_buff->numItems = 7;
    curr_buff->done = 0;
    printf("%p\n",curr_buff);
  }

然后,我需要在使用 pthread_create 创建线程时将“buff”指针作为参数传递:

  pthread_create(&mapThd, NULL, mapper, (void*)buff);
  pthread_join(mapThd, &status);
  free(buff);
  /*end of main*/

我的函数指针如下:

void* mapper(void *buff)
{
  struct buff_ctrl* arr = (struct buff_ctrl *)buff;
  struct buff_ctrl* temp_ptr;
  printf("######################################################\n");
  for(int k=0; k<user_num; k++)
  {
    /*Printing just to check values */
    temp_ptr = arr + (k*sizeof(struct buff_ctrl));
    printf("buffer ptr =  %p\n", temp_ptr->buffer_ptr);
    printf("in =  %d\n", temp_ptr->in);
    printf("out =  %d\n", temp_ptr->out);
    printf("numItems =  %d\n", temp_ptr->numItems);
  }
  printf("######################################################\n");
  pthread_exit((void*)buff);
}

但是,当我从创建的线程(只有一个)打印“buffer_ptr”的值时,对于 ODD 个 user_num,数组“buff”中总是有一个元素会产生垃圾value pthread_create 语句之后!删除对 pthread 的调用后,在 main 中检查值时,它运行良好。

【问题讨论】:

  • 第一个问题很好。

标签: c arrays pointers pthreads


【解决方案1】:

这一行

struct buff_ctrl* curr_buff = (buff + (i*sizeof(struct buff_ctrl)));

应该是

struct buff_ctrl* curr_buff = buff + i;

buff + i 是指针运算,编译器已经占用了 buff 指向的对象考虑在内。通过执行i*sizeof(struct buff_ctrl),您正在分配 可能在分配的内存之后的指针。

一般建议:

不要投射malloc。而不是使用sizeof(&lt;type&gt;),而是使用sizeof *variable,这样更安全,因为 写sizeof(&lt;type&gt;)更容易出错。

所以:

struct buff_ctrl *buff = malloc(user_num * sizeof *buff);

...

struct tuple *ptr = malloc(buffer_size * sizeof *ptr);

而且你不需要声明一个单独的指针,你可以这样做:

for(int i=0; i<user_num; i++)
{
    buff[i].buffer_ptr = malloc(buffer_size * sizeof *buff[i].buffer_ptr);
    buff[i].in = 8;
    buff[i].out = 4;
    buff[i].numItems = 7;
    buff[i].done = 0;
}

您还应始终检查malloc 的返回值。如果它返回 NULL,您无法访问该内存。

【讨论】:

  • 哇。那只比我早 8 秒。
  • @IharobAlAsimi 对我来说正好相反,当我按下“添加答案”时,我看到了你的答案。
  • 是的,事实上,按“oldest”排序显示我是这个问题的第一个答案。我认为这很明显造成了问题,我立即意识到了这一点。
  • @IharobAlAsimi 是什么导致了问题?
  • 这个struct buff_ctrl *buff = malloc(user_num * sizeof *buff);和其他类似的。
【解决方案2】:

这是错误的:

struct buff_ctrl* curr_buff = (buff + (i*sizeof(struct buff_ctrl)));

当你做指针运算时,它以指针指向的大小为单位进行运算,所以你不需要乘以sizeof。结果,您实际上是乘以两次并在数组边界之外访问。

只需将buff 视为一个数组,而不是处理指针。

  for(int i=0; i<user_num; i++)
  {
    struct tuple *ptr = malloc(buffer_size * sizeof(struct tuple));
    buff[i].buffer_ptr = ptr;//points to another array
    buff[i].in = 8;
    buff[i].out = 4;
    buff[i].numItems = 7;
    buff[i].done = 0;
  }

另外,请参阅Do I cast the result of malloc?

【讨论】:

    【解决方案3】:

    你有一个根本性的错误。

    指针算术通过将偏移量添加到指针类型的倍数中来工作,因此您自己添加偏移量不会像您显然期望的那样工作。

    如果它是char * 指针,那么您需要手动添加偏移量,增量将乘以一。但在您的情况下,n 的增量乘以指针基类型的大小。

    有时使用加法表示法进行指针算术是有意义的,但大多数情况下使用索引表示法会更清晰。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-01-15
      • 1970-01-01
      • 2021-08-25
      • 2015-07-23
      • 1970-01-01
      • 2020-12-17
      • 2023-03-11
      • 1970-01-01
      相关资源
      最近更新 更多