Why Does This Program Cause a Segmentation Fault?

AI Thread Summary
The discussion revolves around debugging a C program that causes a segmentation fault when attempting to reverse strings read from a file. Key issues identified include improper memory allocation for new words and the use of string literals, which cannot be modified. The solution involves allocating memory for each string in the main function and copying the literals into this allocated space. Additionally, the function for reversing strings can be simplified by directly using the standard library function `strrev`. The user has also resolved file manipulation concerns for reading and writing the reversed strings.
gruba
Messages
203
Reaction score
1

Homework Statement


Write a program that reads strings(words) from a text file and copy the inverted words to another file (use the command line arguments). Form a new array of words b from original array a using the function
void formNewArray(char **a, char **b, int n, char* (*t)(char *));
where n is the number of words in array, and (*t) is the pointer to function for inverting a string.

Homework Equations


-File handling
-Pointers

The Attempt at a Solution


The following program gives SIGSEGV segmentation fault in function formNewArray():
Code:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>

void form_temp_array(char **a,char **b,int n,char* (*t)(char *))
{
  int i;
  for(i=0 ;i<n; i++)
  b[i]=(*t)(a[i]);
}

char* reverseWord(char *word)
{
  char *new_word;
  new_word=(char*)malloc(sizeof(strlen(word+1)));
  new_word=strrev(word);
  return new_word;
}

void print(char **arr,int n)
{
  int i;
  for(i=0; i<n; i++)
  printf("%s\n",arr[i]);
}

int main()
{
  char* a[]={"PROGRAMMING","CODING"};
  int n=sizeof(a)/sizeof(char**);
  char* b[n];
  printf("original words:\n");
  print(a,n);
  printf("reversed words:\n");
  form_temp_array(a,b,n,&reverseWord);
  print(b,n);
  free(reverseWord);
  return 0;
}
 
Last edited:
Physics news on Phys.org
rcgldr said:
In reverseWord(), allocate memory for new word

Code:
    char *new_word = malloc(strlen(word)+1);

In form_temp_array, just assign to b:

Code:
    b[i] =(*t)(a[i]));

rcgldr said:
In reverseWord(), allocate memory for new word

Code:
    char *new_word = malloc(strlen(word)+1);

In form_temp_array, just assign to b:

Code:
    b[i] =(*t)(a[i]));
 
Trying to edit my answer had problems so I deleted it. You can delete your prior post also if you want. The issue is in main: char *a[] points to literal strings, so they can't be reversed, as they could be in write-protected memory. Rather than allocate memory, copy, and reverse in reverseWord(), I thought it would be better to change main(), and allocate memory for each pointer in a and make copies of the literal strings. I used w[] as an array of pointers to the literal strings.

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

void form_temp_array(char **a,char **b,int n,char* (*t)(char *))
{
    int i;
    for(i=0 ;i<n; i++)
        b[i] = (*t)(a[i]);
}

char* reverseWord(char *word)
{
    return strrev(word);         /* or _strrev, depending on compiler */
}

void print(char **arr,int n)
{
    int i;
    for(i=0; i<n; i++)
        printf("%s\n",arr[i]);
}

int main()
{
    int i;
    char* w[]={"PROGRAMMING","CODING"};
    int n = sizeof(w)/sizeof(char**);
    char* a[n];          /* or    char** a = _alloca(n*sizeof(char*)); */
    char* b[n];          /* or    char** b = _alloca(n*sizeof(char*)); */
    for(i = 0; i < n; i++){
        a[i] = malloc(strlen(w[i])+1);
        strcpy(a[i], w[i]);
    }
    printf("original words:\n");
    print(a,n);
    form_temp_array(a,b,n,reverseWord);
    printf("reversed words:\n");
    print(b,n);
    for(i = 0; i < n; i++)
        free(a[i]);
    return 0;
}
 
Last edited:
  • Like
Likes gruba
I have updated the code, and there is still an error.
Also, I don't think that you can use operator = for string manipulation.
 
I updated my previous answer to show working code. The issue was that a pointed to literals, so I used an array called w, then in a, I allocated memory and copied the literal strings.
 
Several problems, the main being:
  • char *new_word = _strrev(word);
    return new_word;
The new_word pointer is a local variable in reverseWord and is not available outside that function (it is allocated on the stack and deallocated when the function returns).
 
Svein said:
Several problems, the main being:
  • char *new_word = _strrev(word);
    return new_word;
The new_word pointer is a local variable in reverseWord and is not available outside that function (it is allocated on the stack and deallocated when the function returns).
It doesn't matter, since what is being returned is the pointer to the string from strrev(), not a reference to new_word. Since strrev reverses in place, there's no point in using the returned value, but since it does return the pointer to word, the code can be simplfied to:

Code:
char* reverseWord(char *word)
{
    return strrev(word);
}
 
Last edited:
Svein said:
Several problems, the main being:
  • char *new_word = _strrev(word);
    return new_word;
The new_word pointer is a local variable in reverseWord and is not available outside that function (it is allocated on the stack and deallocated when the function returns).

That would be a problem if the function were returning a pointer to new_word. But it is returning the value. That value will be copied somewhere so it doesn't matter that new_word is lost.
 
rcgldr said:
It doesn't matter, since what is being returned is the pointer to the string from strrev(), not a reference to new_word. Since strrev reverses in place, there's no point in using the returned value, but since it does return the pointer to word, the code can be simplfied to:

Code:
char* reverseWord(char *word)
{
    return strrev(word);
}

It can be simplified further by having no reverseWord at all and simply passing a pointer to strrev as an argument.
 
  • #10
Hornbein said:
It can be simplified further by having no reverseWord at all and simply passing a pointer to strrev as an argument.
True, that would be better still. I wasn't sure if it would be OK to use a pointer to a library function for this class assignment. So in main(), it would be:

Code:
    form_temp_array(a,b,n,strrev);
 
  • #11
Assume that file1 contains original words, and is the first argument of a command line.
How to read the content of file1 and put the inverses to file2, which is the second argument of a command line?
 
  • #12
Thanks for all your help, I have figured out how to do file manipulation.
 

Similar threads

Replies
2
Views
2K
Replies
3
Views
1K
Replies
7
Views
2K
Replies
3
Views
1K
Replies
1
Views
4K
Replies
4
Views
1K
Replies
4
Views
2K
Back
Top