2015-09-28 58 views
-1

我想指針傳遞給字符指針的數組的函數,其中i要初始化它。初始化2D陣列的失敗(段錯誤)

然而,我的實現產生分段錯誤,我想不通爲什麼。誰能幫忙?

這是我的代碼:

#include<stdio.h> 
#include<string.h> 
#include<stdlib.h> 

void ret_2darr(char *(*str)[5]) 
{ 
    int i,j; 
    for(i=0;i<3;i++) 
    { 
     for(j=0;j<=5;j++) 
     { 
      str[i][j]=(char *)malloc(sizeof("sach")); 
      strcpy(str[i][j],"sach"); 
     } 
    } 
} 

main() 
{ 
    char *(*a)[5]=NULL; 
    ret_2darr(a); 
    int i,j; 
    for(i=0;i<3;i++) 
    { 
     for(j=0;j<=5;j++) 
     { 
      printf("%s",a[i][j]); 
     } 
    } 
} 
+6

調試器說什麼? – amdixon

回答

-1

在7號線應該是char *(* A)[5];不需要用NULL定義變量a。

+0

如果你編譯qwith gcc -Wall選項,它會給你:警告:'a'在這個函數中未初始化使用[-Wuninitialized] – LPs

+0

那麼所有其他的錯誤:sizeof(「sach」)'不足以strore那個字符串,等等...... – LPs

+0

@LPs:我用gcc -Wall執行上面的代碼,它沒有爲sizeof函數拋出任何錯誤。它給出正確的輸出。糾正我,如果我錯了... – Koushik

1

與調試諮詢,它說:

$ gcc -g test.c -o test 
$ gdb ./test 
GNU gdb (Ubuntu 7.7.1-0ubuntu5~14.04.2) 7.7.1 
Copyright (C) 2014 Free Software Foundation, Inc. 
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html> 
This is free software: you are free to change and redistribute it. 
There is NO WARRANTY, to the extent permitted by law. Type "show copying" 
and "show warranty" for details. 
This GDB was configured as "x86_64-linux-gnu". 
Type "show configuration" for configuration details. 
For bug reporting instructions, please see: 
<http://www.gnu.org/software/gdb/bugs/>. 
Find the GDB manual and other documentation resources online at: 
<http://www.gnu.org/software/gdb/documentation/>. 
For help, type "help". 
Type "apropos word" to search for commands related to "word"... 
Reading symbols from ./test...done. 
(gdb) run 
Starting program: /home/xand/code/stackoverflow/c/test 

Program received signal SIGSEGV, Segmentation fault. 
0x000000000040064a in ret_2darr (str=0x0) at test.c:26 
26  str[i][j]=(char *)malloc(sizeof("sach")); 
(gdb) print str 
$1 = (char *(*)[5]) 0x0 

這意味着ret_2darr當您嘗試訪問STR爲null。 空取消引用導致了段錯誤..

在回頭看STR如何定義並使用:

char *(*a)[5]=NULL; 

我們看到它是一個char ** [5](這是問題的開始)。

因爲我們只需要存儲的五根弦,這應該是作爲一個char * [5]。

糾正這個和流動問題上給出

其他修復

  • corrected main prototype and added flow on return 0..
  • redefined a properly
  • corrected bounds error <=5 goes to < 5 (two times)
  • removed malloc cast as redundant
  • added \n for proper printing..
  • added free(a[j]) to cleanup memory
  • handle allocation errors from malloc

調整代碼

#include<stdio.h> 
#include<string.h> 
#include<stdlib.h> 

int ret_2darr(char *a[5]); 

int main(void) 
{ 
    char *a[5]; 
    if(ret_2darr(a)) 
    { 
    // handle/log allocation errors here.. 
    return 0; 
    } 
    int i,j; 
    for(j=0;j<5;j++) 
    { 
    printf("%s\n",a[j]); 
    free(a[j]); 
    } 
    return 0; 
} 

int ret_2darr(char *str[5]) 
{ 
    int j; 
    memset(str, 5*sizeof(char *), 0); 
    for(j=0;j<5;j++) 
    { 
    str[j]=malloc(sizeof("sach")); 
    if(!str[j])goto err0; 
    strcpy(str[j],"sach"); 
    } 
    return 0; 

err0: 
    for(;j>=0;j--) 
    { 
    if(str[j])free(str[j]); 
    } 
    return 1; 
} 

輸出

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

參考

+0

「我們看到它是一個char ***(這是問題的開始)因爲我們只需要存儲一串字符串,所以它應該是char **」。啊,什麼?這是無稽之談。 2D數組不是指針指針,也不兼容。請更正,因爲我不想投下一個很好的答案。 – Lundin

2

考慮這個簡單的代碼:

int a = 0; 
func(a); 
... 

void func (int x) 
{ 
    x = 5; 
} 

此代碼不會修改變量a,因爲函數只修改了變量的副本,而不是它的實際內容。

指針或數組指針沒有區別,如果將指針傳遞爲指向其他位置的指針,則該指派僅在該函數內有效。所以你必須傳遞一個地址給指針。這是主要的錯誤:功能只會造成內存泄漏,你只有在分配的內存,這是因爲一旦函數返回忘記了臨時指針指向。

所以你將不得不通過地址傳遞數組指針...這是真正棘手的部分。您的選項要麼傳遞指向數組指針的指針,要麼返回數組指針。無論是會產生一些嚴重 C代碼:

void ret_2darr(char *(**str)[5]) // pass array pointer by reference 

char* (*(*ret_2darr)(void))[5]; // return array pointer from function 

不要寫這樣的代碼!這是一個難以理解的混亂。 typedef是唯一的解決方案。例如:

typedef char* arr_t[5]; // the array type 
arr_t* ptr; // a pointer to that array type 

其他錯誤:

  • 你居然從來沒有在任何地方分配的指針數組,你剛開始來分配陣列的項目,而不分配數組本身存在。

  • 您似乎想要一個二維數組,但您使用的是一維數組類型。數組指針應該是char *(*a)[3][5]

  • 您錯誤地訪問數組指針。 str[i][j]的意思是「在數組編號[i]中,給我一個子數組[j]」,你寧願在我的二維char *數組中給我「item [i] [j]」。再次,確定你應該擁有多少維度。

  • 您遍歷6項指標不是5等


我強烈建議只是爲了忘記完全數組指針,至少就爲函數關注。將實際的二維數組分配給調用者。改爲使用char* arr[3][5]作爲函數參數。