【问题标题】:c program seg fault not making sense to me (c beginner)c程序段错误对我没有意义(c初学者)
【发布时间】:2013-05-14 00:08:58
【问题描述】:

这个程序可以编译,但是当运行时输出 find() 方法中的一些第一个打印语句,然后在 for 循环命中时发出 Segmentation fault:11

所以我尝试使用 gdb 进行调试,但无法找出问题所在。根据我从 gdb 收集的信息,由于 strstr() 方法之一发生了段错误。另外,我注意到程序在调用 find 方法中的 for 循环之前关闭。 为什么这个程序在运行时编译但崩溃了?

这是 gdb 的输出:

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

感谢所有帮助。我实际上是 C 的初学者,但我正在努力学习更多。

#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("-----------------------------------------------");
}

【问题讨论】:

    标签: c gdb segmentation-fault


    【解决方案1】:

    您正在使用NULL 指针调用match

    您将 NUM_STUFF 声明为 7(在 C 中应该是 #define NUM_STUFF 7),并且您的 STUFF 数组有 5 个字符串,因为缺少两个逗号

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

    (因为你忘记了逗号,而下一个标记是一个字符串,两行都连接在一个字符串中)

    我在 Linux 上通过indent-ing 你的代码发现了该错误,然后将其编译为gcc -Wall -g u1.c -o u1 并运行gdb u1 进行调试。

    你应该声明

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

    实际上,您应该添加NULL 终止数组的约定。 那么你会有:

    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
    };
    

    使用终止符NULL 编码可以更轻松地添加新句子。在这种情况下无需定义或更改NUM_STUFF

    那么你的主循环就是

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

    风格提示:我发现

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

    很难阅读。我个人更喜欢声明 typedef 来作为潜在指向函数的签名,即我更喜欢编码

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

    【讨论】:

    • 我试过了,但还是不行。不过,感谢您的时间和精力。
    • 什么不起作用?我发现两个缺少的逗号作为另一个答案!
    • 嗯,我也将不得不尝试您的解决方案,我猜想使用所有逗号,因为我只在一行上更正了逗号错误。请稍等...
    • 这个解决方案仍然有一些问题......您在一个初始化为特定大小的代码块中定义了数组,在下面的代码块中它没有初始化为任何大小,而是使用字符串值初始化
    • 是的,因为我提供了两个替代解决方案(带有小代码摘录,不是完整的作业)......以及关于它们的解释
    【解决方案2】:
     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"
    
    };
    

    你忘记了“,”,因为数据不够

    【讨论】:

    • 这行得通!哇,只要 gcc 说,“第 n 行缺少逗号”^o^
    • GCC 无法警告缺少逗号,因为将两个字符串文字一个接一个地放置是完全有效的(也是常见的做法)(例如,为了代码可读性,或通过宏扩展)。
    • 编译器不会抱怨像 "first" "second" 这样的写法,因为它是连接字符串的正确格式。写长字符串时有一个优点可以拆分。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-02-10
    • 1970-01-01
    相关资源
    最近更新 更多