C - 为什么动态数组没有正确初始化?

时间:2016-03-10 12:44:45

标签: c string malloc

我制作了这个代表我的问题的示例程序。 我正在尝试创建一个字符串列表,因为在编译时我将使用calloc / realloc在列表中存储的字符串总数是未知的 在运行时在堆上分配大小。 我之所以使用函数来初始化,修改和释放列表 是因为在我的原始程序中有3个动态列表要创建,所有3个都是字符串数组。 init_pathlist(),add_to_pathlist()和clear_pathlist()只是我在类似问题的堆栈溢出中找到的代码的包装器。

当它到达memcmp(element,array [i],MAXSTRLEN)时,我得到一个SIGSEGV错误,valgrind告诉我array [i]是未映射的。为什么动态数组string_element没有正确初始化? 注意:我尝试替换" * string_element" by" ** string_element"并更改所有来自"& string_element" to" string_element"并得到了相同的结果。

我对内存管理还很陌生,真的会帮助你。 这是相关代码:

#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <stdlib.h>
size_t ARRSIZE = 1024;
size_t MAXSTRLEN = 1024;

void clear_list(char** array)
{
  int i;
  for(i = 0; i < ARRSIZE; i++)
    free(array[i]);
  free(array);
}

void init_list(char** marray)
{
  int i;
  char** array;
  array = calloc(ARRSIZE , sizeof(char*));

  for(i = 0; i < ARRSIZE; i++) {
    array[i] = calloc(MAXSTRLEN +1, sizeof (char));
    if (array[i] == NULL){
      perror("calloc");
      exit(1);
    }
  }
  marray = array;
}

void add_to_list(char* element, char** array, int pos)
{
  int i;
  int NEWSIZE;

  if(pos == ARRSIZE) {
    NEWSIZE = (ARRSIZE + 2) * 2;

    char **newptr = realloc(array, NEWSIZE * sizeof(*array));
    if (newptr == NULL){
      clear_list(array); 
      perror("realloc");
      exit(1);
    }
    ARRSIZE = NEWSIZE;
    array = newptr;
    for (i = pos; i < ARRSIZE; i++) {
      array[i] = calloc((MAXSTRLEN + 1) , sizeof (char));
      if (array[i] == NULL){
        perror("calloc");  
        exit(1);
      }
    }
  }
  strncpy(array[pos], element, MAXSTRLEN);
}


int testloop( char *element, char** array, int pos)
{
  int i;
  printf("Element to add: %s\n", element);
  for(i = 0; i < (pos -1); i++){
    if (memcmp(element, array[i], MAXSTRLEN) == 0)
      return 1;

  }
  add_to_list(element, array, pos);
  return 0;
}

int main(void)
{
  int loop_ret, position = 0;
  char element[100];
  char *string_element;

  init_list(&string_element);

  printf("Enter an element: \n");
  while(scanf("%s", element) != EOF) {
    loop_ret = testloop(element, &string_element, position);
    ++position;
    if (loop_ret == 0)
      continue;
    else if (loop_ret == 1) {
      printf("%s match one of string_element entries\n", element);
      exit(0);
    }
  }

  clear_list(&string_element);
  return 0;
}

以下是一个示例运行:

$ ./2d_char_array_funcparam 
Enter an element: 
bob
Element to add: bob
flo
Element to add: flo
Segmentation fault (core dumped)

这是valgrind告诉我的事情:

$ valgrind --track-origins=yes ./2d_char_array_funcparam
==8944== Memcheck, a memory error detector
==8944== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==8944== Using Valgrind-3.10.1 and LibVEX; rerun with -h for copyright info
==8944== Command: ./2d_char_array_funcparam
==8944== 
Enter an element: 
bob
Element to add: bob
==8944== Use of uninitialised value of size 8
==8944==    at 0x4C2E7BC: __strncpy_sse2_unaligned (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==8944==    by 0x400A97: add_to_list (2d_char_array_funcparam.c:58)
==8944==    by 0x400B2D: testloop (2d_char_array_funcparam.c:72)
==8944==    by 0x400B90: main (2d_char_array_funcparam.c:86)
==8944==  Uninitialised value was created by a stack allocation
==8944==    at 0x400B39: main (2d_char_array_funcparam.c:77)
==8944== 
==8944== Conditional jump or move depends on uninitialised value(s)
==8944==    at 0x4C2E7DC: __strncpy_sse2_unaligned (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==8944==    by 0x400A97: add_to_list (2d_char_array_funcparam.c:58)
==8944==    by 0x400B2D: testloop (2d_char_array_funcparam.c:72)
==8944==    by 0x400B90: main (2d_char_array_funcparam.c:86)
==8944==  Uninitialised value was created by a stack allocation
==8944==    at 0x400B39: main (2d_char_array_funcparam.c:77)
==8944== 
==8944== Conditional jump or move depends on uninitialised value(s)
==8944==    at 0x4C2E7F1: __strncpy_sse2_unaligned (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==8944==    by 0x400A97: add_to_list (2d_char_array_funcparam.c:58)
==8944==    by 0x400B2D: testloop (2d_char_array_funcparam.c:72)
==8944==    by 0x400B90: main (2d_char_array_funcparam.c:86)
==8944==  Uninitialised value was created by a stack allocation
==8944==    at 0x400B39: main (2d_char_array_funcparam.c:77)
==8944== 
==8944== Use of uninitialised value of size 8
==8944==    at 0x4C2E84C: __strncpy_sse2_unaligned (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==8944==    by 0x400A97: add_to_list (2d_char_array_funcparam.c:58)
==8944==    by 0x400B2D: testloop (2d_char_array_funcparam.c:72)
==8944==    by 0x400B90: main (2d_char_array_funcparam.c:86)
==8944==  Uninitialised value was created by a stack allocation
==8944==    at 0x400B39: main (2d_char_array_funcparam.c:77)
==8944== 
==8944== Conditional jump or move depends on uninitialised value(s)
==8944==    at 0x4C2E85B: __strncpy_sse2_unaligned (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==8944==    by 0x400A97: add_to_list (2d_char_array_funcparam.c:58)
==8944==    by 0x400B2D: testloop (2d_char_array_funcparam.c:72)
==8944==    by 0x400B90: main (2d_char_array_funcparam.c:86)
==8944==  Uninitialised value was created by a stack allocation
==8944==    at 0x400B39: main (2d_char_array_funcparam.c:77)
==8944== 
robert
Element to add: robert
==8944== Invalid write of size 1
==8944==    at 0x4C2E7BC: __strncpy_sse2_unaligned (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==8944==    by 0x400A97: add_to_list (2d_char_array_funcparam.c:58)
==8944==    by 0x400B2D: testloop (2d_char_array_funcparam.c:72)
==8944==    by 0x400B90: main (2d_char_array_funcparam.c:86)
==8944==  Address 0x747265626f72 is not stack'd, malloc'd or (recently) free'd
==8944== 
==8944== 
==8944== Process terminating with default action of signal 11 (SIGSEGV)
==8944==  Access not within mapped region at address 0x747265626F72
==8944==    at 0x4C2E7BC: __strncpy_sse2_unaligned (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==8944==    by 0x400A97: add_to_list (2d_char_array_funcparam.c:58)
==8944==    by 0x400B2D: testloop (2d_char_array_funcparam.c:72)
==8944==    by 0x400B90: main (2d_char_array_funcparam.c:86)
==8944==  If you believe this happened as a result of a stack
==8944==  overflow in your program's main thread (unlikely but
==8944==  possible), you can try to increase the size of the
==8944==  main thread stack using the --main-stacksize= flag.
==8944==  The main thread stack size used in this run was 8388608.
==8944== 
==8944== HEAP SUMMARY:
==8944==     in use at exit: 1,057,792 bytes in 1,025 blocks
==8944==   total heap usage: 1,025 allocs, 0 frees, 1,057,792 bytes allocated
==8944== 
==8944== LEAK SUMMARY:
==8944==    definitely lost: 8,192 bytes in 1 blocks
==8944==    indirectly lost: 1,049,600 bytes in 1,024 blocks
==8944==      possibly lost: 0 bytes in 0 blocks
==8944==    still reachable: 0 bytes in 0 blocks
==8944==         suppressed: 0 bytes in 0 blocks
==8944== Rerun with --leak-check=full to see details of leaked memory
==8944== 
==8944== For counts of detected and suppressed errors, rerun with: -v
==8944== ERROR SUMMARY: 2049 errors from 6 contexts (suppressed: 0 from 0)
Segmentation fault (core dumped)

谢谢你的时间!

1 个答案:

答案 0 :(得分:1)

Joachim Pileborg和M.M都添加了正确的答案。

我替换了&#34; * string_element&#34; to&#34; ** string_element&#34; (并相应地修改了函数调用)并替换了&#34; void init_list&#34; to&#34; char ** init_list&#34; ,让它返回char **数组,它的工作原理!

非常感谢你们!

相关问题