user_loser
user_loser

Reputation: 871

c program seg fault not making sense to me (c beginner)

This program compiles but when run outputs a few of the first print statements in the find() method then issues Segmentation fault:11 when the for loop hits.

So I tried debugging with gdb but could not figure out what the problem is. From what I gathered from gdb the seg fault occurs because of one of the strstr() methods. Also, I noticed that the program shuts-down right before the call to the for loop in the find method. Why does this program compile but crashes at run-time?

Here is the output from gdb:

Program received signal EXC_BAD_ACCESS, Could not access memory.
Reason: KERN_INVALID_ADDRESS at address: 0x0000000000000001
0x00007fff8d6469c4 in strstr ()
(gdb) 

Thanks for any and all help. I am a complete beginner practically with C, but I am trying to learn more.

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


int acdc_or_metallica(char *s);
int surfing_or_TV(char *s);
int exo_mustard(char *s);
int arts_theater_or_dining(char *s);

void find(int(*match)(char*));


int NUM_STUFF = 7;
char *STUFF[] = {

"Butthead likes ACDC and TV",
"Beavis likes Metallica and TV",
"Cartman likes to eat",
"Spiderman likes theater and working-out",
"Silver Surfer likes surfing and space",
"GunSword likes mustard and exoskeletons"
"Meatwad likes TV"

};


int main() 
{

find(acdc_or_metallica);
find(surfing_or_TV);
find(exo_mustard);
find(arts_theater_or_dining);

return 0;

}

int acdc_or_metallica(char *s)
{
return strstr(s, "acdc") || strstr(s, "metallica");
}

int surfing_or_TV(char *s)
{
return strstr(s, "surfing") || strstr(s, "TV");
}

int exo_mustard(char *s)
{
return strstr(s, "exoskeleton") && strstr(s, "mustard");
}

int arts_theater_or_dining(char *s)
{
return strstr(s, "arts") || strstr(s, "theater") || strstr(s, "dining");
}

void find(int(*match)(char*))
{
int i;
puts("Search results:");
puts("error below this line...");

puts("-----------------------------------------------");
for (i = 0;i < NUM_STUFF; i++) {
     if (match(STUFF[i])) {
        printf("%s\n", STUFF[i]);       
    }
}
puts("-----------------------------------------------");
}

Upvotes: 1

Views: 506

Answers (2)

You are calling match with a NULL pointer.

You declare NUM_STUFF as 7 (that should be a #define NUM_STUFF 7 in C), and your STUFF array has 5 strings, because of two missing commas

"Silver Surfer likes surfing and space", /* you forgot the comma */
"GunSword likes mustard and exoskeletons", /* you forgot the comma */

(since you forgot the comma and the next token is a string both lines are concatenated in one string)

I found that error on Linux by indent-ing your code, then compiling it as gcc -Wall -g u1.c -o u1 and running gdb u1 to debug it.

You should have declared

#define NUM_STUFF 7
char *STUFF[NUM_STUFF] = {

In fact, you should add the convention of a NULL terminated array. Then you would have:

char *STUFF[] = {
  "Butthead likes ACDC and TV",
  "Beavis likes Metallica and TV",
  "Cartman likes to eat",
  "Spiderman likes theater and working-out",
  "Silver Surfer likes surfing and space",
  "GunSword likes mustard and exoskeletons", 
  "Meatwad likes TV",
  NULL
};

Coding with a terminating NULL makes adding new sentences much easier. No need to define or change NUM_STUFF in that case.

Then your main loop would be

for (i = 0; STUFF[i] != NULL; i++)

A stylistic hint: I find

void find(int(*match)(char*));

quite difficult to read. I personally prefer declaring a typedef for the signature of potentially pointed functions, i.e. I prefer coding

typedef int matchfun_t (char*);
void find (matchfun_t*);

Upvotes: 4

BLUEPIXY
BLUEPIXY

Reputation: 40145

 char *STUFF[] = {

"Butthead likes ACDC and TV",
"Beavis likes Metallica and TV",
"Cartman likes to eat",
"Spiderman likes theater and working-out",
"Silver Surfer likes surfing and space",
"GunSword likes mustard and exoskeletons" //<---- , 
"Meatwad likes TV"

};

you forgot "," because data is not enough

Upvotes: 2

Related Questions