2016-03-10 60 views
-3

我做了這個示例程序,代表了我的問題。 我想製作一個字符串列表,因爲在編譯時我將使用calloc/realloc 在運行時在堆上分配大小,因此將存儲在列表中的字符串總量未知。 我之所以使用函數來初始化,修改和釋放列表 是因爲在我的原始程序中有3個要創建的動態列表,所有3個都是字符串數組。 (),add_to_pathlist()和clear_pathlist()只是我在類似問題中發現堆棧溢出的代碼的包裝。C - 爲什麼動態數組無法正確初始化?

當它到達memcmp(element,array [i],MAXSTRLEN)時,我得到一個SIGSEGV錯誤,valgrind告訴我數組[i]未映射。爲什麼動態數組string_element沒有正確初始化? 注意:我嘗試用「** string_element」替換「* string_element」,並將所有調用從「& string_element」更改爲「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) 

感謝您的時間!

+0

C使用傳遞值。寫'marray = array;'對你傳遞給這個函數的任何參數沒有任何影響 –

+0

你可以在你得到原始代碼的地方引用** stackoverflow **問題嗎?我不斷看到執行崩潰的問題。 –

+0

'char * string_element;'必須是'char ** string_element'。假設這是爲了表示一個二維數組。 –

回答

1

約阿希姆Pileborg和M.M都添加正確的答案。

我將「* string_element」替換爲「** string_element」(並相應地修改了函數調用)並將「void init_list」替換爲「char ** init_list」,使其返回char **數組, !

非常感謝!