2

Reading in a file, memory is dynamically allocated for a string where the file contents will be put. This is done inside of a function, the string is passed as char **str.

Using gdb I find that a seg fault is produced at the line **(str+i) = fgetc(aFile);

Here is the output of $ gdb a.out core along with the values of some variables:

Program terminated with signal SIGSEGV, Segmentation fault.
#0  0x0000000000400bd3 in readFile (aFile=0x994010, str=0x7ffd8b1a9338) at src/morse.c:59
59      **(str + i) = fgetc(aFile);
(gdb) print i
$1 = 1
(gdb) print **(str + 0)
$2 = 65 'A'
(gdb) print *(str + 0)
$3 = 0x994250 "A"
(gdb) print (str + 0)
$4 = (char **) 0x7ffd8b1a9338
(gdb) print **(str + 1)
Cannot access memory at address 0x0
(gdb) print *(str + 1)
$5 = 0x0
(gdb) print (str + 1)
$6 = (char **) 0x7ffd8b1a9340

Here is the relevant function:

int readFile(FILE *aFile, char **str) // puts a file into a string
{
  int fileSize = 0;
  int i = 0;

  // count the length of the file string
  while(fgetc(aFile) != EOF)
    fileSize++;

  // malloc enough space for the string
  *str = (char *)malloc(sizeof(char) * (fileSize + 1 + 1)); // one for null, one for extra space
  if(!(*(str)))
    printf("ERROR: *str == NULL\n");

  // rewind() to the start of the file
  rewind(aFile);

  // put the file into a string
  for(i = 0; i < fileSize; i++)
    **(str + i) = fgetc(aFile);
  **(str + i - 1) = '\0';

  return 0;
}

Why is it that it's possible to access the beginning of the memory (for lack of a better term) but not more? What is the difference between the seemingly contiguous memory at the ** level and the non-contiguous memory at the * level?

The rest of the code can be seen on GitHub here.

Cœur
  • 37,241
  • 25
  • 195
  • 267
Charles
  • 99
  • 2
  • 11
  • [Do not cast the return value of `malloc()`](http://stackoverflow.com/a/605858/1983495) and `sizeof(char) == 1` always. And for the size of the file you can do `ssize_t length; fseek(aFile, 0L, SEEK_END); length = ftell(aFile); rewind(aFile);` – Iharob Al Asimi Apr 18 '15 at 19:36

4 Answers4

7

It should be *(*str+i) instead of **(str+i). You have allocated memory to *str pointer.

B.Shankar
  • 1,271
  • 7
  • 11
1

In your code, the pointer to the allocated memory block is *str, not **str. Therefore, you want to set values of *((*str) + i), or, equivalently, (*str)[i].

John Bollinger
  • 160,171
  • 8
  • 81
  • 157
0

should be *(*str+i) , and you should be shot by the style police for using anything like this coding style in the first place.

use something mode like

char *myStr = *str = (char *) malloc ....

*myStr[i] = byte

....

ddyer
  • 1,792
  • 19
  • 26
0

@B. Shankar already gave you an answer, but I think I should point out some imporvements.

Unless you need to do it with pointer arithmetic, there is absolutely no need for all the loops in your code, you could just do it like this

int readFile(FILE *aFile, char **str) // puts a file into a string
{
  int fileSize;

  // count the length of the file string
  fseek(aFile, 0L, SEEK_END);
  fileSize = ftell(aFile);
  fseek(aFile, 0L, SEEK_SET);

  // malloc enough space for the string
  *str = malloc(fileSize + 1 + 1)); // one for null, one for extra space
  if (*str == NULL)
      return -1;    
  if (fread(*str, 1, fileSize, aFile) != fileSize)
      return -1;
  return 0;
}
Community
  • 1
  • 1
Iharob Al Asimi
  • 52,653
  • 6
  • 59
  • 97