程序在关闭时崩溃

时间:2014-09-03 09:03:12

标签: c crash

所以,这是我第一次在这里发帖,我会尝试尽可能具体。 我必须为我的学校制作一个节目:

首先编写一个获取字符并返回的函数:

  1. 如果它是大写字母,则为同一字符。
  2. 大写字母,如果它是小写字母。
  3. 反斜杠(' \')如果是数字。
  4. 任何其他情况下的星号(' *')。
  5. 然后,使用您的函数,创建一个程序,使其成为一个字符串,并在该函数更改后重新打印它。在用户输入' QUIT'之前,它应该继续询问新的字符串,在这种情况下,它将打印“Bye!”#39;然后退出。

    这是我的代码:

    #include <stdio.h>
    #include <stdlib.h>
    
    char fnChange(char c)
    {
         if (c > 'a'-1 && c < 'z'+1)
              c = c - 32;
         else if (c > '0'-1 && c < '9'+1)
              c = '\\' ;
         else if ( c > 'A'-1 && c < 'Z'+1)
              c = c;
         else 
              c = '*';
         return c;
    }
    
    
    int main()
    {   
        int i, refPoint;
        char *str = (char*)malloc(10);
        //without the next one, the program crashes after 3 repeats.
        refPoint = str;
        while (1==1) {            
           printf("Give a string: ");
           str = refPoint;//same as the comment above.
           free(str);
           scanf("%s",str);
             if (*str == 'Q' && *(str+1) == 'U' && *(str+2) == 'I' && *(str+3) == 'T') {
               // why won't   if (str == 'QUIT')   work?
               free(str);
               printf("Bye!");     //after printing "Bye!", it crashes.
               system("pause");    //it also crashes if i terminate with ctrl+c.
               exit(EXIT_SUCCESS); //or just closing it with [x].
             }       
             printf("The string becomes: ");
             while (*str != '\0') {
               putchar(fnChange(*str));
               str++;
             }
          printf("\n");
        }
    }
    

3 个答案:

答案 0 :(得分:5)

free(str);
scanf("%s",str);

Big no-no,在释放后不允许使用动态分配的内存。最重要的是,你可以在循环中再次释放

这样做是未定义的行为。这几乎可以肯定是导致事故发生的原因。

其他几个问题。您可以使用<=代替<来提高代码的可读性,例如:

if  ((c >= 'a') && (c <= 'z')) ...

使用像32这样的 magic 数字几乎总是一个坏主意。如果您使用字母连续的编码(例如ASCII),则可以执行以下操作:

c = c - 'A' + 'a';

将大写变为小写。

)因为字母保证是连续的。

表达式toupper()不符合您的想法,因为tolower()不是字符串。相反,它是一个多字节字符文字。但是,即使isupper()也不会按照您的想法行事,因为在C中比较字符串的正确方法是:

islower()

答案 1 :(得分:4)

您的代码中有多个undefined behavior个案例。

首先,您指定一个指向整数变量的指针。那些并不是真正兼容的(例如,如果int的大小是32位且指针的大小是64位,那么会发生什么。)

然后在使用之前释放已分配的指针,从而写入未分配的内存。

稍后再次在同一指针上调用free

答案 2 :(得分:1)

这可能导致崩溃的原因有很多。按照您的代码顺序,或多或少:

free str然后对其进行扫描。一旦释放了内存,它就不再可用了。

然后是scanf:scanf("%s", str)。一旦有人在控制台输入一个包含10个或更多字符的字符串,就会输入未定义行为的领域,因为内存将被覆盖。

str分配给refpoint,反之亦然,应该为您提供大量编译器警告。您的一个变量是int,另一个是char *。在某些体系结构中,指针不适合int,并且一旦使用它,程序就会崩溃。

您的while循环递增str。如果没有来自refpoint的(危险)副本,您最终会尝试释放一个不是malloc结果的指针。这是未定义的行为,可能会崩溃。

顺便说一下:

请不要投射malloc的结果。它返回一个void *,在C中你可以为任何东西分配void *,不必要的强制转换会降低代码的可读性。施法意味着你做了一些不寻常的事情,并且这项任务不是。

你不能做str == 'QUIT'因为C编译器会比较字符串的地址 - 嗯,键入'QUIT'的效果是编译器相关的。它可能会将它与'Q'的字符值进行比较。即使使用str == "QUIT",它也会将指针str的值(即malloc返回的地址)与字符串“QUIT”的地址进行比较,该字符串将位于链接器的任何位置旨在存储它。 C不进行字符串比较,你必须使用strcmp