【问题标题】:Segmentation Fault in C?C中的分段错误?
【发布时间】:2013-06-20 21:40:37
【问题描述】:

我一直在尝试对计算器进行编程,但遇到了一个我无法修复的错误。一旦我输入要完成的计算,就会出现分段错误。我认为分段错误是内存不足,所以我尝试删除我的两个循环,假设它们是问题所在,但没有运气。

可能是我的 malloc 吗?

int calculator()
{
int exit = (int *)malloc(sizeof(int));
exit = 1;
while(exit == 1){

    printf("Welcome to the calculator, please enter the calculation you wish to make, if you wish to exit type EXIT\n");

    float *num1 = (float *)malloc(sizeof(float));
    float *num2 = (float *)malloc(sizeof(float));
    char operation = (char *)malloc(sizeof(char));
    float *ans = (float *)malloc(sizeof(float));
    char *string = (char *)malloc(10*sizeof(char));

    scanf("%s", &string);
    int result = strncmp(string, "EXIT", 10);

    if(result == 0){
        exit = 0;
    }
    else{
        //scanf("%f%c%f", &num1, &operation, &num2);
        int length = strlen(string);
        int i;
        for(i = 0; i <= length; i++){
            printf("forever");
            if(isdigit(string[i]) != 0){
                num1 = string[i];
            }
            else{
                operation = string[i];
            }
        }
        printf("num1%f\n", num1);
        printf("operation%c\n", operation);
        printf("num2%f\n", num2);

        if(operation == '+'){
            *ans = *num1 + *num2;
        }
        if(operation == '-'){
            *ans = *num1 - *num2;
        }
        if(operation == '/'){
            *ans = *num1 / *num2;
        }
        if(operation == '*'){
            *ans = *num1 * *num2;
        }
        if(operation == '^'){
            *ans = (float)pow(*num1,*num2);
        }

        printf("Your answer is %f\n", ans);

        }
}
return 0;
}

示例输出:

欢迎使用计算器,请输入您要进行的计算,如果您想退出输入EXIT 5+9 分段错误(核心转储) 进程返回 139(0x8B) 执行时间:2.611s

我使用 malloc 的原因是,当我退出 for 循环时,我分配给变量的值丢失了。虽然这并没有解决问题,但我觉得我的代码存在根本问题。

【问题讨论】:

  • 首先考虑scanf("%s", string);。正如凯尔所指出的,您的operation 分配既不需要也不建议(大部分情况都是如此)。 char operation; 不是指针类型,因此不需要分配。它是一个纯粹的堆栈变量。我建议一个关于指针和格式化输入过程的好教程。
  • 你能给我们一个示例输出吗?
  • 在这里使用 GDB 或 Valgrind 非常有帮助。
  • 如果你使用 GCC,你可以使用 -g 编译,然后使用 valgrind 查看失败的确切行。很可能是scanf("%s", &amp;string);,看看string 已经是一个指针了。
  • @ImreKerr 谢谢,这有效

标签: c segmentation-fault


【解决方案1】:
char operation = (char *)malloc(sizeof(char));

应该是

char operation; // you don't need to call malloc for a single byte

还有:

int exit = (int *)malloc(sizeof(int));

应该是

int exit;

事实上,你程序中的大部分数据都是用malloc 分配的,但也不是必须的。这些导致您的代码出现问题的原因是因为您分配了一个指向非指针变量的指针。

还有:

scanf("%s", &string);

应该是

scanf("%s", string); // string is already declared as a pointer

这很容易导致分段错误,因为您将用户输入的数据存储在指针的地址,而不是指针指向的分配空间。

这里也一样:

printf("Your answer is %f\n", ans);

应该是:

printf("Your answer is %f\n", *ans);

这里:

printf("num1%f\n", num1);
// should be 
printf("num1%f\n", *num1);

这里:

printf("num2%f\n", num2);
// should be 
printf("num2%f\n", *num2);

这里发生了什么?

num1 = string[i];

这是行不通的。当您将字符转换为 float 指针时,它会打印出垃圾。

这段代码的大部分问题是由于指针的无效使用造成的。我建议,至少在您修复错误时,您更改所有指向编译时数据的指针。您也没有在程序结束时释放数据。这会导致内存泄漏 - 另一个取消您对 malloc 的调用的原因。

也许暂时尽量避免一起使用指针。

还有:

我认为分段错误是内存不足

不是真的。当您尝试读取/写入内存中的无效位置时,会发生分段错误。这可能是由于我的 malloc 返回了一个空指针(可能是由于内存不足),但也可能是一些更可能的原因。

编辑:

这是您的程序的非指针示例:

#include <stdio.h>

int main (){

    char input[50];

    char operation = 0;
    float   num1 = 0.0f,
            num2 = 0.0f,
            ans  = 0.0f;

    printf ("Enter the calculation\n");

    scanf ("%f %c %f", &num1, &operation, &num2);

    if (operation == '+') printf ("The answer is %f\n", num1 + num2);

    return 0;
}

【讨论】:

  • 这是一个很好的答案,谢谢。看起来我完全误解了使用 malloc。我正在删除我的 malloc
  • 它发生了,我添加了一个示例。这个 calculator 程序在开始 C 类时非常常见,它们通常不涉及对 malloc 的调用
  • 我希望用户能够输入整个字符串,然后我想自己将其拆分为操作和数字。事实证明这很困难,所以我可能不得不回到这种方式。谢谢
  • 您可以使用scanf 轻松做到这一点。我更新了我的例子
  • 我最初是从那个开始的,想要合并退出位,这比它的价值要麻烦得多。有什么办法可以兼得吗?非常感谢您的帮助,谢谢。
【解决方案2】:

可能是这些台词

int exit = (int *)malloc(sizeof(int));
exit = 1;

如果您分配的是 (int *),则不要将其分配给 (int),因为这不是同一类型。

你可能想要

int exit = 1;

或者如果你真的想使用指针

int* exit = (int *)malloc(sizeof(int));
*exit = 1;

while (*exit == 0) {

通过分配

int exit = (int *)malloc(sizeof(int));

您有效地获取 malloc 返回的地址,然后将其转换为整数。然后,您通过在下一行将 exit 重新分配给 1 来永久丢失地址。由于地址现在永远丢失了,您有一些内存分配给您的程序,但不再可以从程序的代码中访问。这种事情称为内存泄漏,应该避免。

这意味着每次执行 malloc 时,将它与 free 配对通常是一个非常好的主意,如下所示:

/* near the beginning */
int* exit = (int *)malloc(sizeof(int));

... code ...

/* just after exit isn't used anymore */
free(exit);

【讨论】:

  • float* 也存在类似问题。赔率是你真的想要浮动。如果这样做是为了避免有关 scanf 的编译器警告,那么您更改了错误的位置。你真的应该改变 scanf 来获取变量的地址,比如 &exit (而不是改变变量的类型)。
【解决方案3】:

多个问题:

int exit = (int *)malloc(sizeof(int));
exit = 1;

如何将指针存储为整数??

改变它

int exit = 1;

不会再来了..!!

char operation = (char *)malloc(sizeof(char));

改变它

char* operation = (char *)malloc(sizeof(char));

字符串是一个指针,不要发送指向scanf()的指针。

scanf("%s", &string);

改变它

scanf("%s", string);

天哪,我不认为你想打印 ans 的地址:

printf("Your answer is %f\n", ans);

改变它

printf("Your answer is %f\n", *ans);

我不会谈论你代码的奇怪逻辑。首先解决致命问题。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-08-01
    • 1970-01-01
    相关资源
    最近更新 更多