consulting with debugger, it says :
$ 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
which means in ret_2darr
when you try to access str it is null.
null dereferencing is causing the segfault..
looking back at how str is defined and used :
char *(*a)[5]=NULL;
we see that it is a char **[5] ( this is the start of the problem ).
Since we only need to store an five strings, this should be as a char *[5].
correcting this and flow on issues gives
other fixes
- 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
adjusted code
#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;
}
output
$ 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)
reference