C - 2D char指针数组realloc

时间:2015-11-22 02:01:06

标签: c arrays pointers

所以我有这段代码:

#include <stdio.h>
#include <stdlib.h>
void init_pointer_arr(void)
{
char *arr[1];
int command_count = 1;
int length_counter = 1;
int fixed_cols = 5;

int i, j;

// malloc -first- initialization of the array
*arr = malloc(sizeof(char) * 5);
if (arr == NULL) {
    printf("17:malloc NULL");
}

/**************************************DEBUG***************************/ 
// init with char 'a' for debug purpose
for (i = 0; i < command_count; i++)
{
    for (j = 0; j < length_counter*fixed_cols; j++)
    {
        arr[i][j] = 'a';
    }
}

// print
for (i = 0; i < command_count; i++)
{
    for (j = 0; j < length_counter*fixed_cols; j++)
    {
        printf("%c", arr[i][j]);
    }
}
\*************************************END DEBUG*******************/

printf("\nrealloc\n"); // DEBUG
// realloc
//arr = realloc(arr, sizeof(arr[0]));
arr[0] = malloc(sizeof(char) * 5);
arr[1] = malloc(sizeof(char) * 5);
if (arr == NULL) 
{
    printf("51:malloc NULL");
}

/***************Re init newly allocate space for DEBUG*********************/
// init newly allocated space
for (i = 0; i < command_count; i++)
{
    for (j = 0; j < length_counter*fixed_cols; j++)
    {
        arr[i][j] = 's';
    }
}
printf("s\n"); // DEBUG
// print
for (i = 0; i < command_count; i++)
{
    for (j = 0; j < length_counter*fixed_cols; j++)
    {
        printf("%c", arr[i][j]);
    }
}

\******************************END DEBUG*****************************/

}

int main() {
init_pointer_arr();
system("pause");
return 0;
}

我基本上想要用指针数组实现一个二维数组,但我一直得到错误:&#34;内存arround arr已损坏&#34;这个错误的来源是这两行:

    arr[0] = malloc(sizeof(char) * 5);
    arr[1] = malloc(sizeof(char) * 5);

我已经看过其他关于此的帖子,但似乎没有人像我想的那样解决这个问题,而且上面的代码编译得很好,没有任何警告。

我很遗憾,为什么会这样。任何帮助将不胜感激。 提前谢谢。

编辑〜一开始arr只有一行,但在某些时候(上面麻烦的代码)我想添加更多行,我也试过realloc(你可以在另一个注释中看到它与另一行2以上)。但是那里也没有运气。

2 个答案:

答案 0 :(得分:0)

<强>问题

  
      
  • 将char *数组存储在不允许扩展的堆栈上
  •   
  • 打印硬编码的行号(可能会改变)
  •   
  • 没有退出失败(例如malloc失败)
  •   
  • 内存泄漏(之后没有释放内存)
  •   
  • system(&#34; pause&#34;)是特定于窗口的
  •   

调整后的代码

#include <stdio.h>
#include <stdlib.h>
void init_pointer_arr(void)
{
/*  char *arr[1]; */
// store the char * s on the heap
  char **arr, **temp;
  int command_count = 1;
  int length_counter = 1;
  int fixed_cols = 5;

  int i, j;

// malloc storage for the char * s
  arr = malloc(command_count * sizeof(char *));
  if(!arr)
  {
    goto err0;
  }

//  malloc -first-
    arr[0] = malloc(sizeof(char) * 5);
  if (arr[0] == NULL) {
//    printf("17:malloc NULL");
    printf("%d:malloc NULL\n", __LINE__);
    // should return on failure :
    goto err1;
  }

//  init
//  you might want to put some \n in these printfs..
    for (i = 0; i < command_count; i++)
    {
      for (j = 0; j < length_counter*fixed_cols; j++)
      {
        arr[i][j] = 'a';
      }
    }

//  print
    for (i = 0; i < command_count; i++)
    {
      for (j = 0; j < length_counter*fixed_cols; j++)
      {
        printf("%c", arr[i][j]);
      }
    }


  printf("\nrealloc\n");
//    realloc
  command_count = 2;
  temp = realloc(arr, command_count * sizeof(char *));
  if(!temp)
  {
    goto err2;
  }
  arr = temp;
//  arr[0] has already been alloced, not necessary again
//  and will cause a leak
//  arr[0] = malloc(sizeof(char) * 5);
  arr[1] = malloc(sizeof(char) * 5);
  if (arr[1] == NULL) 
  {
    printf("%d:malloc NULL\n", __LINE__);
    goto err2;
  }


//  init newly allocated space
    for (i = 0; i < command_count; i++)
    {
      for (j = 0; j < length_counter*fixed_cols; j++)
      {
        arr[i][j] = 's';
      }
    }
  printf("s\n");
//    print
    for (i = 0; i < command_count; i++)
    {
      for (j = 0; j < length_counter*fixed_cols; j++)
      {
        printf("%c", arr[i][j]);
      }
    }

err3:
  free(arr[1]);
err2:
  free(arr[0]);
err1:
  free(arr);
err0:
  return ;
}

int main() {
  init_pointer_arr();
#if defined(_WIN32) || defined(WIN32)
  system("pause");
#endif
  return 0;
}

<强>输出

$ gcc -g test.c -o test
$ valgrind ./test
==3612== Memcheck, a memory error detector
==3612== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==3612== Using Valgrind-3.10.0.SVN and LibVEX; rerun with -h for copyright info
==3612== Command: ./test
==3612== 
aaaaa
realloc
s
ssssssssss==3612== 
==3612== HEAP SUMMARY:
==3612==     in use at exit: 0 bytes in 0 blocks
==3612==   total heap usage: 4 allocs, 4 frees, 34 bytes allocated
==3612== 
==3612== All heap blocks were freed -- no leaks are possible
==3612== 
==3612== For counts of detected and suppressed errors, rerun with: -v
==3612== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)

<强>参考

答案 1 :(得分:0)

指甲的象征性的一点就是你宣称arr是一个1 char *arr[0])的数组,但是你正在接近界限( arr[1])。

正如我之前在评论中提到的,错误数量的绝对数量表明您正在使用的资源不起作用。您应该考虑阅读并参加K&amp; R 2E的练习。它经过了试验和测试,通过成功教授成千上万的学生数十年来证明了这一点。

对于这个答案的其余部分,似乎可能有助于描述K&amp; R没有描述的相切的东西:在声明中利用VLA和优先级,向您展示为什么你的方向错误对这个。这应该证明为什么你应该花更多的时间磨斧子,所以说;在你削尖斧头之后,你的代码应该只有一行。那一行是:

char (*ptr_to_array)[y] = malloc(x * sizeof *ptr_to_array);

从技术上讲,你所描述的类型中有三个间接层:数组的两个维度(x和y轴,如果你愿意),一个维度是指向该类型的指针(z轴)。您可以使用typedef

轻松声明此类型
typedef char two_dimensional_array[42][11];
two_dimensional_array *ptr; // ptr is a pointer to two_dimensional_array.

这对于VLA来说效果不好,所以您需要知道替代方案。让我们从简单的事情开始:

char *array[42];

应该很明显,这是一个指针数组,因为我告诉过你它是。你怎么读它作为一个数组?将标识符读为X,然后将标识符右侧的部分读为Y,然后将标识符左侧的部分读为Z,并形成以下句子:

  X   is       Y     of   Z
array is an array 42 of char *

现在考虑一些更复杂的事情:

char *array_of_array[42][11];

我会将此作为练习留给那些希望测试他们理解的人。下面的评论,我会告诉你,你是否正确。如果你做对了,请删除你的评论,这样你就不会破坏下一个人......

在下面的示例中,您应首先阅读括号,因为括号表示优先级。它是相同的模式,但是递归应用,首先读取括号内的内容。

char (*ptr)[42][11];

你的眼睛应该像往常一样被吸引到ptr(建立X),并且在括号内的右手边没有任何东西,所以你的眼睛应该被吸引到{{1在括号内,表示它是一个指针。

然后你的眼睛应该按照我们之前建立的模式被吸引到括号外的右侧。那里有两个维数的阵列,它们从左到右阅读。因此指针(一维)指向具有两个维度的数组。

最后,你的眼睛应该被吸引到声明的最左边,以便在括号外读取该类型的其余部分。

我建议您在评论中描述您认为*的类型。

假设您正确理解了所有这些内容,以下内容应该很容易破译,并且似乎符合您的要求:

ptr