2015-09-28 60 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]作为函数参数。