初始化动态分配的struct array

时间:2018-02-09 01:34:29

标签: c arrays pointers pthreads

我有一个动态分配的结构数组,' 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);
  }

然后,我需要通过&#39; buff&#39;使用pthread_create创建线程时,指针作为参数:

  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);
}

但是,当我打印&#39; buffer_ptr&#39;的值时从创建的线程(只有一个),对于 ODD user_num的数量,总是有一个元素的数组&#39; buff&#39;在 pthread_create语句之后给出了垃圾值!删除对pthread的调用后,在main本身中检查值时,它运行正常。

3 个答案:

答案 0 :(得分:4)

这一行

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(<type>),使用sizeof *variable,这更安全,因为 在撰写sizeof(<type>)时,更容易犯错误。

所以:

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,您无法访问该内存。

答案 1 :(得分:3)

这是错误的:

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?

答案 2 :(得分:1)

你有一个根本性的错误。

指针算术通过在指针类型的倍数中添加偏移量来工作,因此自己添加偏移量将无法正常显示。

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

有时候使用附加符号做指针算术是有道理的,但大多数时候它更容易编写索引符号。